I'm building a small eCommerce app in React Native and when the customer adds something to their cart I want to display a "View cart" TouchableOpacity at the bottom of the screen until they clear the cart.
This is what I'm returning on each page, along with styling:
return (
<TouchableOpacity
style={styles.cartView}
onPress={() => navigation.navigate('View Cart')}>
<Text style={styles.cartText}>View cart</Text>
</TouchableOpacity>
);
cartView: {
justifyContent: 'center',
alignItems: 'center',
maxHeight: 50,
minWidth: '100%',
alignSelf: 'center',
marginTop: 50,
backgroundColor: '#373F51',
padding: 10,
top: 40,
borderRadius: 20,
},
When I'm on a page that isn't scrollable this works fine and it appears right above the tab navigator. However, when I try and render this on a scrollable page, like one with a FlatList, things get messy. It either lays directly on top of the component below it or you'll have to scroll to the bottom of the screen to see it if it's placed at the bottom of the component tree.
How can I change my styling so that it renders at the bottom of the page and stays there in one spot (I'm fine with it covering the content behind it)?
You may try to refer to this article.
The main concept is using position: 'absolute' and bottom: 0 to do the trick. This will force component render by absolute position instead of flex.
I want to arrange the material top tab navigator name in a single line.
The first tab name is lengthy here, so it displays in two lines. Like this (img_1).
img_1
But I want to convert the name to a single line. Like this (img_2).
img_2
I suggest you to try this.
<Tab.Navigator
screenOptions={{
tabBarItemStyle: {
width: 'auto',
minWidth: '100',
alignItems: 'center',
},
}} >
I have a View like this
<View style={styles.columnView}>
<View style={[styles.columnButtonItem, styles.columnC]}><Text></Text></View>
<View style={[styles.columnButtonItem, styles.columnA]}><Text></Text></View>
<View style={[styles.columnButtonItem, styles.columnB]}><Text></Text></View>
<View style={[styles.columnButtonItem, styles.columnE]}><Text>{value}</Text></View>
<View style={[styles.columnButtonItem, styles.columnAs]}><Text></Text></View>
<View style={[styles.columnButtonItem, styles.columnT]}><Text></Text></View>
</View>
After iterations, I compose a table like this:
There is a way to add ScroolView on a single column?
For example, I want to enable scroll only on columnE.
Obviously, when i scroll columnE I want to scroll all the table.
Thanks
Absolutely positioned Views
If you know the width of the columns then you could use Views that are absolutely positioned that overlap the underlying ScrollView, they would stop all touches to the ScrollView. Meaning that it would only scroll on the part that isn't covered by the absolutely positioned views.
So you could do something like this
render() {
// set these widths to be the size before row E and the size after row E
let leftWidth = '33%';
let rightWidth = '33%';
return (
<View style={{flex: 1}}>
<ScrollView style={{flex: 1}}>
// items for the scroll view go here
</ScrollView>
<View style={{position:'absolute', top:0, left: 0, bottom: 0, width: leftWidth}} />
<View style={{position:'absolute', top:0, right: 0, bottom: 0, width: rightWidth}} />
</View>
)
}
Snack
Here is a snack showing this implementation. I have set a backgroundColor on the absolutely positioned views so that you can clearly see them.
https://snack.expo.io/#andypandy/partial-scrollview
Caveat
The main problem with this solution is that you will not be able to touch anything that is below the absolutely positioned views. You could mitigate that by capturing touches using gestures on each View and then mapping them to positions on the ScrollView.
I (think) this is what you're looking for... essentially you can only scroll the far right column and the rest of the columns are not scrollable. Because of that, you have to wait for the native event handler of ScrollView to propagate any change before you render the fact that the rest of those 4 columns are scrolling though.
https://snack.expo.io/#vincentvella/scroll-example
I have a ScrollView which content doesn't necessarily exceeds it's size. Let's say it's a form where, upon errors, it expands to add error messages and then it exceeds the ScrollView size and thus is why I'm using that scroll.
The thing is that I want the content to always be at least of the same size of the ScrollView. I'm aware of the minHeight property, but the only way I found to use it is re-rendering, which I'd like to avoid.
I'm using redux for state management and this is what I have
<ScrollView
contentContainerStyle={[ownStyles.container, {minHeight: this.props.scrollHeight}]}
style={this.props.style}
showsVerticalScrollIndicator={false}
onLayout={(event) => {
scrollHeight = event.nativeEvent.layout.height;
this.props.setScrollContentHeight(scrollHeight);
}}
>
Where the this.props.setScrollContentHeight triggers an action which enters the height on the state, and this.props.scrollHeight is said height. So that after the first render where the onLayout function is triggered, the state is updated with the ScrollView's height, which I then assign as minHeight to its content.
If I set the content's style to flex: 1 then the ScrollView won't scroll.
Can you think of a way to avoid that second render for performance purposes?
Thank you!
You should use flexGrow: 1 for the ScrollView and flex: 1 inside the ScrollView, to get a ScrollAble but at least as big as possible <View>.
There has been a discussion about it in react-native and tushar-singh had the great idea to it.
It has been a long time but I struggled with the same issue. The easy way to do it is to use flexGrow: 1 instead of flex:1 on both scrollView's style and contentContainerStyle props. The content will take at least 100% of space and more if needed.
A couple of solutions of doing this are:
Use a minHeight on the ScrollView (but this requires taking into account the screen dimension to render correctly)
Use a flexGrow: 1 on the ScrollView contentContainerStyle and a flex: 1 to the inner content:
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
<View style={{ flex: 1 }}>
...
</View>
</ScrollView>
i want to share my solution, for me nothing of https://github.com/facebook/react-native/issues/4099 worked. Also i cannot comment there because facebook blocked the thread ¬.¬ !
Basically my solution is set flexGrow: 1 in contentContainerStyle on the ScrollView component, and wrap all the content inside in a View component with a height property setted with the screen size. Here the example code:
import { Dimensions } from "react-native";
let screenHeight = Dimensions.get('window').height;
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
<View style={{height: screenHeight}}>
... your content here ...
</View>
</ScrollView>
I know this is a little late, but I think wrapping the contents inside of that ScrollView with a View with minHeight style property will do the trick.
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
<View style={{ flexGrow: 1 }}>
Your content
</View>
</ScrollView>
That worked for me.
The Text input is center aligned, how to fix this text input so that it takes input from top left corner
Here is my css for text input:
/* The Text input is center aligned, how to fix this text input so that it takes input from top left corner */
input: {
flex: 1,
padding: 4,
marginRight: 1,
marginTop: 5,
fontSize: 18,
borderWidth: 1,
borderRadius: 4,
borderColor: '#E6E5ED',
backgroundColor: '#F8F8F9',
justifyContent: 'flex-start',
height: 150
}
I had the same issue, but the above notes didn't solve it. There's an android-only style property textAlignVertical that fixes this issue on multiline inputs.
i.e. textAlignVertical: 'top'
TextInput has default padding, override it by setting:
paddingTop: 0,
paddingBottom: 0
Github Issue
I have found the solution that in Android, TextInput style textAlignVertical: 'top' works. but in ios, TextInput prop multiline={true} works.
The Above Answers either give the for iOS or android, which can be quite misleading so this fixes it for both of the platfoms.
<TextInput
style={{
flex: 1,
width: "100%",
height: 150,
color: "#FFF",
textAlignVertical: "top", // android fix for centering it at the top-left corner
}}
multiline={true} // ios fix for centering it at the top-left corner
numberOfLines={10}
/>
For Android -
style={{
//...
flex:1,
textAlignVertical: "top", // android fix for centering it at the top-left corner
//...
}}
For iOS, add
multiline={true}
to the <TextInput/> component
Give textAlignVertical : "top" that will solve your issue.
<TextInput placeholder="Your text post" multiline={true} numberOfLines={10}, maxLength={1000} style={{ borderWidth: 1, backgroundColor: "#e3e3e3", textAlignVertical : "top" }} />
I had a similar use case in my iOS app, wherein the TextInput's height was 100 and the placeholder was showing in middle. I used multiline={true} and it made the text appear from the top.
It worked for me (RN 0.61.5):
<TextInput style={{textAlignVertical:'top', paddingTop: 0, paddingBottom:0 }} />
Update 2015-07-03: multiline text inputs have now been merged:
https://github.com/facebook/react-native/pull/991
The multiline examples that ship with React Native in the UI Explorer should work as documented.
The problem you'll have is that multiline TextInput aren't working correctly yet, and the docs are misleading. Please see this Github issue:
https://github.com/facebook/react-native/issues/279
"We haven't ported that functionality to open source yet."
There is some code in that issue that gives minimal multiline functionality, so you might be able to get it working with that.
Just Incase you are looking for code:
<TextInput
placeholder={'comment goes here!'}
multiline
style={{textAlignVertical:'top', ...otherStyle}}
/>
import { Dimensions} from 'react-native';
const screenWidth = Math.round(Dimensions.get('window').width);
const screenHeight = Math.round(Dimensions.get('window').height);
// ...
intext: {
height:screenHeight - 10,
textAlignVertical: 'top',
fontSize:17,
padding:12,
fontFamily:'courier',
margin:10,
},
I found out per element inspector, that for iOS there is a paddingTop: 5 for multiline TextInputs. This was still applied even though I set paddingVertical: 15 for all of my inputs. The result was a not centered text in multiline inputs on iOS. The solution was to additionally add a paddingTop: 15 if the TextInput is multiline and the platform is iOS.
Now there is visually no difference between single line and multiline inputs on both platforms, Android and iOS.
I think it's default for iOS, for android in my case adding paddingVertical: 0, to text style worked.
Apparently the solution for iOS is not as trivial as one might think.
While on Android you can just add this style:
paddingTop: 0,
paddingBottom: 0,
On iOS you'd need this:
multiline={true}
But what if you want a single line? This is my workaround:
<TextInput
value={comment}
onChangeText={setComment}
{/*The lines below are the important ones*/}
multiline={true}
blurOnSubmit={true}
autoCorrect={false}
onSubmitEditing={handleOnSubmit}
/>
Let me explain what's happening here:
As we said, multiline={true} vertically aligns the text.
To avoid adding a new line after pressing the submit button, you need blurOnSubmit={true}. This also closes the keyboard and although in my case that's ok, I haven't figured a way around it, unfortunately.
I used autoCorrect={false} because without it, the submit button will change the TextInput's value to the automatically selected suggestion (if any).
Finally, if you want to perform some action when the submit button is pressed, then you need onSubmitEditing={handleOnSubmit}.
What a journey to just align a text...
To get text aligned vertically center on both platforms use:
For android use textAlignVertical: "center"
For ios use justifyContent: "center"