React native scrollView not wrapping text elements (showing in a row) properly - react-native

I am using scrollView in need to show multiple text elements () in a single row.
For that i am using something like
`
{':AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:'}
{':BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB:'}
I am getting result something shown in image. Second 'BB.....' is not wrapping properly.
`

add flexwrap to view
Like this
<View
style={{
flexDirection: 'row',
flexWrap: 'wrap'
}}>

Try nesting the two texts inside a container Text:
<Text>
<Text>A...</Text>
<Text>B...</Text>
</Text>

Related

Include ListHeaderComponent in numColumns - React-Native

Does anyone know how I can include the header of a flatlist in the columns?
For example, in the image below I would like "Design" to follow "New +" in the same row.
Example Screenshot
Here is my code in render:
<FlatList
data={goalItems}
extraData={this.props}
renderItem={this._renderGoal}
ListHeaderComponent={this._renderGoalHeader}
keyExtractor={item => item.goal_id}
showsVerticalScrollIndicator={false}
numColumns={2}
/>
and in _renderGoal:
_renderGoal = ({ item }) => (
<TouchableOpacity
onPress={() => this.openOptions(item)}
style={{ padding: 10 }}>
<Bubble>
<Text style={[styles.normalText]}>{item.name}</Text>
<View style={{ alignItems: 'center' }}>
<Text>{formatSeconds(item.total_time)}</Text>
</View>
</Bubble>
</TouchableOpacity>
);
and in _renderGoalHeader:
_renderGoalHeader = () => (
<TouchableOpacity
onPress={() => this.openAddGoal()}
style={{ padding: 10 }}>
<Bubble style={[styles.newGoal]}>
<Text style={[styles.touchableText]}>New +</Text>
</Bubble>
</TouchableOpacity>
)
Thanks in advance.
As a temporary fix, I removed numColums from the flatList and added the following:
contentContainerStyle={{ flexWrap: 'wrap', flexDirection: 'row', width: 345 }}
I would love to be proven wrong here, but as far as I can tell, this cannot be done using numColumns. There is a workaround which I'll list at the end, but first the reasoning:
Explanation
I ran into this same issue but with the footer and did a code dive into the React Native source to see what was happening. First thing I did was use the inspector and I noticed that the header and footer of a FlatList are wrapped in a View while each row of columns is wrapped in CellRenderer > View. This is the first clue that FlatList does not account for headers and footers in numColumns. This is problematic because FlatList does not support masonry type layouts. This hints at the fact that there are many assumptions being made about how they are handling rendering the rows - that is, items are separated into rows to be rendered.
With these clues, I went into the source and found that FlatList passes its own custom renderItem down to VirtualizedList. Meanwhile, ListHeaderComponent and ListFooterComponent are passed down as is. They are never used in FlatList. Not a good sign as you'll see that the aforementioned _renderItem is what handles grouping the items together into columns to render using flexDirection: 'row' and whatever is passed down with columnWrapperStyle.
But perhaps VirtualizedList is smart enough to combine the header and footer into data that gets passed into renderItem?
Sadly, this is not the case. If you follow the code in VirtualizedList, you'll eventually see all the logic get played out in render() where:
a cells array is created
that first has the header pushed into it
followed by all of the data pushed into it via its _pushCells helper method
This is where CellRenderer appears;
hence why headers and footers are not wrapped by this whereas the rows are.
This is also where FlatLists _renderItem is used explaining why you get numColumns number of items wrapped in a CellRenderer.
and then finished with the footer being pushed in the same manner as the header.
This cells array of React components is then eventually cloned which helps with things such as keeping scroll position.
And finally rendered.
Do to this implementation, you will always get a fixed CellRenderer component which prevents headers and footers from being included as part of numColumns.
Workaround (not recommended)
If you've used React Native prior to FlatList being released, you'll know that one old workaround was to be very careful with your dimensions and use flexWrap: 'wrap'. It's actually documented within the source code as it will spit out a warning if you use this method of handling columns. Do note that it is NOT recommended to do this (I believe performance and perhaps scroll position may be some of the reasons against using this method).
If you are willing to do this though, add these styles to your contentContainerStyle:
flexDirection: 'row',
flexWrap: 'wrap',
// You'll probably also want this for handling empty cells at the end:
justifyContent: 'flex-start',
and remove the numColumns prop. Then make sure to manually size your component dimensions to get the correct looking column style layout you desire. This should allow your header and footer to render as part of the columns.
If you want to do it with numOfColumns, than use flexDirection:'row' within your header component
_renderGoalHeader = () => (
return(
<View style={{flexDirection:'row'}}>
<TouchableOpacity
onPress={() => this.openAddGoal()}
style={{ flex:1, padding: 10, }}>
<Bubble style={[styles.newGoal]}>
<Text style={[styles.touchableText]}>New +</Text>
</Bubble>
</TouchableOpacity>
<View>
<View style={{flex:1}}/> //this view is just to cover half width
);
)

