React Native justifyContent: "center", height: "100% not working - css

I am trying to center the content in the center of the page. There is a block where the height is only going to the bottom of the content. (Acting like height: "auto"). I want the height of the tan block to be 100%. I have tried using justifyContent: "center" and nothing works. The top portion is also scrollable and I want no scrolling. enter image description here
import {StyleSheet, TouchableOpacity, Text, View, Button} from 'react-native';
import {NativeRouter, Route, Link} from 'react-router-native';
import {TextInput} from 'react-native-paper';
import {mdiArrowRightCircleOutline} from '#mdi/js';
class Register extends Component {
state = {
email: '',
password: '',
confirmPassword: '',
};
render() {
return (
<View style={styles.root}>
<View style={styles.wrapper}>
<Text style={{marginBottom: 8, fontSize: 20}}>Welcome,</Text>
<Text style={{marginBottom: 12, fontSize: 20}}>
sign up to continue
</Text>
<TextInput
label="Email"
value={this.state.email}
onChangeText={email => this.setState({email})}
style={styles.form}
underlineColor="#eb0091"
/>
<TextInput
label="Password"
value={this.state.email}
onChangeText={password => this.setState({password})}
style={styles.form}
underlineColor="#eb0091"
/>
<TextInput
label="Confirm Password"
value={this.state.email}
onChangeText={confirmPassword => this.setState({confirmPassword})}
style={styles.form}
underlineColor="#eb0091"
/>
<Text
style={{fontSize: 20, color: '#eb0091'}}
onPress={() => this.props.history.push('/')}>
Sign Up
</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
root: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
//backgroundColor: '#ffffff', uncomment this once height issue is better
},
wrapper: {
width: '80%',
},
form: {
marginBottom: 20,
},
footer: {
position: 'absolute',
bottom: 0,
},
});
export default Register;

I don't see any problem in the code so the problem must me in the component which contain , can you share the rest of the code.

Related

Stick two flex elements with dynamic growing in react-native

With react-native, I'm looking forward having a TextInput stuck with a MaterialIcons.Button within the same line.
I want the whole elements be centered horizontally but cannot achieve this with the following code:
import React from 'react';
import {
StyleSheet, TextInput, View,
} from 'react-native';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
const WordInput = () => {
return (
<View style={styles.container}>
<View style={styles.textInputContainer}>
<TextInput
textAlign="left"
/>
</View>
<View style={styles.arrowButtonContainer}>
<MaterialIcons.Button
name="arrow-forward-ios"
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
flex: 1,
},
textInputContainer: {
flex: 1,
alignItems: 'flex-end',
justifyContent: 'center',
},
arrowButtonContainer: {
flex: 1,
alignItems: 'flex-start',
justifyContent: 'center',
},
});
Here is the associated expo snack link.
The problem is that when I type text inside the TextInput, the Button doesn't move at all.
I would like it to dynamically shift to the right when the TextInput's width grow. The overall should be horizontally centered.
Does anyone know how I can proceed?
Thanks!
Unfortunately <TextInput> doesn't support any sort of "auto-growing" behaviour by default, but you could implement something yourself using a hidden <Text> layer that has the same font styling and sizing rules as your <TextInput>. If you then render your input value to that <Text> element, you can measure the layout of that element and apply the measured width to your <TextInput> component.
import { useState } from 'react';
import { StyleSheet, TextInput, View, Dimensions, Text } from 'react-native';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
export default function App() {
const [value, setValue] = useState();
const [containerWidth, setContainerWidth] = useState(
Dimensions.get('window').width
);
const [textWidth, setTextWidth] = useState(0);
const [buttonWidth, setButtonWidth] = useState(0);
const inputWidth = Math.min(textWidth, containerWidth - buttonWidth);
return (
<View style={styles.root}>
<View
style={styles.inner}
onLayout={(e) => setContainerWidth(e.nativeEvent.layout.width)}>
<Text
style={styles.hiddenText}
onLayout={(e) => setTextWidth(e.nativeEvent.layout.width)}
numberOfLines={1}
accessibilityElementsHidden
importantForAccessibility="no-hide-decendants">
{value}
</Text>
<TextInput
textAlign="left"
placeholder="enter text"
style={[styles.input, { width: inputWidth }]}
onChangeText={setValue}
/>
<View onLayout={(e) => setButtonWidth(e.nativeEvent.layout.width)}>
<MaterialIcons.Button name="arrow-forward-ios" />
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
root: {
flex: 1,
justifyContent: 'center',
},
inner: {
flexDirection: 'row',
justifyContent: 'center',
borderWidth: 1,
borderColor: 'red',
},
input: {
borderWidth: 1,
borderColor: 'green',
minWidth: 100,
},
hiddenText: {
position: 'absolute',
top: 0,
left: 0,
opacity: 0,
},
});
Here's an expo snack example.

