zIndex on component incorrectly stacking - css

// renderItem
<View>
<Image source={image} style={{position: 'absolute', zIndex: 40}} />
</View>
<View>
<ImageBackground source={image} style={{position: 'absolute', zIndex: 50}}/>
<Image source={image} style={{position: 'absolute', zIndex: 30}} />
<Image source={image} style={{position: 'absolute', zIndex: 20}} />
</View>
<FlatList renderItem={renderItem}/>
Idea is that the code above FlatList is fixed in place and image in renderItem can change position with scroll.
Expected Behavior
renderItem is stacked between zIndex of 50 and 30.
Current Behavior
renderItem is always at the back (before zIndex 20 eventhough renderItem has a zIndex of 40)
What I tried
For testing, I added another Image tag between 50 and 30 in the same file and that seems to be working. So I am guessing the issue only happens when componentizing it. I also tried messing with elevation since my target is Android but to no effect.
Any insight would be really helpful - thank you!

Working with zIndex sometimes happens this. For your case, I suggest you use the props ListHeaderComponent and stickyHeaderIndices to sticky the header when scrolling the list.
// Some code...
const Header = () => (
<View style={styles.header}>
<ImageBackground
style={styles.imageBackground}
source={require('./assets/image.png')}
>
<Text style={styles.headerTitle}>Fixed header</Text>
</ImageBackground>
</View>
);
// More code...
return (
<FlatList
ListHeaderComponent={Header}
stickyHeaderIndices={[0]}
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
)
I create a snack on Expo for you to see the complete example. Just scan the QR Code from your smartphone.

Related

Double Modal in React-Native?

I'm experiencing a lot of difficulty trying to implement a "double modal", i.e. two modals at the same time.
e.g.
I'm using Overlay from the 'react-native-elements' library to achieve the modal effect, however, putting two of them together in a view isn't working as it will only display the first one. I'm also finding that directly setting the height of the overlay isn't having any effect.
I then considered creating a custom component but can't figure out how to dim the background using CSS.
If you want, change the your element modal to react-native-modal. Keep try and execute the below code. I hope it'll work for you.
import Modal from 'react-native-modal';
const [isModalVisible, setModalVisible] = useState(false);
const toggleModal = () => {
setModalVisible(!isModalVisible);
};
<TouchableOpacity onPress={toggleModal}>
<Text>Button Text</Text>
<Modal
isVisible={isModalVisible}
onBackdropPress={() => setModalVisible(false)}>
<View style={{ backgroundColor: 'white', padding: 20, height:250 }}>
<Text>First box content appear here</Text>
</View>
<View style={{ backgroundColor: 'white', padding: 20, height:100, marginTop: 30 }}>
<Text>Second box content appear here</Text>
</View>
</Modal>
</TouchableOpacity>

React-Native: Scroll view does not respect justify content?

When attempting to use ScrollView it appears to not respect justifyContent of its parent container.
import React from 'react';
import { Text, ScrollView, StyleSheet, TextStyle, View, ViewStyle } from 'react-native';
interface TODO_TextCard {
text: string,
}
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
<ScrollView>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
</View>;
}
const styles = StyleSheet.create({
quoteTextStyle: {
fontSize: 30,
fontStyle: 'italic'
} as TextStyle,
viewStyle: {
flex: 1,
borderWidth: 2, borderColor: 'red',
justifyContent: 'center',
paddingHorizontal: 10
} as ViewStyle,
});
<TODO_TextCard text={'The mind adapts and converts to its own purposes the obstacle to our acting. The impediment to action advances action. What stands in the way becomes the way'}/>
Rendered as:
Now if I remove the and just render text such as
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</View>;
}
The Text element does respect the justifyContent:center of the parent and renders as:
Is it possible for Scroll view to be centered?
The solution that I have in mind right now is to check the length of the text and conditionally render Scroll View something like:
/** This some text length would have to be different depending on the device screen, and
* even with different device screens would still not work all the time if the text
* can have new lines in it.*/
const SOME_TEXT_LENGTH = 300;
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
{props.text.length > SOME_TEXT_LENGTH ?
<ScrollView>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
:
<Text style={styles.quoteTextStyle}>{props.text}</Text>
}
</View>;
}
Which very much is not ideal, due to different device screens as well as text potentially having new lines.
The ScrollView does in fact respect the justifyContent:center of its parent. The ScrollView is placed in the center of the outer View component. But here the ScrollView takes up the whole vertical screen, so it seems like it is not centered.
Try setting <ScrollView style={{backgroundColor: 'green'}}> to see what i mean.
Try applying viewStyle or a similar styling to the ScrollView itself. Make sure that you use the attribute contentContainerStyle instead of style. This snippet works for me.
<View style={styles.viewStyle}>
<ScrollView contentContainerStyle={{flex: 1, justifyContent: 'center'}}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
</View>
I also found this article. Maybe it will also help you out.
You need to give styling to ScrollView, for styling ScrollView you can use style or contentContainerStyle prop:
style defines the outer container of the ScrollView, e.g its height and relations to siblings elements
contentContainerStyle defines the inner container of it, e.g items alignments, padding, etc
In your case you need to give contentContainerStyle to position your items for eg:
return (
<View style={styles.viewStyle}>
{props.text.length > SOME_TEXT_LENGTH ?
<ScrollView
contentContainerStyle={{
flex: 1, //To take full screen height
justifyContent: 'center',
alignItems: 'center,
}}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
:
<Text style={styles.quoteTextStyle}>{props.text}</Text>
}
</View>
);

