React native, children of ScrollView wont fill full height - flexbox

So I have a horizontal scrollview at the top of the view. The ScrollView contains nodes that have a specified width. I then have a border on the bottom of the ScrollView, like you can see in this screen cap: http://i.imgur.com/pOV1JFP.png
As you can see the child nodes of the ScrollView at the top don't reach the border. However, if I change the ScrollView to a View with flexDirection: 'row', then the child nodes fill the height fine. I've tried changing a few properties on the scrollview, such as:
Setting padding:0 on contentContainerStyle
automaticallyAdjustContentInsets={false}
Changing the values of contentInsets directly
None of those seem to fix the issue.
The scrollview code & style:
var styles = StyleSheet.create({
nav: {
padding: 0,
marginTop: 30,
flex: 1,
borderBottomWidth: 1,
borderColor: '#000000'
}
});
<ScrollView
style={[{width: screen.width}, styles.nav]}
horizontal={true}
showsHorizontalScrollIndicator={true}
automaticallyAdjustContentInsets={false}>
{dayNavItems}
</ScrollView>
The child components (makes up dayNavItems)
const styles = StyleSheet.create({
container: {
paddingLeft: 15,
paddingRight: 15,
width: 50,
justifyContent: 'center'
},
odd: {
backgroundColor: '#ccc'
},
selected: {
backgroundColor: '#39b54a'
},
text: {
fontFamily: 'Optima'
}
});
class DayNavItem extends React.Component {
static propTypes = {
day: React.PropTypes.object.isRequired,
odd: React.PropTypes.bool,
selectDay: React.PropTypes.func.isRequired,
selected: React.PropTypes.bool
};
render() {
const d = new Date(this.props.day.created_at);
const viewStyles = [styles.container];
if (this.props.selected) {
viewStyles.push(styles.selected);
} else if (this.props.odd) {
viewStyles.push(styles.odd);
}
return (
<TouchableOpacity style={viewStyles} onPress={() => this.props.selectDay(this.props.day.uuid)}>
<View>
<Text style={styles.text}>{getMonth(d)}</Text>
<Text style={styles.text}>{d.getDate()}</Text>
</View>
</TouchableOpacity>
);
}
}

Adding contentContainerStyle={{flexGrow: 1}} will do the trick.
<ScrollView contentContainerStyle={{flexGrow: 1}}>
</ScrollView>

There is a property called contentContainerStyle for ScrollView. I just solved a similar issue where I set flex: 1 to the ScrollView's styles, ScrollView's contentContainerStyle, and the child View component.

The other answers are correct, but just to provide a clarifying example:
<ScrollView contentContainerStyle={{ flex: 1 }}>
{children}
</ScrollView>

Setting flex: 1 for ScrollView's contentContainerStyle property did the trick for me.

I always end up creating this component in all my projects:
import * as React from 'react'
import { ScrollView, ScrollViewProps, StyleSheet } from 'react-native'
export function FullHeightScrollView(
props: {
children: React.ReactNode
} & Omit<ScrollViewProps, 'contentContainerStyle'>
) {
return (
<ScrollView contentContainerStyle={styles.grow} {...props}>
{props.children}
</ScrollView>
)
}
const styles = StyleSheet.create({
grow: { flexGrow: 1 },
})
Use it in place of React Native's ScrollView.

If ScrollView is wrapped inside of a SafeAreaView, put flex: 1 on SafeAreaView, this did the trick for me after hours of debugging...
Parent:
Child (styles ScrollView I implemented has nothing to do with the current issue you reported):

I have made a simple package for those who just want, like me, a working out of the box ScrollView, without having to apply all the time the styles to make it work properly.
https://github.com/SrBrahma/pagescrollview
Usage:
import { PageScrollView } from 'pagescrollview';
<PageScrollView>
{/** Your contents */}
</PageScrollView>

Related

in react native how i can change background color for every view element independent

for every view element independent when i press them without effect other views and save pressed state so next time i can find what ipressed still pressed and i can change color of other view when ipress them without lose stat of preview view
the problem is when i press one from two task the other task also change her background color
import React, { useState } from 'react';
import {
SafeAreaView,
View,
FlatList,
StyleSheet,
Text,
TouchableOpacity,
} from 'react-native';
function App() {
const [changBack,backgroundColor]=useState('green')
function changIt() {
backgroundColor('red');
}
const DATA1 = 'Task one';
const DATA2 = 'Task two';
return (
<View>
<TouchableOpacity
style={{
flex: 1,
backgroundColor:changBack,
padding: 20,
}}
onPress={changIt}>
<View>
<Text>{DATA1}</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
style={{
flex: 1,
backgroundColor:changBack,
padding: 20,
}}
onPress={changIt}>
<View>
<Text>{DATA2}</Text>
</View>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection:'column',
textAlign:'right',
justifyContent:'space-evenly',
},
});
export default App;
Brother I notice you passed backgroundColor on Style for <TouchableOpacity> so definitely it won't work. backgroundColor is applicable for <View> only but not for TouchableOpcacity.
Do something like this ~
<View>
<View style={{backgroundColor:changBack}}>
<TouchableOpacity onPress={changeIt}>
<View>
<Text>Heyya</Text>
</View>
</ToucableOpacity>
</View>
</View>
or this,
<View>
<TouchableOpacity onPress={changeIt}>
<View style={{backgroundColor:changBack}}>
<Text>Heyya</Text>
</View>
</ToucableOpacity>
</View>

