Related
I saw that React Native offers nested vertical scroll-views from React Native Nested ScrollView Can`t Scroll on Android Device
The problem is that it doesn't seem to work on nested Horizontal ScrollViews on Android. See this code for an example:
https://snack.expo.io/#harrytravelchime/broken-horizontal-scroll
import React from 'react';
import _ from 'lodash';
import { View, ScrollView, StyleSheet, Text, SafeAreaView } from 'react-native';
export default class App extends React.PureComponent {
render() {
return (
<SafeAreaView style={styles.container}>
<ScrollView
style={{ height: '100%', width: '100%' }}
horizontal
nestedScrollEnabled
>
<View style={{ flexDirection: 'row' }}>
<ScrollView
style={{ width: 200, height: '100%' }}
horizontal
nestedScrollEnabled
>
<View style={{ flexDirection: 'row' }}>
{_.times(200, n => (
<View key={1000 + n} style={{ marginRight: 10 }}>
<Text>{1000 + n}</Text>
</View>
))}
</View>
</ScrollView>
{_.times(200, n => (
<View key={n} style={{ marginRight: 10 }}>
<Text>{n}</Text>
</View>
))}
</View>
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'stretch',
paddingVertical: 50,
},
});
On the other hand, the same code except with vertical scrolling totally works:
https://snack.expo.io/#harrytravelchime/working-vertical-scroll
Is there a way to make nested horizontal scrolling work?
One solution that I've come up with is to have a TouchableWithoutFeedback that tracks any touch by the user within the inner ScrollView. As soon as it detects a touch, it disables scrolling on the outer ScrollView, which would cause the inner ScrollView to receive events.
The main changes from the above code are:
Added state with outerScrollViewScrollEnabled
When the inner ScrollView is touched via the TouchableWithoutFeedback, change that state
Make the outer ScrollView's scrollEnabled depend on that
import React from "react";
import _ from "lodash";
import {
View,
ScrollView,
StyleSheet,
Text,
SafeAreaView,
TouchableWithoutFeedback
} from "react-native";
interface State {
outerScrollViewScrollEnabled: boolean;
}
export default class App extends React.PureComponent {
state = { outerScrollViewScrollEnabled: true };
handleInnerPressIn = () => this.setState({ outerScrollViewScrollEnabled: false });
handleInnerPressOut = () => this.setState({ outerScrollViewScrollEnabled: true });
render() {
const { outerScrollViewScrollEnabled } = this.state;
return (
<SafeAreaView style={styles.container}>
<ScrollView
style={{ height: "100%", width: "100%" }}
horizontal
scrollEnabled={outerScrollViewScrollEnabled}
>
<View style={{ flexDirection: "row" }}>
<ScrollView style={{ width: 200, height: "100%" }} horizontal>
<TouchableWithoutFeedback
onPressIn={this.handleInnerPressIn}
onPressOut={this.handleInnerPressOut}
>
<View style={{ flexDirection: "row" }}>
{_.times(200, n => (
<View key={1000 + n} style={{ marginRight: 10 }}>
<Text>{1000 + n}</Text>
</View>
))}
</View>
</TouchableWithoutFeedback>
</ScrollView>
{_.times(200, n => (
<View key={n} style={{ marginRight: 10 }}>
<Text>{n}</Text>
</View>
))}
</View>
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
justifyContent: "center",
alignItems: "stretch",
paddingVertical: 50
}
});
There is one more easier solution if you are using react-native-gesture-handler
import { ScrollView } from 'react-native'
import { ScrollView as GestureHandlerScrollView } from 'react-native-gesture-handler'
<ScrollView horizontal>
<GestureHandlerScrollView horizontal />
</ScrollVIew>
I got this answer from react-native github issue
import React, { Component } from 'react';
import { Alert, Button, TextInput, View, StyleSheet, Text, AsyncStorage } from 'react-native';
import { DrawerItems, DrawerNavigation } from 'react-navigation';
export default class Home extends Component {
const DrawerContent = (props) => (
<View>
<View
style={{
backgroundColor: '#f50057',
height: 140,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text style={{ color: 'white', fontSize: 30 }}>
Header
</Text>
</View>
<DrawerItems {...props} />
</View>
)
const Navigation = DrawerNavigator({
// ... your screens
Home:{
screen: HomeScreen,
},
Settings: {
screen: SettingsScreen,
},
}, {
// define customComponent here
contentComponent: DrawerContent,
})
render() {
return (
<View>
<Text>Welcome To Home</Text>
</View>
);
}
}
I am designing a screen which will be a home screen for my app. This screen will have navigation drawer like in Android and the drawer header will contain an image and a text label inside it and below that there will be drawer items from which i will navigate to a different screen. I have tried to achieve this using the above code but it doesn't work. Can you tell me where i am wrong? How can i achieve my target? I am a newbie to react native so i please make my concepts clear
Please replace your DrawerContent with the following code and check if it works.
const DrawerContent = (props) => {
return (
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<View style={{ flexDirection: 'row', paddingBottom: 20 }}>
<View style={{ flex: 80, backgroundColor: '#f50057'}}>
<Image style={{ width: 181, height: 132}} source={images.logo} />
</View>
<Text style={{ color: '#000', fontSize: 30 }}>Header</Text>
</View>
<DrawerItems {...props}/>
</SafeAreaView>
)};
First create Drawer Component
export default class DrawerComponent extends React.Component {
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView>
<View style={{ backgroundColor: "white" }}>
<Image
style={{ margin: 15 }}
source={{uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
/>
</View>
<DrawerItems {...this.props} />
</ScrollView>
</SafeAreaView>
);
}
}
and import the component in your Home.js
import DrawerComponent from "./path/to/drawerComponent";
Please note : ScrollView is necessary for the case when you have more items to show ex: 7+ items (with margins in style prop) and also when screen height is small
I am trying to make my application button in react-native like below
I am using inbuilt Button view of react native where I see that it does not allow to change the height also. I want to change the height as well rounded like expected image.
This is how my button is looking :
<Button
title="CONTINUE"
color="#FE434C"
onPress={() => navigate("EnableNotification")}
/>
So this is what I usually do:
<TouchableOpacity onPress={() => {/* do this */}}>
<View style={{
backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 15
}}
>
<Text style={{ color: 'white' }}>Button</Text>
</View>
</TouchableOpacity>
I find using this method makes buttons much more customisable, but if you do some digging there could be a library which implements something similar (I never really found the need to search for it).
NOTE: Obviously you will have to adjust the height/width of the button to your flavor.
EDIT: My mistake... I had put the onPress prop in the view, woops.
Here is my solution to easily style buttons using TouchableOpacity, Text and StyleSheet:
import React, { Component } from 'react';
import { View, StyleSheet, TouchableOpacity, Text } from "react-native";
export default class CustomButton extends Component {
render(){
return (
<View style={styles.container}>
/* Custom Button */
<TouchableOpacity
style={styles.customBtnBG}
onPress={() => {}} >
<Text style={styles.customBtnText}>Button</Text>
</TouchableOpacity>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center"
},
/* Here, style the text of your button */
customBtnText: {
fontSize: 40,
fontWeight: '400',
color: "#fff",
},
/* Here, style the background of your button */
customBtnBG: {
backgroundColor: "#007aff",
paddingHorizontal: 30,
paddingVertical: 5,
borderRadius: 30
}
});
#Ryan Turnbull, Well, i think a little padding and fontSize will do.
<TouchableOpacity onPress={() => this.onLogin()}>
<View
style={{
backgroundColor: 'black',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 15,
padding: 15,
}}>
<Text style={{color: 'white', fontSize: 20, fontWeight: '800'}}>
Button
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress = {() => {/* do this */}}>
<View style = {{backgroundColor: 'red', alignItems: 'center',
justifyContent: 'center', borderRadius: 15}}
>
<Text style = {{color: 'white'}}>Button</Text>
</View>
You can use Touchable Opacity and it's prop border radius to adjust it's curve.
https://facebook.github.io/react-native/docs/touchableopacity
In React-native, we can customise user defined button component and call it from anywhere. So that we can have structured approach throughout the program or application.
import React from "react";
import { StyleSheet, TouchableOpacity, Text, View } from "react-native";
const MyButton = props => {
return (
<TouchableOpacity
onPress={props.onPress}
>
<View style={{...styles.buttonStyle, ...props.style,
backgroundColor:props.buttonColor,
borderColor:props.buttonColor}}>
<Text style={{...styles.TextStyle, ...props.style,
color:props.fontColor}}>
{props.children}
</Text>
</View>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
buttonStyle: {
paddingVertical: 10,
paddingHorizontal: 10,
borderRadius: 10,
borderWidth: 2,
},
TextStyle: {
textAlign: "center",
},
});
export default MyButton;
In style ... spread operator is used to integrate all the styles from same components and incoming styles from parent component through props.
props.children is used here to pass button title, so that title text is displayed on the button.
When button is pressed then instead of handling this press event inside of the button but inside of the component where we use this button. So we pass a fitting function reference on the button.
This MyButton button component can be called anywhere inside the program like:
<MyButton onPress={() => onPressFunction()}
buttonColor="red" fontColor="white">Button Title</MyButton>
You can use this library https://github.com/APSL/react-native-button to create a customizable button in react native.
<View>
<Button
style={{
backgroundColor: "#FE434C",
borderColor: "transparent",
borderRadius: 20,
width: 250,
height: 50,
}}
textStyle={{ color: "#FFFFFF" }}
onPress={() => { }}
>
CONTINUE
</Button>
</View>
I am learning React Native programming for Android mobile apps. I am making a screen where I need to set height of button. I have added button in view and set the height of using style however there is no change on button height.
/**
* LoginComponent of Myntra
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from "react";
import { AppRegistry, Text, View, Button, TextInput } from "react-native";
class LoginComponent extends Component {
render() {
return (
<View style={{ flex: 1, flexDirection: "column", margin: 10 }}>
<TextInput
style={{
height: 40,
borderColor: "gray",
borderWidth: 0.5
}}
placeholder="Email address"
underlineColorAndroid="transparent"
/>
<TextInput
style={{
height: 40,
borderColor: "gray",
borderWidth: 0.5
}}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid="transparent"
/>
<View style={{ height: 100, marginTop: 10 }}>
<Button title="LOG IN" color="#2E8B57" />
</View>
</View>
);
}
}
AppRegistry.registerComponent("Myntra", () => LoginComponent);
Can anyone help me to set the height of button according to my requirement?
This component has limited options, so you can't resize it to a fixed height.
I recommend you to use the TouchableOpacity component to build your own button, with own properties and styles.
You can easily style it like this:
<TouchableOpacity style={{ height: 100, marginTop: 10 }}>
<Text>My button</Text>
</TouchableOpacity>
You can set the button width as per the mentioned width easily by using following method :
<View style={[{ width: "90%", margin: 10, backgroundColor: "red" }]}>
<Button
onPress={this.buttonClickListener}
title="Button Three"
color="#FF3D00"
/>
</View>
Best solution is to use minHeight or maxHeight instead of using Height const.
It often happens that we want to change the dimensions of the button, which by default is extended to the entire width of the parent element. While reducing its width is not a problem – it is enough to reduce the width of the parent, but changing the height is already problematic. The Button element has no style property, so apart from changing the text color on iOS and the background color on Android, we can not set much in it.
To have more control over the button, it is better to use TouchableOpacity or TouchableNativeFeedback instead.
TouchableOpacity Function Component Example -
import React, { useState } from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
const App = () => {
const [count, setCount] = useState(0);
const onPress = () => setCount(prevCount => prevCount + 1);
return (
<View style={styles.container}>
<View style={styles.countContainer}>
<Text>Count: {count}</Text>
</View>
<TouchableOpacity
style={styles.button}
onPress={onPress}
>
<Text>Press Here</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
paddingHorizontal: 10
},
button: {
alignItems: "center",
backgroundColor: "#DDDDDD",
padding: 10
},
countContainer: {
alignItems: "center",
padding: 10
}
});
export default App;
<View style={styles.btnContainer}>
<TouchableOpacity>
<Button style={styles.btnSize}>
<Text>Change Address</Text>
</Button>
</TouchableOpacity>
<TouchableOpacity>
<Button style={styles.btnSize}>
<Text>Change Address</Text>
</Button>
</TouchableOpacity>
</View>
Style sheet code snippet
const styles = StyleSheet.create({
btnContainer:{
flexDirection:"row",
justifyContent:"space-between"
},
btnSize:{
width:"100%"
}
})
The component Button supports a minimal level of customization, so you have to use an other component.
You can use : Pressable or TouchableOpacity ,
<Pressable onPress={onPressFunction} style={styles.yourButtonStyle}>
<Text>I'm pressable!</Text>
</Pressable
const styles = StyleSheet.create({
yourButtonStyle: {
...
}
});
Doc Button
I am currently using React-Native for an Android Project. I have been trying to make a TextInput field with an icon beside the field. However, for some reasons, I notice that the flexDirection: 'row' is not working if the TextInput is one of its child component. The whole view of the one that I apply the style will automatically disappear. This is a snippet of how my code looks like:
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<View style={{flexDirection: 'row'}}>
<Image
style={{height: 30, width: 30}}
source={require('./images/email-white.png')}
/>
<TextInput
style={{height: 40}}
underlineColorAndroid={'transparent'}
placeholder={'E-mail'}
placeholderTextColor={'white'}
onChangeText={(data) => this.setState({ username: data })} />
</View>
</View>
I also tried to wrap both component inside each individual view, but the problem still persists. Is there anyone who knows how to solve this? or anyone can confirm that this is a bug?
Your code with a small modification worked fine for me. The only thing I did was adding a width to the TextInput resulting in the icon being beside the text-input.
Working code:
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<View style={{flexDirection: 'row'}}>
<Image
style={{height: 30, width: 30}}
source={require('./images/email-white.png')}
/>
<TextInput
style={{height: 40, width: 300}}
underlineColorAndroid={'transparent'}
placeholder={'E-mail'}
placeholderTextColor={'white'}
onChangeText={(data) => this.setState({ username: data })} />
</View>
</View>
I had the same problem when I was building example code from the book Mastering React Native
The code had enclosed a TextInput field in a View with a flexDirection: 'row' and the child TextInput field was not accessible. Only the TextInput border was visible. After playing around with some of the suggestions on this page I found something that worked.
If the container view has a flexDirection: 'row'. Please make sure to add a flex: 1 into your textfield input. The image flex does not seem necessary. As soon as I added the flex: 1 to the styles.input sheet, the TextInput was accessible.
The following code works for me :
<View style={globalStyles.COMMON_STYLES.pageContainer}>
<View style={styles.search}>
<Image
style={{height: 30, width: 30}}
source={require('../../images/email-white.png')}/>
<TextInput
style={styles.input}
onChangeText={text => this.setState({ searchText: text})}
value={this.state.searchText}
placeholder={'Search'}
placeholderTextColor={globalStyles.MUTED_COLOR}/>
</View>
</View>
Local Styles :
const styles = StyleSheet.create({
input: {
flex: 1,
height: 35,
color: globalStyles.TEXT_COLOR,
borderColor: globalStyles.MUTED_COLOR,
backgroundColor: globalStyles.BG_COLOR
},
search: {
borderColor: globalStyles.MUTED_COLOR,
flexDirection: 'row',
alignItems: 'center',
borderRadius: 5,
borderWidth: 1,
// marginTop: 10,
// marginBottom: 5
}
})
Global Styles (styles/global)
export const COMMON_STYLES = StyleSheet.create({
pageContainer: {
backgroundColor: BG_COLOR,
flex: 1,
marginTop: 0,
paddingTop: 20,
marginBottom: 48,
marginHorizontal: 10,
paddingHorizontal: 0
},
text: {
color: TEXT_COLOR,
fontFamily: 'Helvetica Neue'
}
});
Hopefully this provides assistance to you guys. It took me a long time get something this simple working.
Try closing your Image tag...
<Image style={{width:30, height: 30}} source={require('./icon.png')} />
Also, add some dimensions to your TextInput...
<TextInput style={{height: 40, borderColor: 'gray', borderWidth: 1}} />
You might also need to set flex: 0 on the image and flex: 1 on the TextInput