Scrollview and child with flex: 1 - react-native

Is it possible to have a layout which is wrapped with ScrollView:
<ScrollView>
<View>dynamic height</View>
<View>flex with minHeight</View>
<View>static height</View>
</ScrollView>
and meets below prerequisites:
Height of the first View is dynamic (depends on text length). Height of the third View is static (always three buttons inside). Rest of the screen should be filled with View with map, but the minimal height is set to 250.
Now the tricky part: if there is a lot of text in first View, so that map doesn't fit, a scroll should appear. I couldn't achieve that. I was trying to give the map View flex: 1 and minHeight: 250, but it's not rendered at all.
Solution
Ok, I've found a way to fix it. In first render, I get screen height (Dimensions) and height of first and third view (onLayout). Then, I calculate the height of second view (screenHeight - view1 - view3 - naviagtionHeight) and forceUpdate() to re-render it.

Add contentContainerStyle={{flexGrow: 1}} prop to ScrollView and its children's flex:1 would work. So you don't need to calculate it manually.

Related

Why aren't all items displayed in the ScrollView?

I have a Flatlist inside a ScrollView with 100 items, but no matter what height I give to the ScrollView or Flatlist, there are always just 18 items displayed on my Phone. After that the slider of the ScrollView is still scrolling down, but the list ends after 18 items. I want to be able to scroll through the complete list of items with the ScrollView containing the FlatList. I am using a Samsung Galaxy S8+ as a test device.
Here is a snack of the problem: https://snack.expo.io/#christophhummler/stickyheaderscrollscreens
Thanks for your help :)
I think it has to do with the scrollEnabled={false}, set it to true or remove the prop altogether otherwise it may be your todos array
Edit
Since you want to create a sticky header you must set the height to be the device height of screen + height of header, change styles.scrollView to :
scrollView: {
height: height + 200,
}
also on android there is an issue of nesting scrollviews, to enable a nested scrollview add the nestedScrollEnabled prop:
<FlatList
...
nestedScrollEnabled={true}
/>
You will have to implement logic to enable the Flatlist scroll view when the specific threshholds are met. It works at the moment in conjunction with scrollEnabled={true}
i hope this helps

Hold Position of ScrollView when adding data

I am trying to make it so whenever something new is rendered into a scroll view, the scroll view will stay put and not bump up and down. Right now if a new component is rendered in, the scrollview appears to be reset to 0.
Is there a way to stop this behavior, and hold position?
Right now for the scrollview I am using:
handleScrollt(event){
this.scroll = event.nativeEvent.contentOffset.y
}
handleSizet(width, height){
if (this.scroll) {
const position = this.scroll + height - this.height
this.refs.sv.scrollTo({x: 0, y: position, animated: false})
}
this.height = height
}
<ScrollView
ref="sv"
scrollEventThrottle={16}
onScroll={this.handleScrollt.bind(this)}
onContentSizeChange={this.handleSizet.bind(this)}
The issue with this is the scrollview will render briefly, before then scrolling to the correct offset. So it seems like theres a brief splash of the top of the screen
you have to define a height for the scrollview.
If the scrollview is supposed to cover an entire View you can get the view's height by:
<View style={styles.contactView} onLayout={(event) => {
var contactViewY = event.nativeEvent.layout.y;
this.setState({contactViewY: contactViewY})
}}>
and then give it to the scrollview
<ScrollView style={[styles.contactScroller, {height: this.state.contactViewY}]}>
Bear in mind that the onLayout method is called immediately once the layout has been calculated, so if the view's height changes later, this two lines of code alone won't update it.
You should try maintainVisibleContentPosition.
Example:
<ScrollView
{...props}
maintainVisibleContentPosition={{
minIndexForVisible: 0,
}}
/>
From the docs:
maintainVisibleContentPosition
When set, the scroll view will adjust the scroll position so that the
first child that is currently visible and at or beyond
minIndexForVisible will not change position. This is useful for lists
that are loading content in both directions, e.g. a chat thread, where
new messages coming in might otherwise cause the scroll position to
jump. A value of 0 is common, but other values such as 1 can be used
to skip loading spinners or other content that should not maintain
position.

Fixed View at bottom (variable height) and fill remaining height with other View

I want to build a chat. In the view for the messages are the messages and the input field for the message. The Inputbox should be at the bottom and should use the height it needs. The height of the Inputbox can change if the user enters multi-line text. The msgs-View should fill the rest of the height (above). I don't want to position the Input absolute because the message's FlatList should be always in the "visible" area.
<View style={styles.wrapper}>
<View style={styles.msgs}>Messages (FlatList)</View>
<View style={styles.input}>Inputbox</View>
</View>
Don't give flex style to your input.
Give your wrapper and list a flex: 1 style. Wrapper will take up all the space in its parent (which I assume is the screen). And list will take all the space in wrapper. And input will sit in the bottom.

Fix children container width trouble

My children views may be a different width, but it not be bigger than parent view. How can I fix it?
This is a screenshot of how it looks now:
you can give your parent view width as device window width like this:
var {height, width} = Dimensions.get('window');
Implement height and width as you required like this in your parent view:
<View style={{height:height, width:width}}></View>
After constructing your parent view, you can give your child view width and height as your own interest like :
style={{height:40, width:250}}
also you should have some knowledge on react-native flex to construct others layout you can view from here
I would need to see your code, but for React, you should be using Flexbox to align children for consistency.
http://moduscreate.com/aligning-children-using-flexbox-in-react-native/

ListView fails to scroll

As you can see in the attached GIF, I can't scroll through the ListView. The view snaps back to the original position as soon as I release the mouse.
I've read over the documentation and it seems like scrolling should just work. Here's the implementation of render():
render: function(){
return (
<ListView
automaticallyAdjustContentInsets={false}
initialListSize={9}
dataSource={this.state.dataSource}
renderRow={this.renderTrack}
renderSectionHeader={this.renderSectionHeader}/>
);
Your ListView might actually be quite small but not appear that way do to visible overflow. Try setting flex: 1 or height: 587 on your ListView's style property.
The only time I've seen this is when contentContainerStyle is set to flex:1. Remove the flex if that's the case.
setting flex:1 to list's parent did the trick for me.
I had the same problem, I had a View wrapping the ListView, I removed the outer View and now it works as expected.
It is due to this property, I assume you only have one, maybe add a sticky header per row?:
renderSectionHeader function
(sectionData, sectionID) => renderable
If provided, a sticky header is rendered for this section. The sticky
behavior means that it will scroll with the content at the top of the
section until it reaches the top of the screen, at which point it will
stick to the top until it is pushed off the screen by the next section
header.