How to "stack" touch events in React Native

I have a feed of items that looks something like this:
What I am trying to Achieve:
When the user presses an item in the feed (represented by the black box), they will be brought to a separate page for that item. When the user clicks on the star icon, they can "favorite" the item.
How I am trying to do it:
I am currently trying to implement this by nesting two TouchableOpacity's (represented by the black boxes), where the inner/child TouchableOpacity has a zIndex: 2 style applied to it.
The zIndex style does not seem to give a priority to the child container for touch events, so I was wondering if anyone knows how I can implement this pattern. I think I might need to use the PanResponder, but it seems like a very verbose way to add this functionality.
Any comments or examples would be greatly appreciated ! Thanks.
Can you not simply nest a TouchableOpacity in your parent TouchableOpacity ? I've done a mock project and this below seems to work
<View>
<TouchableOpacity
style = {{backgroundColor: 'red', height: 100}}
onPress = {() => {console.log("PARENT METHOD")}}>
//content
<TouchableOpacity
style = {{width: 30, height: 30, backgroundColor: 'yellow',
position: 'absolute', right: 5, bottom: 5}}
onPress = {() => {console.log("CHILD METHOD")}}>
//content
</TouchableOpacity>
</TouchableOpacity>
</View>
I've used logs and when pressing the small nested box, only child method is logged, and similarly for if i press the parent view.
Log output: showing independant touches
Let me know if this helps
Why not something like below:
<View style={{flex-direction: "row"}}>
<View>
<TouchableOpacity onPress={this.goToDetails.bind(this)}>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity onPress={this.goToDetails.bind(this)}>
</TouchableOpacity>
<TouchableOpacity onPress={this.favoriteItem.bind(this)}>
</TouchableOpacity>
</View>
</View>
Where you have two views in a row, first view has one TouchableOpacity, and the second view has two TouchableOpacitys in a a column (where first one is similar to previous TouchableOpacity, and the second is to favorite the item).
Should be structured like this:

Wrap Text in TouchableOpacity nested in Text

Including onPress inside a Text component will cause an ugly gray highlight to appear (for a split second) on the text when pressed.
Rather than having the gray highlight, I want the text to become slightly transparent while being pressed. This can easily be accomplished by wrapping the Text component in a TouchableOpacity. However, including this within another Text component is a different story. According to this and the fact that TouchableOpacity returns a View component, I have to specify a width and a height in order to accomplish this... and it's only possible on iOS.
How can I include a "pressable" Text component--that undergoes an opacity change when pressed--within another Text component?
<Text/>
Click <TouchableOpacity onPress={...}><Text>Here</Text></TouchableOpacity>
<Text/>
Try this:
<View style={{ flex: 1, flexDirection: 'row' }}>
<Text>Click</Text>
<TouchableOpacity onPress={...}><Text>Here</Text></TouchableOpacity>
</View>

Flexbox align images with different size to fill the area

I am using React Native's flexbox (not css flexbox). I am creating an image gallery and the first image has to be double the size, and the rest of the images smaller. Works good, but I have a problem that the third image is displayed in new row, instead where the blank space is.
Is it possible to achieve such behaviour with flex-box, so that the third image would be below the first small image?
I tried all combinations with aligning items, self aligning, flex directions, but no success. If needed I can provide a small example of the code which I already have.
I don't have a fully responsive answer, but this may be helpful here:
<View style={{ flexDirection: 'column' }}>
<View style={{ flexDirection: 'row' }}>
{this.renderPhoto(0)}
<View>
{this.renderPhoto(1)}
{this.renderPhoto(2)}
</View>
</View>
<View style={{ flexDirection: 'row' }}>
{render rest...}
</View>
</View>
Try this component. Maybe it will help you
https://xudafeng.github.io/autoresponsive-react/

Why my react native navigation bar's text not on the vertical center?

I use the Navigator.NavigationBar component to make a navbar, but the text not vertical centering.
Like this:
How can I solve this?
I just ran into this issue too. The solution:
<Navigator.NavigationBar
routeMapper={{
Title: (route, navigator, index, navState) =>
{
return (
<View style={{
justifyContent: 'center',
flex: 1
}}>
<Text style={{color: 'white'}}>Candidates</Text>
</View>
);
},
}}
/>
So basically make sure there's a parent wrap on your navbar elements filling the navbars height (the flex: 1 rule) and vertically center its contents with justifyContent: 'center'.
I've done the styles inline for this example, but of course it'd be more efficient to get those from a StyleSheet object.