Slash "/" symbol added in data list after each order

im just a begineer with react native and i have this problem :
im working on a food app where you can check food items with checkbox , for each food checked it will be automatically stored in array like this :
const data = [
{
"Viande": Viande,
"Sauce": Sauce,
"Extra": Extra,
"Boisson": Boisson,
"Supplements": Supplements,
}
]
AsyncStorage.getItem("STORAGE_Data").then((datacart) => {
console.log("datacart = ", datacart)
if (datacart !== null) {
const cart = JSON.parse(datacart)
cart.push(datacart)
AsyncStorage.setItem("STORAGE_Data", JSON.stringify(cart))
console.log("cart 2:",JSON.stringify(cart))
}else{
AsyncStorage.setItem("STORAGE_Data", JSON.stringify(data))
console.log("else : " , data)
}
console.log("DATA:", JSON.stringify(data))
alert("done")
}).catch((error) => {
alert(error)
})
};
Everything works properly so far , im using asyncstorage to save all the data and get them in my Cart class where i have all the data , im using map() function to create a view for each time i add new food :
constructor(props) {
super(props);
this.state = {
dataCart: [],
};
}
componentDidMount()
{
try {
AsyncStorage.getItem('STORAGE_Data').then((cart) => {
if (cart !== null) {
const cartfood = JSON.parse(cart)
console.log(cart)
this.setState({ dataCart: cartfood })
console.log(JSON.stringify(this.state.dataCart))
}
})
}
catch (error) {
console.log(error)
}
}
and here is my map() function
{
this.state.dataCart.map((item , i) => {
return (
<View style={styles.rectangle}>
<Image style={{ width: normalize(200), height: normalize(64), alignSelf: 'center', marginLeft: normalize(-40) }} source={require("../assets/Tacos-M.png")}></Image>
<View>
<Text style={{ alignSelf: 'center', fontSize: normalize(17), marginTop: normalize(10) }} key={i}>{item.Viande}</Text>
<View style={{ flexDirection: 'row', alignSelf: 'center', marginTop: normalize(40) }}>
<TouchableOpacity onPress={() => alert('ok')}><Feather name="minus" color={'#D05A0B'} size={normalize(20)} style={styles.btnMoin} /></TouchableOpacity>
<Text style={{ fontSize: normalize(15), marginLeft: normalize(15) }}>2</Text>
<TouchableOpacity><Feather name="plus" color={'#D05A0B'} size={normalize(20)} style={styles.btnPlus} /></TouchableOpacity>
</View>
</View>
<View>
<TouchableOpacity><Feather name="x" color={'#D05A0B'} size={25} style={{ alignSelf: 'flex-start', marginTop: normalize(20), marginLeft: normalize(40), }} /></TouchableOpacity>
<Text style={{ fontSize: normalize(15), alignSelf: 'center', marginTop: normalize(27), marginLeft: normalize(35) }}>14 DT</Text>
</View>
</View>
)
})
}
So the problem is i can make a food list as a first order , but in the second order after i change the food choice my map() function doest not give food name like this :
it returns an empty text instead in the second order view
so tired console.log() to see if im getting real data or no and suddenly i figured out whenever i add another order the food list becomes like this :
the slash "/" symbol added for each order , i have no clue how but is there any solution to avoid these kind of symbols and get a clean and proper list for my data ?
If you look in your AsyncStorage.getItem callback, you'll see that you're doing:
cart.push(datacart)
meaning you're pushing your stringified cart onto your cart and then setting it back into AsyncStorage, when you probably want to be doing:
cart.push(data)
Edit:
Actually, you probably want to set data equal to the object rather than an array containing the object, and then change your code to either push the object to the cart array in the if statement or set the AsyncStorage with a new array containing the object like so:
const data = {
"Viande": Viande,
"Sauce": Sauce,
"Extra": Extra,
"Boisson": Boisson,
"Supplements": Supplements,
}
...
if (...) {
const cart = JSON.parse(datacart)
cart.push(datacart)
AsyncStorage.setItem("STORAGE_Data", JSON.stringify(cart))
} else {
AsyncStorage.setItem("STORAGE_Data", JSON.stringify([data]))
}

React Native - zIndex