How can I create a middle tab button like these with React Navigation?

I need to create a bottom tab navigation with React Navigation (v6) like this one:
So far what I did was:
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="ForYou" component={ForYouScreen} />
<Tab.Screen name="Maps" component={MapsScreen} />
<Tab.Screen name="Premium" component={PremiumScreen} />
<Tab.Screen name="Shop" component={ShopScreen} />
<Tab.Screen name="Media" component={MediaScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
But I'm not sure the right approach for styling, should I try to style 3rd tab button somehow? or should I create a 4 tabs navigation and create a floating button on the middle, but in this case how do I create room for it within the tabs on the middle?
Any idea or snippet is appreciated.
What you can do is add a custom tabBarButton and use svg in it like this (you will need to install react-native-svg)
//background svg which will create space
const TabBg = ({ color = '#FFFFFF', ...props }) => {
return (
<Svg width={75} height={61} viewBox="0 0 75 61" {...props}>
<Path
d="M75.2 0v61H0V0c4.1 0 7.4 3.1 7.9 7.1C10 21.7 22.5 33 37.7 33c15.2 0 27.7-11.3 29.7-25.9.5-4 3.9-7.1 7.9-7.1h-.1z"
fill={color}
/>
</Svg>
);
};
//custom tabBarButton
const TabBarAdvancedButton = ({ bgColor, ...props }) => {
return (
<View style={styles.container} pointerEvents="box-none">
<TabBg color={bgColor} style={styles.background} />
<TouchableOpacity
style={styles.button}
onPress={props.onPress}>
// any image or icon here
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
position: 'relative',
width: 75,
alignItems: 'center'
},
background: {
position: 'absolute',
top: 0,
},
button: {
top: -22.5,
justifyContent: 'center',
alignItems: 'center',
width: 50,
height: 50,
borderRadius: 27,
backgroundColor: '#E94F37',
},
buttonIcon: {
fontSize: 16,
color: '#F6F7EB'
}
});
// add your custom tabBarButton component
<Tab.Screen
name="Premium"
component={PremiumScreen}
options={{
tabBarButton: (props) => (
<TabBarAdvancedButton
bgColor={barColor} // background space color.
{...props}
/>
)
}}
/>
You can customize this the way you want if you need more help you can follow the below mentioned article. This works with react-navigation v6.
ReactNative: TabBar With Float Button

Absolute position in React-Native

