I'm trying to use the KeyboardAvoidingView component from react native.
I want to display a little dot at the bottom of my screen. that dot is an absolut positioned element. When the keyboard appear, it hide it. I would like to know how to use that KeyboardAvoidingView component in my case :
<NetworkContext.Provider value={network}>
{props.children}
<KeyboardAvoidingView behavior={Platform.select({android: undefined, ios: "padding"})}>
{!network && <ConnectionAlert
style={{
position: "absolute",
bottom: 10,
right: 10
}}/>}
</KeyboardAvoidingView>
</NetworkContext.Provider>
There is something I did wrong ?
Related
I have a FlatList in React Native with fullscreen image and video items (with pagingEnabled). I want to have a short descriptive touchable text floating on top of the FlatList, to open up a view with some information about the image/video when pressed.
To make the user experience nice, I'd like to be able to scroll the FlatList through the touchable text as well. I.e. if the user happen to start their scrolling motion on top of the text, the FlatList would scroll but if it is a simple press event I'd like to open the view with details about the image/video.
No mater what I try I end up with either the text being able to react to the press OR the FlatList being able to scroll. I have tried different configurations with a custom PanResponder and pointerEvents but seem to always end up with a state were one thing does not work. Do you guys have any smart ideas? I am probably just stuck in the wrong train of thought.
This is a simplified view of my component structure:
<View>
<View style={{ position: 'absolute', bottom: 100, zIndex: 10 }}>
<TouchableOpacity onPress={() => console.log('press')}>
<Text>Some Descriptive Text</Text>
</TouchableOpacity>
</View>
<FlatList pagingEnabled horizontal {...otherFlatListProps} />
</View>
I want to make a little game when some circles comes from the top of the screen. After they appear they will drag down until they go out of the screen.
To make that i have a flatlist which contains all of the circles
<FlatList scrollEnabled={false}renderItem={this.renderItem}data={this.state.elements} />
Then in the render item I insert the circle item view
renderItem = ({item}) => (
<Circle
apparitionTime={new Date().getTime() / 1000}
id={item.id}
removeCircle={this.removeCircle}
updateScore={this.updateScore}/>
);
A circle item looks like this :
<Animated.View style={[/*this.moveAnimation.getLayout(),*/ styles.animatedView]}>
<TouchableOpacity style={styles.circleStyle} onPress={() => this.prepareToSend()}>
<View style={styles.absoluteView}>
</View>
<Image style={styles.image} source={require('../assets/images/music.png')}/>
</TouchableOpacity>
</Animated.View>
I use the animated view to make them scrolling all over the view.
I want the animated view to be on position absolute,but no matter what i've tried after sending the animated view to position absolute, the element disappear
animatedView: {
top: 0,
zIndex: 100,
width: 75,
height: 75,
position: "absolute", // does not work
},
Any Ideas ? Thank you
Position absolute didn't work inside a flatlist.
Now how to render positional elements inside it !!!!!!!....
Alternatively, you can use alignSelf: 'flex-end' or alignSelf:
'flex-start' and further you can place it by using margin/padding
inside the view. More you can read here about absolute not working in
their official docs
I have TouchableOpacity in a space between flex container that I want to take space even not shown,
My code:
<TouchableOpacity
style={showClear && { visibility: 'hidden' }}
onPress={() => this.props.clearCompleted()}>
<Text>Clear Completed</Text>
</TouchableOpacity>
display: none works but it doesn't take space, the code above dont work but does in web?
In my case, I needed to use the element, so I did something like this:
<TextInput style={{opacity: 0, height: 0}} {...props} />
I hope this works for someone else with my problem.
Update
React Native's StyleSheet now supports toggling visibility using display: 'none' and display:flex.
Not all CSS are supported in React Native, that include visibility: hidden or display:none.
To hide a component, not to render it at all, render empty View or null. Or you want to switch a component visibility, verify react's state
<View>
{ !showClear && (
<TouchableOpacity
onPress={() => this.props.clearCompleted()}>
<Text>Clear Completed</Text>
</TouchableOpacity>
}
</View>
showClear is kept in state
As Leu mentioned, you can just render null.
Another option if you want to keep the area used by TouchableOpacity is setting up opacity: 0.0 in style, but then you have to remember to set also disabled={false} in props of the TouchableOpacity, to avoid call clicking action on invisible area
Just setting the opacity to 0 was enough for my use case.
If we want to make sure element takes space on DOM but is kept hidden to user,
Step 1: Hide it from user using opacity: 0 .
Step 2: Disable interactions of hidden element.
Our JSX should be like below:
<IconButton
icon="close"
disabled
style={styles.hiddenElement}
onPress={() => console.log("Pressed")}
/>
Our stylesheet should look like below:
const styles = StyleSheet.create({
...
hiddenElement: {
opacity: 0,
},
...
});
So, I want to create a layout similar to whats below. [Refer the Image]
So the background has a full screen MapView (React Native Maps) with Markers over it, which needs to be clickable.
And there is a Scrollview with full screen height over the MapView which initially has some top-margin associated with its contents.
But the issue if I arrange my Views this way, the Markers on the map are not clickable in the initial state.
<View>
<MapView>
<Marker clickEventHere></Marker>
<Marker clickEventHere></Marker>
</MapView>
<ScrollView fullscreen>
<View marginTop></View>
</ScrollView>
<View>
I am unsure if its really possible to solve this out.
Initial State
After Scrolling
Solution Tried
yScrolled = event.nativeEvent.contentOffset.y;
yValue = this.state.yValue - yScrolled;
upwardScroll = yScrolled > 0;
if(upwardScroll && (yValue > 0)){
this.setState({
yValue: yValue
});
}
if(yScrolled === 0){
yScrolled = -10;
}
if(!upwardScroll && (yValue <= scrollViewMarginTop)){
yValue = this.state.yValue - yScrolled;
console.debug("UPDATE DOWNWARD");
this.setState({
yValue: yValue
});
}
I'd start with adding absolute positioning to your ScrollView, (position: absolute) starting at whatever y coordinate you would like. I would make this y value a state, eg
yValue: new Animated.Value(start_value) or simply yValue: start_value
I would then use ScrollView's prop onScroll event to handle the change in this y coordinate, for example for the first 100 pixels of a scroll it would simply change the yValue instead of scrolling the view.
This should enable you to press the markers you have in your parent view, and use the same component structure that you have provided.
Note: You would need to do this for collapsing the scrollview also.
Note2: if this doesn't give you the result you were looking for, i'd suggest looking into using some sort of collapsable component for this task, eg https://github.com/oblador/react-native-collapsible
Hope this helps
EDIT: To collapse the scrollview you could first identify if the scroll direction is downwards ( which i think youve done via upwardScroll ) and then..
1) Either simply add the content offset to your yValue
2) If you used Animated.Value for yValue, you can have an animate function that animates the scrollview downwards to your desired position. I think this would look nicer as the user would only need a simple downwards flick to collapse the view, which seems like the industry standard.
There is also a library that is called react-native-touch-through-view that can do this for you. This it how it works basically:
<View style={{ flex: 1 }}>
// Your map goes here
</View>
<TouchThroughWrapper style={{
position: 'absolute'',
top: 0,
left: 0,
width: '100%',
height: '100%',
}}>
<ScrollView
style={{
backgroundColor: 'transparent',
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
// Maybe in your case is flex: 1 enough
}}
bounces={false}
showsVerticalScrollIndicator={false}
>
<TouchThroughView
style={{
height: 400, // This is the "initial space" to the top
}}
/>
// The "slide up stuff" goes here
</ScrollView>
</TouchThroughWrapper>
For example, this then can look like this:
So the map is overlayed by the TouchThroughView that passes all the events right to the view behind. In my case this worked better than using pointer-events box-none.
Here is the code:
<View
style={{transform: [{translateX: this.state.translateX}], width: '120%'}}>
<View style={{width: '20%'}}>{someText}</View>
<View style={{width: '80%'}}>{someText}</View>
<View style={{width: '20%'}}>{someText}</View>
</View>
this.state.translateX was respond to swipe gesture which worked fine, the first two View did move but the last View was not visible (or not moved?). I want to show the last View when this.state.translateX changed. But it seems not being properly rendered?
It is because Android does not render element which is off screen. Solution is place the element in screen with position: 'absolute' and then use translateX to hide it from screen.