I'm building a React Native app for the first time using an iOS Simulator with XCode, and it seems that my elements on the bottom of the screen are being cut off, as if the screen can only scroll so far. I've tried changing the overall container View's height, but it doesn't change how far down I can scroll. I've also tried removing the styling, as well as changing View to ScrollView, but neither helped. Another strange thing is that I need to add paddingTop, otherwise, the first Text is displayed over the time in the simulator
Here's the code:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Fields from './components/Fields.js'
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Calculator</Text>
<Text>1099 Calculator</Text>
<Fields />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
paddingTop: 50
},
});
Here's the top of the screen without the padding
And here's how it looks cut off
This is an issue I also had. To fix it just wrap your container with another view without padding but with flex. So like this:
export default class App extends React.Component {
render() {
return (
<View style={styles.main}>
<View style={styles.container}>
<Text>Calculator</Text>
<Text>1099 Calculator</Text>
<Fields />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
paddingTop: 50
},
main: {
flex: 1
}
});
I was facing the same problem, it turned out to be the padding that I added to my ScrollView. Maybe it is not the solution, it is simply to discard ideas..
Related
I am learning react-native and am very new to it. So, when I was learning to use flexbox, I ran into an issue. The issue was, the views are not being displayed when inside another view. My code =
import React from "react";
import { View, StyleSheet } from "react-native";
class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View backgroundColor="red" />
<View backgroundColor="blue" />
<View backgroundColor="green" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
});
export default App;
If you run this program, you will get a blank screen. I don't know why this is happening, and I also want to know how to fix it. By the way, I am running it in Iphone 11 simulator
You have set BackgroundColor directly to the View which is not possible. It has to be in the "Style" param. Also you have no height and width set to the View.
You can either do it inside the View directly like this:
<View style={{ backgroundColor: "red", height: 20, width: "100%"}} />
or create a new Style in your StyleSheet and then pass that to the View.
I have a ScrollView which has two children, and I want each of the children to be the full height of the available space on the screen, meaning view 1 fills the whole screen, and then I scroll down to start to see part of slide 2. If I scroll all the way down, I should only see slide 2.
I can't figure out how to get this to happen. What is currently happening is that each child is filling half of the available vertical space, so I don't get any scrolling.
Any ideas how I can achieve this layout? Thanks!
Current UI: https://i.imgur.com/fZdbUSo.png
Desired UI:
Before scrolling: https://i.imgur.com/EsQpVMm.png
After scrolling all the way down: https://i.imgur.com/PfXQyfI.png
Code:
import React from "react";
import {
StyleSheet,
ScrollView,
Text,
View
} from "react-native";
const Home = () => {return (
<ScrollView style={styles.scrollView} contentContainerStyle={styles.scrollViewContainer}>
<View style={styles.slide1}>
<Text>this should be full height</Text>
</View>
<View style={styles.slide2}>
<Text>this should also be full height, but only be visible once i scroll down</Text>
</View>
</ScrollView>
)};
const styles = StyleSheet.create({
slide1: {
justifyContent: "center",
flexGrow: 1,
backgroundColor: "blue"
},
slide2: {
justifyContent: "center",
flexGrow: 1,
backgroundColor: "green"
},
scrollView: {
flex: 1
},
scrollViewContainer: {
flexGrow: 1
}
});
export default Home;
I'm not sure if there is a way to do what you are trying to accomplish with flex layout.
I would suggest getting the height of the visible container - either the height of the window or calculate it some other way, possibly using onLayout of the containing view and getting the height there, and then you have to set the height of your two inner views using that. You may need to wrap your scrollView in a View and use its onLayout function instead of the one for the scrollView.
To do the second part of your question, scrollView has a snapToInterval prop you can set.
Let me know how that goes for you or if you need code examples.
I was able to get this to work by using onLayout() as Doug Watkins suggested and updating the height of the children to match the height of the parent ScrollView:
import React, { Component } from "react";
import {
StyleSheet,
ScrollView,
Text,
View,
LayoutChangeEvent
} from "react-native";
class Home extends Component {
state = {
slideHeight: 0
};
updateHeight = (e: LayoutChangeEvent) => {
this.setState({ slideHeight: e.nativeEvent.layout.height });
};
styles = StyleSheet.create({
slide1: {
justifyContent: "center",
backgroundColor: "blue"
},
slide2: {
justifyContent: "center",
backgroundColor: "green"
},
scrollView: {
flex: 1
},
scrollViewContainer: {
flexGrow: 1
}
});
render () {
return (
<ScrollView style={this.styles.scrollView} contentContainerStyle={this.styles.scrollViewContainer} onLayout={this.updateHeight}>
<View style={[this.styles.slide1, {height: this.state.slideHeight}]}>
<Text>this should be full height</Text>
</View>
<View style={[this.styles.slide2, {height: this.state.slideHeight}]}>
<Text>this should also be full height, but only be visible once i scroll down</Text>
</View>
</ScrollView>
)
}
};
export default Home;
You can use react-native-swiper to achieve this functionality. Set your data or component in swiper slides and set props horizontal={false} to get vertical sliding.
So, first install react-native-swiper using this command:
npm i react-native-swiper --save
Now, import and use it as following :
import React from "react";
import { StyleSheet, ScrollView, Text, View } from "react-native";
import Swiper from "react-native-swiper";
const { width } = Dimensions.get("window");
const { height } = Dimensions.get("window");
const Home = () => {
return (
<Swiper style={{}} height={height} horizontal={false}>
<View style={styles.slide1}>
<Text>this should be full height</Text>
</View>
<View style={styles.slide2}>
<Text>
this should also be full height, but only be visible once i scroll
down
</Text>
</View>
</Swiper>
);
};
const styles = StyleSheet.create({
slide1: {
justifyContent: "center",
flexGrow: 1,
backgroundColor: "blue",
},
slide2: {
justifyContent: "center",
flexGrow: 1,
backgroundColor: "green",
},
scrollView: {
flex: 1,
},
scrollViewContainer: {
flexGrow: 1,
},
});
export default Home;
I know this may not perfect solution, but it work around. Swiper originally made up with scrollview, so there may be not problem.
I created a component at react-native, but the text of the button is always at uppercase, someone knows why it doesn't take the text that pass, because I want to show 'Login', but it shows 'LOGIN'
import React, { Component } from 'react';
import { View, Button} from 'react-native';
import LabelApp from "../../config/labels.app";
const labelApp = LabelApp.loginView;
export default class Login extends Component {
constructor(props){
super(props);
this.handleClickBtnEnter = this.makeLogin.bind(this);
}
makeLogin() {
}
render() {
return (
<View>
<Button title= {labelApp.textButtonLogin} onPress={this.handleClickBtnEnter}/>
</View>
);
}
}
Label of component
const LabelApp = {
loginView: {
textButtonLogin: 'Ingresar',
},
}
export default LabelApp;
The visualization
For react Native Paper button use uppercase={false} prop:
<Button
mode="outlined"
uppercase={false}
accessibilityLabel="label for screen readers"
style={styles.yourButtonStyle}>Button label</Button>
So, the other two answers are correct that you should use TouchableOpacity, but as someone new to React Native, it took me awhile to understand what was going on here. Hopefully this explanation provides a little more context.
The built-in Button component seems to have some weird compatibility/visibility issues on occasion, one of which is rendering the title prop text all uppercase. When viewing the documentation for the Button component in Chrome, the preview shows all text being capitalized under the "Web" view but not Android or iOS (I was having this issue using Expo and Metro Bundler on an Android device, so not sure what to make of this). I couldn't find anything about capitalization/uppercase in the Button docs, so perhaps this is a bug.
The solution is to use a different component called TouchableOpacity. It also has an onPress event you can use and a built-in touch animation, but it has less out of the box styling than the Button component. Important to note from docs: "Opacity is controlled by wrapping the children in an Animated.View, which is added to the view hierarchy. Be aware that this can affect layout." It doesn't have a title prop, so you just put the button text in a Text component, like so:
<Button
title='text will be capitalized'
onPress={onPress}
/>
becomes
<TouchableOpacity onPress={onPress}>
<Text>text will stay lowercase</Text>
</TouchableOpacity>
I was having the same issue as OP, and this solved it for me.
From the official documentation
A basic button component that should render nicely on any platform. Supports a minimal level of customization.
The recommend use of touchable opacity or touchable native feedback
https://facebook.github.io/react-native/docs/touchableopacity
Below I've added textTransform: 'lowercase', as a style rule for the button to override any inherited text casing.
import React, { Component } from 'react'
import {
StyleSheet,
TouchableOpacity,
Text,
View,
} from 'react-native'
export default class App extends Component {
constructor(props) {
super(props)
this.state = { count: 0 }
}
onPress = () => {
this.setState({
count: this.state.count+1
})
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={styles.button}
onPress={this.onPress}
>
<Text> Touch Here </Text>
</TouchableOpacity>
<View style={[styles.countContainer]}>
<Text style={[styles.countText]}>
{ this.state.count !== 0 ? this.state.count: null}
</Text>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 10
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
textTransform: 'lowercase', // Notice this updates the default style
},
countContainer: {
alignItems: 'center',
padding: 10
},
countText: {
color: '#FF00FF'
}
})
https://snack.expo.io/Bko_W_gx8
This question is 3 years old and I'm not sure why no one has answered it correctly until now.
Native android buttons are all caps by default starting from android lollipop, which is what react native uses when you use the control Button from react-native in your app. To override the functionality, you just need to add this line in your styles.xml file inside your app theme (not the splash screen style)
<item name="android:textAllCaps">false</item>
You can get more details here: https://stackoverflow.com/a/30464346/11104068
The changes are not going to apply instantly obviously since the change is in the naive xml file and not in a JavaScript file. So you will need to do a npm/yarn run android
I've tried your code and it looks like it's the expected behaviour with Button component from react-native
You can see this at the official documentation
I believe that you need to change Button component, take it from another package to meet your needs.
As an alternative you can create your own button
import React, { Component } from 'react';
import { View, Button, TouchableHighlight, StyleSheet } from 'react-native';
import LabelApp from "../../config/labels.app";
const labelApp = LabelApp.loginView;
export default class Login extends Component {
constructor(props){
super(props);
this.handleClickBtnEnter = this.makeLogin.bind(this);
}
makeLogin() {
}
render() {
return (
<View>
<TouchableHighlight onPress={this.handleClickBtnEnter} underlayColor="white">
<View style={styles.button}>
<Text style={styles.buttonText}>{labelApp.textButtonLogin}</Text>
</View>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
marginBottom: 30,
width: 260,
alignItems: 'center',
backgroundColor: '#2196F3'
},
buttonText: {
textAlign: 'center',
padding: 20,
color: 'white'
}
});
<Button
style={{
borderRadius: 10,
backgroundColor: "#000",
width: 200,
height: 50,
}}
>
<Text
uppercase={false}
>
Login
</Text>
</Button>
App.js:
import React, { Component } from "react";
import { Text, View, StyleSheet } from "react-native";
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text>
<Text>First</Text>
<Text style={{ borderBottomWidth: 1 }}>Second</Text>
<Text>Third</Text>
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#ECF0F1"
}
});
As you can see, we have nested <Text> components. The problem is some style props such as borderBottomWidth - marginVertical - width is NOT working for the nested components!
Any idea for solving this issue?
Thanks in advance!
I'm not sure why the (width, marginVertical) are not working but I know that you should specify the (borderStyle=solid, borderColor) so that you can see it.I think that's the problem, hope it helped.
But I should say that it might not be it cause I came across your question by trying to ask one, and for me all the styles did not work, not only that but it's raising an error and it does not run at all, this strange behavior only happen to Text component whether nested or not.
I'm new here on react native, And i was trying to align the back button to the left, But keeping the title on the center, But nothing works, This is the code.
The TouchableOpacity is the back button, And the Text is the title, Each one have his own style.
import React, { Component } from 'react';
import { View, Text, TouchableOpacity, Image } from 'react-native';
import { Colors } from '../Variables';
class Header extends Component {
render(){
return(
<View style={ styles.headerStyle }>
<TouchableOpacity>
<Image style={ styles.backBtnStyle } source={ require('../graphics/icons/arrow_left_white.png') }/>
</TouchableOpacity>
<Text style={ styles.titleStyle }>
TITLE
</Text>
</View>
);
}
}
const styles = {
headerStyle: {
backgroundColor: Colors.primary,
flexDirection: 'row',
alignItems: 'center',
},
backBtnStyle: {
width: 25,
height: 25,
margin: 10,
},
titleStyle: {
color: '#fff',
textAlign: 'center',
fontSize: 25,
}
};
export default Header;
Thanks for helping.
You should try to view this document about Flex in React native and practive more to mastered it.
In Your case, just simplify add alignSelf: 'flex-start' to backBtnStyle StyleSheet to make it in first of your parent component
Here is demo code:
headerStyle: {
backgroundColor: Colors.primary,
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'flex-start'
},
<TouchableOpacity style={styles.backBtnStyle}>
<Image source={require('../graphics/icons/arrow_left_white.png') }/>
</TouchableOpacity>
You see: TouchableOpacity contain a Viewable Layout and wrap your image then you need to set style for TouchableOpacity to make flex work, not at Image.
From React NativeTouchableOpacity Documents: Opacity is controlled by wrapping the children in an Animated.View, which is added to the view hierarchy. Be aware that this can affect layout.
You can see Touchable Opacity Document here
Note: Set Your StyleSheet on StyleSheet.create() to make it create one and only one time when your bundle load. It make your app light weight and faster
Read about React Native StyleSheet here
You are using alignItems: 'center' in your container, so everything will be in the center.
In your case, there are a lot of solutions available. The more simple is just use a position: absolute; left: 15 in the styles.backBtnStyle.