How to make scroll view scroollabe inside panGestureHandler?

I am using a react-native-gesture-handler library with reanimated and react-native-redash. I want to make scrollView scrollable which is nested inside panGestureHandler but all the interactions are handled by panGestureHandler, so scrollView is not working. Here is my code.
VideoModal.js file
import Animated , {useCode , cond , eq , set , add, block, interpolate, Extrapolate} from "react-native-reanimated"
import {PanGestureHandler , State } from "react-native-gesture-handler"
import {usePanGestureHandler , useValue , timing , snapPoint} from "react-native-redash/lib/module/v1"
export default function VideoModal(props) {
const { video } = props;
const {gestureHandler , velocity , translation , state} = usePanGestureHandler()
const translateY = useValue(0)
const offsetY = useValue(0);
const snapPoints = snapPoint(translateY , velocity.y , [0 ,upperBound])
useCode(()=>block([
cond(
eq(state , State.ACTIVE),
[
set(translateY , add(offsetY , translation.y))
]
),
cond(
eq(state , State.END),
[
set(translateY , timing({from:translateY , to:snapPoints, duration:350})),
set(offsetY , translateY)
]
)
]))
return (
<>
<View
style={{
height: statusBarHeight,
backgroundColor: 'black',
}}
/>
<PanGestureHandler {...gestureHandler} >
<Animated.View
style={{
...shadow,
transform:[{translateY:translateY}],
zIndex:10
}}
>
<TouchableWithoutFeedback onPress={()=>alert('Working'}>
<View style={{ backgroundColor: 'white', width }}>
<View style={{ ...StyleSheet.absoluteFillObject }}>
<PlayerControls title={video.title} onPress={() => alert('abc')} />
</View>
<AnimatedVideo
source={video.video}
style={{ width, height:videoContent }}
resizeMode={Video.RESIZE_MODE_COVER}
shouldPlay
/>
</View>
</TouchableWithoutFeedback>
<Animated.View style={{ backgroundColor: 'white', width:contentWidth, height:contentHeight }}>
<Animated.View style={{opacity:contentOpacity}}>
**<VideoContent {...{ video }} />**
</Animated.View>
</Animated.View>
</Animated.View>
</PanGestureHandler>
</>
);
}
the scrollView is inside VideoContent
import {
View, StyleSheet, Text, Image, ScrollView,
} from 'react-native';
export default function VideoContent(props) {
const { video } = props;
return (
<ScrollView>
<View style={styles.upNext}>
<Text style={styles.upNextTitle}>Up next</Text>
{
videos.map(v => (
<View key={v.id} style={styles.thumbnail}>
<Image source={v.thumbnail} style={styles.thumbnailImage} />
<View style={styles.thumbnailContent}>
<Text numberOfLines={2} style={styles.thumbnailTitle}>{v.title}</Text>
<Text style={styles.thumbnailUsername}>{v.username}</Text>
</View>
</View>
))
}
</View>
</ScrollView>
);
}
Is there anyway I can tell pangesture to work only if the finger is placed on the top part of screen otherwise it should not work and i can scroll the content present inside the scrollview??
Hey i Know its bit late to reply to your answer but i also faced the similar issue, a bit of research unable to me find this trick
activeOffsetX={[-10, 10]}
in you pangestureHandler like this
<PanGestureHandler
onGestureEvent={onGestureEvent}
activeOffsetX={[-10, 10]}
onHandlerStateChange={evt =>handleStateChange(evt)}
>
source : https://www.gitmemory.com/issue/software-mansion/react-native-gesture-handler/1380/786721032
I hope it helps

React Native Image not being centered with View

I am trying to center an Image within a View both horizontally and vertically the problem is that no matter what I put in the code it still seems to be in the same position all the time. I have this code for another View from another screen and it's exactly how I need it to be, however for the other pages it's not responding.
Here is my code:
<View style={styles.header}>
<Icon
raised
name='chevron-left'
type='octicon'
color='#f50'
onPress={() => this.props.navigation.goBack()}
containerStyle={{ alignSelf:'flex-end', marginRight:20, marginTop:-60 }}/>
<Image source={Logo} style={{resizeMode:'stretch', width:50, height:50, alignItems:'center', marginTop:30, position:'absolute'}}/>
</View>
const styles = StyleSheet.create({
header:{
backgroundColor:'#ff4714',
height:SCREEN_HEIGHT/8,
flexDirection: 'row'
}
});
EDIT: I've removed all the styling for the <Image> except for width and height and the image stays at the same place. I don't know what to make of this
Here is an expo snack https://snack.expo.io/SyCO!ree8
You need to add justifyContent:'center' and alignSelf:'center' to your image style,
Just check the code :
<View style={{
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
}}>
<Image source={{uri:'https://source.unsplash.com/random'}} style={{height:50,width:50,alignSelf:'center'}} />
</View>
And this is expo snack : expo-snack
UPDATE:
HERE IS MY UPDATED EXPO SNACK:
check here
Hope it helps
Try adding:
alignItems: 'center',
justifyContent: 'center'
to your header style
You might also need to add flex:1, depending on the state of your View

Align text to image - React Native

I am trying to align the social icon texts under each image like so:
However, I am getting these results:
I placed each row as a separate view
<View style={styles.socialIcons}>
<Image source={require("social/facebook-icon.png")} />
<Image source={require("social/twitter-icon.png")} />
<Image source={require("social/mail-icon.png")} />
<Image source={require("social/message-icon.png")} />
</View>
<View style={styles.socialIconsText}>
<Text style={styles.socialIconText}>Facebook</Text>
<Text style={styles.socialIconText}>Twitter</Text>
<Text style={styles.socialIconText}>Email</Text>
<Text style={styles.socialIconText}>Message</Text>
</View>
followed by their styles:
socialIcons: {
alignItems: 'center',
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: 40,
paddingRight: 40,
},
socialIconsText: {
backgroundColor: 'transparent',
alignItems: 'center',
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: 40,
paddingRight: 40,
},
I think what I should be doing instead is to place the text inside the image tags but, when I do that the images height cuts off any text under it. Is there a way to get the image heights and increase the height in the styles?
Or is there a better way to align the text underneath the images?
i think the padding interferes with the text.
also try to make every image and text element 25% in width + box-sizing: border-box; and center text.
İnstead of seperating image and text of facebook, twitter ... Covering them in a special wiew is better idea. In this way you will have much more control on your views and you can make a dynamic implementation.
<View style = {{flex:1}}>
<View style={{height:80, width:80}}>
<Image style ={{flex:1}}>
...
</Image>
<Text style={{flex:1}}>
</Text>
</View>
.
.
.
</View>
Creating a function for returning special views will save you from repeating codes.
getSpecView(uri,text)//use this params to specify your images and texts
{
return(
...
);
}
And now you just have to do is calling this function
<View style = {{flex:1}}>
getSpecView(*faceuri, *facetext)
getSpecView(*twitter, *twittertext)
.
.
</View>
You can even get rid of calling this function several times for every couple by creating an Json array and calling map function
couples = [{ name:'facebook', uri:'faceuri' }, { name:'twitter', uri:'twitter uri'}]
and now you just have a three lines of codes + a function and a json array.
<View style = {{flex:1}}>
couples.map(this.getSpecView(name,uri))// not sure about syntax
</View>
If you have trouble with images you can use resizeModes
resizeMode PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center'])
https://facebook.github.io/react-native/docs/image.html

Resources