I try to make FlatList where circles are different sizes, for each cirle, i need to have own zIndex.
Numbers in circles, show zIndex number, as you see its not working.
I use zIndex on <TouchableWithoutFeedback>
Here is my component:
<TouchableWithoutFeedback
onPress={() => dispatch(selectHockeyPlayer(item))}
style={[
styles.listItem,
{
width: playerWidth,
height: playerWidth,
transform: [{scale: scaleNum + 1.2}],
zIndex: Math.floor(scaleNum + 2),
},
isRated ? styles.isRated : null,
styles.circle,
activePlayer(item, styles.selectedListItem),
]}>
Place a View inside of TouchableWithoutFeedback and apply TouchableWithoutFeedback styles to the View
Do this
<TouchableWithoutFeedback
onPress={() => dispatch(selectHockeyPlayer(item))}>
<View
style={[
styles.listItem,
{
width: playerWidth,
height: playerWidth,
transform: [{scale: scaleNum + 1.2}],
zIndex: Math.floor(scaleNum + 2),
},
isRated ? styles.isRated : null,
styles.circle,
activePlayer(item, styles.selectedListItem),
]}>
Allright, i figured out what was the problem, FlatList doesnt work with zIndex, so i had to use ScrollView.

Adding checkbox in between text description in react native

I have a view where I display a Heading and details which I get from server as below.
Now, in the question description there is a tag __CB__ which I need to replace with the checkbox, so, instead of that tag there will be a checkbox and rest of the text will continue as usual. I have separated the text based on tag and placed a checkbox in between but I haven't been able to align the view, either it gets arranged columnwise or if I try to arrange in row the text doesn't continue. Here is what I've tried.
Try 1:
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<View style={styles.checkBoxTextContainer}>
<Text style={styles.questionText}>{questionText1}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
// leftText={questionText1}
// rightText={questionText2}
/>
<Text style={styles.questionText}>{questionText2}</Text>
</View>
</ScrollView>
Styles
checkBoxTextContainer: {
flex: 1,
flexDirection: "row"
},
checkBoxStyle: {
width: 20,
height: 20
}
Result:
Try 2:
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<Text style={styles.questionText}>{questionText1}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
// leftText={questionText1}
// rightText={questionText2}
/>
<Text style={styles.questionText}>{questionText2}</Text>
</ScrollView>
Result:
I need the checkbox to continue in between text like the tag in my original image. Any help is appreciated.
Below is sample working code for your scenario.
import React, { Component } from 'react'
import { View, Text, StyleSheet } from 'react-native'
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap'
},
cb: {
width: 10,
height: 10,
borderWidth: 2,
borderRadius: 2,
borderColor: 'red',
marginTop: 4,
marginHorizontal: 3,
}
})
const sampleData = [ 'Lorem', 'ipsum', 'dolor', 'sit', 'amet',
'CB',
'consectetur', 'adipiscing', 'elit.', 'Curabitur',
'CB',
' nunc', 'vel', 'scelerisque', 'tempus.', 'CB', 'Morbi', 'luc', 'abcd', 'xyzw'
]
const CheckBox = () => (
<View style={styles.cb} />
)
export default class CheckText extends Component {
renderData = (data) => {
const views = data.map((item) => {
if (item === 'CB') { return <CheckBox />}
return (<Text>{item}</Text>)
})
return views
}
render() {
return (
<View style={styles.container}>
{this.renderData(sampleData)}
</View>
)
}
}
And this is snapshot of output
Note:
I have parsed the text into array of strings. This is the key logic here. The way you decide to tokenize your input text will affect the rendering of your component. When I tried long strings as token, flexWrap: 'wrap' didn't work properly. See this issue for more details. Tokenizing into single words may do the job.
try to wrap the Text and Checkbox into <Text> tag.
Please try below solution. It may help you.
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<View style={{
width:'100%',
flexDirection: "row"
}}>
// wrap into text tag
<Text>
// add space after first text
<Text style={styles.questionText}>{questionText1+" "}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
/>
// add space before second text
<Text style={styles.questionText}>{" "+questionText2}</Text>
</Text>
</View>
</ScrollView>

React native router flux : how to overrride burger button style?

Is there way to customize padding / position... of the burger button.
In the doc, i just can find the drawerImage parameter to override the burger image...
Saddly no option without forking. You can check the code here:
https://github.com/aksonov/react-native-router-flux/blob/master/src/NavBar.js. Padding and position is fixed.
Actually there's a parameter for it : leftButtonStyle
in my case I use react-native-vector-icons getImageSource for the burger icon
componentWillMount() {
Promise.all([Icon.getImageSource('bars', 16, 'black')])
.then((values) => {
this.setState({
menuIcon: values[0],
});
});
}
then you do something like this:
const menuIcon = {
uri: this.state.menuIcon.uri,
height: 20,
width: 20,
resizeMode: 'stretch',
color: 'white',
};
then in your tabs scene
<Scene
key="main"
type="replace"
initial
drawerImage={menuIcon}
tabs
style={{ backgroundColor: theme.navColor, justifyContent: 'center' }}
>

Resources