react native - Overlay above certain components only - react-native

I'm trying to display a simple overlay, but over certain components only.
Example code:
<Animated.View style={{ flex: 1 }}>
<Text style={ [{zIndex: 0}, styles.titleText] }>Title under overlay</Text>
<Animated.View style={ [styles.overlay] } />
<View style={{ zIndex: 2, flex: 1, justifyContent: 'center' }}>
<Text style={{ zIndex: 2, fontSize: 32, fontWeight: 'bold', color: '#ffffff', textAlign: 'center' }}>Subtitle above overlay</Text>
<Text style={ [{ zIndex: 0 }, styles.descriptionText] }>Text under overlay</Text>
<Text style={ [{ zIndex: 0 }, styles.descriptionText] }>Text above overlay</Text>
</View>
</Animated.View>
As mentioned, I need some of the components above the Overlay and others under it.
Right now, all components written in code after the overlay view, comes above overlay. I want specifically the component saying "Text under overlay" to come under overlay but the other text should be above.
How do I go about it? zIndex is not working the way I want it to.

You can add the overlay the by the combination of position: 'absolute' and zIndex in the following way.
<View style={styles.container}>
<View style={{position: 'absolute', backgroundColor: 'transparent', top: 0, bottom: 0, right: 0, left: 0, zIndex: 0}} /> //... Here is the overlay
<View style={{backgroundColor: 'red', position: 'absolute', top: 0, bottom: 200, right: 0, left: 0, zIndex: 1}} >
// Set the elements over the overlay here
</View>
<View style={{backgroundColor: 'blue', position: 'absolute', top: 0, bottom: 100, right: 0, left: 0, zIndex: -1}} >
// Set the elements under the overlay here
</View>
</View>
Here's the sample snack demo

Related

Place Item to Bottom React Native

I'm creating a react native app i have a item - a plus button(shown in image)
I want this to the bottom of my page onto footer -
but the problem is that when i place this button on bottom with position: 'absolute', bottom: 0 it's only going to the bottom of the hero section & not to the footer
Code -
<View style={styles.main}>
<View style={styles.hero}>
<View style={styles.flex}>
<View style={styles.container}>
</View>
</View>
<View style={styles.flex2}>
</TouchableOpacity>
</View>
<View style={styles.container12}>
</View>
</View>
</View>
<TouchableOpacity>
<View style={styles.container33}>
<EntypoIcon name="plus" style={styles.icon28}></EntypoIcon>
</View>
</TouchableOpacity>
Main Styles -
main: {
width: '100%',
height: '100%',
},
hero: {
alignSelf: 'stretch',
height: 250,
backgroundColor: '#fff',
borderBottomLeftRadius: 50,
borderBottomRightRadius: 50,
},
container33: {
width: 50,
height: 50,
backgroundColor: '#1DA6FA',
// flex: 1,
borderRadius: 50,
position: 'absolute',
bottom: 0,
right: 10,
alignItems: 'center',
justifyContent: 'center'
},
The problem si that you are applying the absolute css position to the View inside the TouchableOpacity and not to the TouchableOpacity itself.
To achieve what you want to do, you should write something like:
<View style={styles.absoluteOpacity}>
<TouchableOpacity>
<View style={styles.container33}>
<EntypoIcon name="plus" style={styles.icon28}></EntypoIcon>
</View>
</TouchableOpacity>
</View>
And then the css:
container33: {
width: 50,
height: 50,
backgroundColor: '#1DA6FA',
// flex: 1,
borderRadius: 50,
right: 10,
alignItems: 'center',
justifyContent: 'center'
},
absoluteOpacity: {
position: 'absolute',
bottom: 0,
}

Vertically center image that's not affected by KeyboardAwareScrollView in React Native