Fix: My problem was that I didn't know what I should use. And this is which I want.
If you want to make it yourself, see ksav's answer
I have a component which acts as a Picker in React Native.
<Modal
transparent
visible={editVisible}
animationType="fade"
onRequestClose={modalChange}>
<Pressable style={styles.modalView} onPressOut={modalChange}>
<View style={styles.modalContainer}>
<TouchableOpacity style={styles.button} onPressOut={modalChange}>
<Text>Edit button</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPressOut={modalChange}>
<Text>Delete button</Text>
</TouchableOpacity>
</View>
</Pressable>
</Modal>
<TouchableOpacity onPress={modalChange}>
<Ionicons name="ios-ellipsis-horizontal-sharp" size={20} />
</TouchableOpacity>
I want to set the modalContainer to always be at the bottom of TouchableOpacity (Ionicons). But I set TouchableOpacity's css: position: 'relative' and
modalContainer: {
position: absolute,
bottom: 0,
right: 0,
}
It's not working as expected. Because:
position in React Native is similar to regular CSS, but everything is set to relative by default, so absolute positioning is always relative to the parent.
To simplify the problem, I want some View is always under the button which will show the view when I onPress
My demo
Ensure the parent View is flexing vertically and that your style is position: 'absolute',
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity, Modal, Pressable } from 'react-native';
export default function App() {
const [modalVisible, setModalVisible] = React.useState(false);
return (
<View style={styles.centeredView}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}
>
<View style={styles.modalContainer}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</Pressable>
</View>
</View>
</Modal>
<Pressable
style={[styles.button, styles.buttonOpen]}
onPress={() => setModalVisible(true)}
>
<Text style={styles.textStyle}>Show Modal</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
modalContainer: {
position: 'absolute',
bottom: 0,
right: 0,
},
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
});
After discussion, I think what you want would better be described as a tooltip or a popover rather than modal. E.g it is positioned at the bottom of the button that opens it, but doesnt take up any space in the flow.
import * as React from 'react';
import {
Text,
View,
StyleSheet,
TouchableOpacity,
Modal,
Pressable,
SafeAreaView,
} from 'react-native';
export default function App() {
const [tooltipVisible, settooltipVisible] = React.useState(false);
const [buttonHeight, setButtonHeight] = React.useState(0);
const handleLayout = (event) => {
const { x, y, height, width } = event.nativeEvent.layout;
setButtonHeight(height)
};
const handlePress = () => {
settooltipVisible(!tooltipVisible);
};
return (
<SafeAreaView style={styles.centeredView}>
<Pressable
onLayout={handleLayout}
style={[styles.button, styles.buttonOpen]}
onPress={() => settooltipVisible(true)}>
<Text style={styles.textStyle}>Show Thing</Text>
</Pressable>
{tooltipVisible && (
<View style={[styles.tooltipView, {top: buttonHeight}]}>
<Text style={styles.modalText}>Hello World!</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={handlePress}>
<Text style={styles.textStyle}>Hide Thing</Text>
</Pressable>
</View>
)}
<Text>Some other content</Text>
<Text>Some other content</Text>
<Text>Some other content</Text>
<Text>Some other content</Text>
<Text>Some other content</Text>
<Text>Some other content</Text>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
button: {
padding: 20,
backgroundColor: 'blue',
color: 'white',
},
centeredView: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 60,
},
tooltipView: {
zIndex:1,
padding: 20,
position: 'absolute',
backgroundColor: 'white',
borderRadius: 20,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
});
Demo

Center Alignment of Text in React Native App

A few issues with my visualization:
The text on my first button appears on the right end of the button, even though I have aligned it to the center. How can I shift the text 'login' to the center?
Currently, the 'Sign Up Here' text appears in the mid of the screen. I want it towards the end. However, when I increase the value for marginTop, the text disappears. For instance if I change it to 20, I can see only half of it (in the middle of the screen). If I increase it further it just disappears.
The Forgot Password text also appears on the left side even though I have aligned it.
The title 'My App' does not appear at all.
How can I fix these minor issues?
<Container View style={styles.container}>
<Text View style={styles.title}>
Instaride</Text>
<View style={{flex:1}}></View>
<Form View style={styles.formInput}>
<Item floatingLabel>
<Label View style={styles.labelText}>Username</Label>
<Input
View style={styles.textInput}
onChangeText={(textUname) => uname(textUname)}
value={textUname}
placeholder={'Username'}
/>
</Item>
<Item floatingLabel >
<Label View style={styles.labelText}>Password</Label>
<Input
View style={styles.textInput}
onChangeText={(textPassword) => password(textPassword)}
value={textPassword}
placeholder={'Password'}
secureTextEntry={true}
/>
</Item>
</Form>
<Button View style={styles.button}
onPress={() => navigation.navigate("Details")}>
<Text>Login</Text>
</Button>
<Text View style={styles.forgotText}>
Forgot Password?</Text>
<Right>
<Button hasText transparent onPress={() => navigation.navigate('Registration')}>
<Text View style={styles.signupText}>
Don't have an account? Sign Up Here</Text>
</Button>
</Right>
</Container>
);
}
);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#242625',
paddingTop: getStatusBarHeight(),
},
title: {
textAlign: 'center',
fontSize: 22,
color: 'white',
},
textInput: {
color: 'white',
},
button: {
marginTop: 15,
backgroundColor: '#65c756',
width: '70%',
height: '6%',
justifyContent: 'center',
alignSelf: 'center'
},
forgotText: {
marginTop: 15,
justifyContent: 'center',
textAlign: 'center',
color: 'white',
},
signupText: {
marginTop: 16,
justifyContent: 'center',
color: 'white',
},
labelText: {
fontSize : 14,
},
formInput: {
borderBottomWidth: 1,
marginLeft: 20,
marginRight: 20,
marginTop: 40,
},
});
UPDATE:
You don't need to use Input View, as that's not the right way.
The below code works and you can check in the Expo demo, you need to add full in the Button.
Answers to the points:
You don't need Left/Right, you can simply put it in View, Left was causing the issue.
Use flex:1 on the Middle Part, so it will grow and occupy the screen and will push your Sign Up here at the bottom
Forget password is pushed to the center
We used getStatusBarHeight and have padding equal to the statusBarHeight
import * as React from "react";
import {
Text,
View,
StyleSheet,
Container,
Form,
Item,
Label,
Input,
Left,
Right,
Button,
Content
} from "native-base";
import { SafeAreaView } from "react-native";
import Constants from "expo-constants";
import { getStatusBarHeight } from "react-native-status-bar-height";
// You can import from local files
import AssetExample from "./components/AssetExample";
// or any pure javascript modules available in npm
import { Card } from "react-native-paper";
export default class App extends React.Component {
render() {
return (
<Container
View
style={Object.assign(
{ ...styles.container },
{ marginTop: getStatusBarHeight() }
)}
>
<Content contentContainerStyle={{ flex: 1 }}>
<View>
<Text style={styles.title}>Instaride</Text>
</View>
<View style={{ flex: 1 }}>
<Form style={Object.assign({ ...styles.formInput }, { flex: 1 })}>
<Item floatingLabel>
<Label style={styles.labelText}>Username</Label>
<Input style={styles.textInput} placeholder={"Username"} />
</Item>
<Item floatingLabel>
<Label style={styles.labelText}>Password</Label>
<Input
View
style={styles.textInput}
placeholder={"Password"}
secureTextEntry={true}
/>
</Item>
<Button
full
style={styles.button}
onPress={() => navigation.navigate("Details")}
>
<Text>Login</Text>
</Button>
</Form>
</View>
<View>
<Text View style={styles.forgotText}>
Forgot Password?
</Text>
<Button
hasText
transparent
onPress={() => navigation.navigate("Registration")}
style={{ justifyContent: "center" }}
>
<Text style={styles.signupText}>
Don't have an account? Sign Up Here
</Text>
</Button>
</View>
</Content>
</Container>
);
}
}
const styles = {
container: {
flex: 1,
backgroundColor: "#242625",
borderWidth: 2,
borderColor: "red"
},
title: {
textAlign: "center",
fontSize: 22,
color: "white"
},
textInput: {
color: "white"
},
button: {
marginTop: 15,
backgroundColor: "#65c756"
},
forgotText: {
marginTop: 15,
justifyContent: "center",
textAlign: "center",
color: "white"
},
signupText: {
textAlign: "center",
justifyContent: "center",
color: "white"
},
labelText: {
fontSize: 14
},
formInput: {
borderBottomWidth: 1,
marginLeft: 20,
marginRight: 20
}
};
Temporary Link to Expo: https://snack.expo.io/#dhavaljardosh/8af9d3