Alright, so this has got me busy for quite a few hours already. I am trying to create a login screen where the main components are rendered on the bottom, with the logo in the remaining space. This is kind of what I would like to achieve:
To support my textinputs, I use KeyboardAwareScrollView, as it works better for me as opposed to KeyboardAvoidingView. My code currently looks like this (I plan on using a background image with a 50% color overlay rather than the red background, so the ImageBackground has to stay in place too):
<ImageBackground
source={require('./assets/img/background-clouds.png')}
resizeMode="cover"
style={styles.backgroundImage}>
<View style={styles.backgroundOverlay} />
<View style={styles.dummyView}>
<Text>elloha</Text>
</View>
<Image
source={require('./assets/img/logo.png')}
style={styles.backgroundLogo}
resizeMode="contain"
/>
<KeyboardAwareScrollView
keyboardShouldPersistTaps="always"
keyboardOpeningTime={0}
alwaysBounceHorizontal={false}
alwaysBounceVertical={false}
contentInsetAdjustmentBehavior="automatic"
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
automaticallyAdjustContentInsets={false}
extraScrollHeight={30}
enableOnAndroid>
<StatusBar
backgroundColor="transparent"
barStyle="light-content"
hidden={false}
translucent
/>
<TouchableWithoutFeedback
onPress={Keyboard.dismiss}
accessible={false}>
<View style={styles.content}>
<View style={styles.backgroundContainer}>
<SafeAreaView style={{ flex: 0 }} />
<View style={styles.loginContainer}>
<View style={styles.loginScreen}>
// textinputs and buttons go here
</View>
<SafeAreaView style={{ backgroundColor: 'white' }} />
</View>
<View
style={{
backgroundColor: 'white',
height: Dimensions.get('window').height,
position: 'absolute',
width: Dimensions.get('window').width,
top: Dimensions.get('window').height,
}}
/>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAwareScrollView>
</ImageBackground>
Relevant styles:
const styles = StyleSheet.create({
container: {
backgroundColor: "white",
},
content: {
flex: 1,
},
backgroundImage: {
flex: 1,
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0,
width: Dimensions.get("window").width,
height: Dimensions.get("window").height,
},
backgroundContainer: {
justifyContent: "flex-end",
flex: 1,
width: Dimensions.get("window").width,
height: Dimensions.get("window").height,
},
backgroundOverlay: {
backgroundColor: "red",
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
},
logoContainer: {
top: "10%",
width: "100%",
},
backgroundLogo: {
alignSelf: "center",
position: "absolute",
width: 126,
height: 96,
},
dummyView: {
backgroundColor: "red",
flex: 1,
},
loginContainer: {
borderTopEndRadius: 30,
borderTopStartRadius: 30,
width: "100%",
backgroundColor: "white",
height: 500,
alignItems: "center",
paddingTop: Dimensions.get("window").width * 0.1,
},
loginScreen: {
width: "80%",
backgroundColor: "white",
},
});
This yields the following result:
I can get it done by adding top: 160 to the backgroundLogo style, but that's a fixed value. I want it to be always in the center of the available space, but I'm unable to add a view between the background and the loginContainer, as all the logic for the keyboard and such is handled in between.
Is there a way to achieve what I want? Ideally, I should also be able to check the available height, and only show the logo if there is enough space (e.g. available height > 100, otherwise don't show logo).
Important:
I want the logo to stay fixed, so if the keyboard is shown, the logo should not move up. The loginContainer should go "over" the logo
EDIT:
Wrap Image inside a View with this style and give the loginContainer style height: '70%' :
...
<View style={styles.dummyView}>
<Text>elloha</Text>
</View>
<View
style={{
justifyContent: 'center',
alignItems: 'center',
height: '30%',
position: 'absolute',
width: '100%',
}}>
<Image
source={require('./assets/img/logo.png')}
style={styles.backgroundLogo}
resizeMode="contain"
/>
</View>
<KeyboardAwareScrollView
keyboardShouldPersistTaps="always"
...
...
loginContainer: {
borderTopEndRadius: 30,
borderTopStartRadius: 30,
width: '100%',
backgroundColor: 'orange',
height: '70%',
alignItems: 'center',
paddingTop: Dimensions.get('window').width * 0.1,
},
...
hie! I think using Dimension to get a specific screen's height and deciding it has 70% of the screen covered via form sheet and rest is free for a logo to be in and we can ask it to be down a little using rest of height's 50% as margin-top ( the image will be in the center of that image )
here is a SNACK LINK to see your example working with my suggested solution.
here is the draft code:
import * as React from 'react';
import { Text, View, StyleSheet, Dimensions, ImageBackground,TextInput,
Image, TouchableWithoutFeedback, Keyboard, SafeAreaView, StatusBar} from 'react-native';
import Constants from 'expo-constants';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
export default function App() {
return (
<ImageBackground
source={{
uri: 'https://cdn.pixabay.com/photo/2021/08/23/18/37/tea-6568547_960_720.jpg',
}}
resizeMode="cover"
style={styles.backgroundImage}>
<View style={styles.backgroundOverlay} />
<Image
source={require('./assets/snack-icon.png')}
style={styles.backgroundLogo}
resizeMode="contain"
/>
<KeyboardAwareScrollView
keyboardShouldPersistTaps="always"
keyboardOpeningTime={0}
alwaysBounceHorizontal={false}
alwaysBounceVertical={false}
contentInsetAdjustmentBehavior="automatic"
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
automaticallyAdjustContentInsets={false}
extraScrollHeight={30}
enableOnAndroid>
<StatusBar
backgroundColor="transparent"
barStyle="light-content"
hidden={false}
translucent
/>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={styles.content}>
<View style={styles.backgroundContainer}>
<SafeAreaView style={{flex: 0}} />
<View style={styles.loginContainer}>
<View style={styles.loginScreen}>
<TextInput value={'email'} style={{borderBottomWidth:1, padding:10}}/>
<TextInput value={'password'} style={{borderBottomWidth:1, padding:10}}/>
</View>
<SafeAreaView style={{backgroundColor: 'white'}} />
</View>
<View
style={{
backgroundColor: 'white',
height: Dimensions.get('window').height,
position: 'absolute',
width: Dimensions.get('window').width,
top: Dimensions.get('window').height,
}}
/>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAwareScrollView>
</ImageBackground>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
},
content: {
flex: 1,
},
backgroundImage: {
flex: 1,
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
backgroundContainer: {
justifyContent: 'flex-end',
flex: 1,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
backgroundOverlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
logoContainer: {
top: '10%',
width: '100%',
},
backgroundLogo: {
alignSelf: 'center',
position: 'absolute',
marginTop: Dimensions.get('window').height/7, // top for rest of the screen to push logo down
width: 126,
height: 96,
},
dummyView: {
backgroundColor: 'red',
flex: 1,
},
loginContainer: {
borderTopEndRadius: 30,
borderTopStartRadius: 30,
width: '100%',
backgroundColor: 'white',
height: Dimensions.get('window').height/1.5, //container of form height
alignItems: 'center',
paddingTop: Dimensions.get('window').width * 0.1,
},
loginScreen: {
width: '80%',
backgroundColor: 'white',
},
});
Here is the output of code on android/ios:

Scrollable Absolute Position Button

How to create Gmail like a floating action button in react native
<TouchableOpacity
style={{ zIndex: 99, position: 'absolute', top: height/1.4,
right: 10, justifyContent: 'center', alignItems: 'center',
backgroundColor: Colors.Primary, height: height/10, width:
width/5.5, borderRadius: width/2.2 }} >
<Text style={{ color: '#fff' }}> Compose </Text>
</TouchableOpacity>
Here is a simple floating button
<TouchableOpacity
style={{
borderWidth:1,
borderColor:'rgba(0,0,0,0.2)',
alignItems:'center',
justifyContent:'center',
width:70,
position: 'absolute',
bottom: 10,
right: 10,
height:70,
backgroundColor:'#fff',
borderRadius:100,
}}
>
<Text style={{ color: '#fff' }}> Compose </Text>
</TouchableOpacity>
If you want an advance solution https://github.com/mastermoo/react-native-action-button

How to prevent react native modal from moving up when keyboard opens in android?

I have a very basic modal component(using React-native-modal) which render its given child views. However, I dont want the behaviour similar to KeyBoardAvoiding view, i.e. I don't want the modal to be pushed up when keyboard opens.
<Modal
isVisible={isVisible}
onBackdropPress={onCartDismiss}
style={CartStyles.cartModal}
onSwipeEnd={this.onCartDismiss}
onSwipe={this.onCartDismiss}
swipeDirection="down"
swipeThreshold={200}
propagateSwipe
avoidKeyboard={false}
>
{this.props.children}
....
On ios it is working fine i.e. the keyboard opens over the modal component, but not on android. avoidKeyboard={false} is not working.
This is my style for the modal (position:'absolute' didn't work too)
cartModal: {
position: 'absolute',
justifyContent: 'flex-end',
bottom: 0,
left: 0,
right: 0,
zIndex: 1,
},
I have even tried changing softinputmode in android manifest to :
android:windowSoftInputMode="adjustPan"
<Modal
isVisible={modalVisible}
animationInTiming={500}
animationOutTiming={1000}
backdropTransitionInTiming={500}
backdropTransitionOutTiming={1000}
onBackdropPress={() => setModalVisible(!modalVisible)}
onBackButtonPress={() => setModalVisible(!modalVisible)}
style={{
justifyContent: 'flex-end',
margin: 0,
position:'absolute'
}}
avoidKeyboard={false}
>
try this, it works for me.
Set you model height as integer value without percentage.
<Modal
// style={{backgroundColor:'red'}}
deviceHeight={screenHeight}
deviceWidth={screenWidth}
transparent={true} visible={isVisible} animated={false}>
<View style={{
backgroundColor: 'rgba(0,0,0,.6)',
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
flexDirection: 'row',
height: 200,
width: '80%',
alignSelf: 'center'
}}>
{content}
</View>
</View>
</Modal>
Give the main view inside your modal a "fixed height value" and the containing view should have a "100%" view height. Like this:
<Modal animationType={fade} ...>
<View style={{
height: "100%",
width: "100%",
alignItems: "center",
// justifyContent: "center",
backgroundColor: "rgba(0, 0, 0, 0.4)",
}}>
<View style={{
borderRadius: 10,
marginHorizontal: width * 0.05,
marginTop: height * 0.1,
width: width * 0.9
height: height * 0.8
}}>
...`enter code here`
</View>
</View>
</Modal>
I solved the issue by removing justifyContent: "center"

text Align :'right' doesn't work for placeholder when multiline is true

In my code i have 2 textInputs, one has one line and the other has multiple lines, the input is arabic so i have to enable textAlign: 'right',
my problem is when i set multilines to true, the placeholder text remains on the left side of the text input,
any idea how to solve this?
my code is the following:
View:
<View style={{ position: 'relative' }}>
<TextInput
style={forms.textInput}
value={this.state.telephone}
placeholder={'رقم هاتفك'}
placeholderTextColor={'rgba(0,0,0,0.6)'}
onChangeText={(val) => this.setState({telephone: val}) } />
<Icon name="android-phone-portrait" size={27} color="rgba(0,0,0,0.6)" style={{ position: 'absolute', top: 10, right: 24 }}/>
</View>
<View style={{ position: 'relative' }}>
<TextInput
style={[forms.textInput,{height: 120}]}
multiline={true}
value={this.state.desc}
numberOfLines={4}
placeholder={'اقتراحك'}
placeholderTextColor={'rgba(0,0,0,0.6)'}
onChangeText={(val) => this.setState({desc: val}) }/>
<Icon name="ios-help-outline" size={27} color="rgba(0,0,0,0.6)" style={{ position: 'absolute', top: 10, right: 24 }}/>
</View>
Style:
textInput: {
height: 40,
borderColor: 'rgba(0, 0, 0, 0.4)',
borderWidth: 2,
margin: 15,
marginTop: 5,
backgroundColor: '#fff',
color: 'rgba(0, 0, 0, 0.9)',
paddingRight: 40,
textAlign :'right'
},
______________________*******________________________
______________________*******________________________
I have actually made a pull request for this which has been accepted and will be in the 0.29.0 release of react-native.
My fix was to add this line
_placeholderView.textAlignment = _textView.textAlignment;
to react-native/Libraries/Text/RCTTextView.m
Inside the updatePlaceholder function (right before [self insertSubview:_placeholderView belowSubview:_textView];)
GitHub Commit