I want my text to flow to my next line but flex is not letting me do it?

I want my app to add text underneath the goal section but flex is not letting me do that even if I create new components in native P.S Still a beginner
import React, { useState } from "react";
import { StyleSheet, View, TextInput, Button, Text } from "react-native";
export default function App() {
return (
<View style={styles.Container}>
<View style={styles.GoalInp}>
<TextInput
placeholder="Course Goal"
style={{ overflow: "scroll" }}
onChangeText={goalInputHandler}
value={enteredGoal}
/>
</View>
<View>
<Button title="ADD" onPress={addGoalHandler} />
</View>
<View>
{couseGoals.map(goal => (
<Text>{goal}</Text>
))}
</View>
</View>
);
}
const styles = StyleSheet.create({
Container: {
padding: 50,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
},
GoalInp: {
borderWidth: 1,
width: "80%",
padding: 10,
borderColor: "black"
}
});
You need to bring the listing outside the Container View, as the flex-direction of Container is row, all items will be in a row including form.
My modified code is given below
<View style={styles.wrapper}>
<View style={styles.Container}>
<View style={styles.GoalInp}>
<TextInput
placeholder="Course Goal"
style={{ overflow: "scroll" }}
/>
</View>
<View>
<Button title="ADD" onPress={this.addGoalHandler} />
</View>
</View>
<View>
{this.state.couseGoals.map(goal => (
<Text>{goal}</Text>
))}
</View>
</View>
const styles = StyleSheet.create({
wrapper:{
flex:1,
},
Container: {
padding: 50,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
},
GoalInp: {
borderWidth: 1,
width: "80%",
padding: 10,
borderColor: "black"
},
});
I think that you use to much Vieuw elements.
You should for example use a Text for where your text need to print out.
But I think I have it.
You wrapped everything into a View with a style of;
flexDirection: "row",
Not that good if you don't want to have the whole View on one line....
Issue solved?

Resources