RN Android: button takes too much space when text on 2 lines - react-native

I have this button
const TestButton = ({ text }) => (
<View
style={{
width: '100%',
marginTop: 10,
padding: 10,
backgroundColor: 'red',
flexDirection: 'row',
justifyContent: 'center',
}}>
<View
style={{
backgroundColor: 'green',
padding: 10,
flexDirection: 'row',
alignItems: 'center',
}}>
<Text numberOfLines={2}>{text}</Text>
</View>
</View>
);
I want the button to be the smallest possible, and centered.
Android
On Android, as you can see it's not really the case. For the 3 case we can clearly see that the button (green) is much larger than it should be and takes all available space.
iOS
On iOS as you can see it seems to work as I expect.
Is this a bug? Are there any workaround to solve this problem on Android?
Here is an Expo snack to reproduce.

Try this
const TestButton = ({ text }) => (
<View
style={{
width: '100%',
marginTop: 10,
padding: 10,
backgroundColor: 'red',
flexDirection: 'row',
justifyContent: 'center',
}}>
<View
style={{
padding: 10,
flexDirection: 'row',
alignItems: 'center',
}}>
<Text numberOfLines={2}
style = {{
backgroundColor: 'green',
padding:10
}}>
{text}
</Text>
</View>
</View>
);

I could solve my issue with wrapping my labels into container:
itemContainer: {
flex: 1,
marginHorizontal: 25,
paddingVertical: 15,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
},
itemView: {
width: "100%"
},
newsTitle: {
fontSize: 20,
color: darkBlue,
paddingRight: 20,
fontFamily: "Helvetica-middle",
borderColor: darkBlue,
borderWidth: 1
},
newsChannel: {
paddingTop: 10,
fontSize: 16,
fontFamily: "Helvetica",
color: darkGrey
},
return (
<TouchableOpacity style={styles.itemContainer}>
<View style={styles.itemView}>
<Text style={styles.newsTitle}>{news.title}</Text>
<Text style={styles.newsChannel}>{newsChannelTitle}</Text>
</View>
<ArrowIcon />
</TouchableOpacity>
);

Related

Remove SafeAreaView from Android

I am trying to set the background image to whole screen area including the notch. This is the default on iPhone but I am not able to achieve it on Android Phone. The Android phone I am using is Samsung Galaxy A-01 and the iPhone is iPhone XS. Attached are the screenshots.
Android Screenshot (Not fine)
iPhone Screenshot (I want to achieve this on Android as well)
UPDATE 1:
Following is the code:
render() {
const { roomId, nickName } = this.state;
return (
<>
<StatusBar barStyle='light-content' translucent />
<ImageBackground
source={require('../../../assets/images/backgroundImage.png')}
style={{ flex: 1, justifyContent: 'center', height: '100%' }}
resizeMode='cover'>
<KeyboardAvoidingView
style={{ flexGrow: 1 }}
enabled
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<View
style={{
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: 1,
flexDirection: 'column',
height: '100%',
}}>
<Image
source={require('../../../assets/images/logo.png')}
style={{ marginBottom: 50 }}
resizeMode='contain'
/>
<SafeAreaView
style={{
height: '50%',
justifyContent: 'flex-end',
width: '100%',
}}>
<View
style={{
width: '100%',
justifyContent: 'flex-end',
marginBottom: 10,
}}>
<TextInput
ref={this.classIdRef}
style={{
width: '100%',
backgroundColor: '#fff',
height: 50,
borderRadius: 4,
marginBottom: 15,
paddingHorizontal: 15,
}}
placeholderTextColor='rgb(218, 218, 218)'
placeholder='Class ID'
value={roomId}
onChangeText={(text) => this.setRoomId({ roomId: text })}
/>
<TextInput
ref={this.nicknameRef}
style={{
width: '100%',
backgroundColor: '#fff',
height: 50,
borderRadius: 4,
marginBottom: 20,
paddingHorizontal: 15,
}}
placeholder='Nickname'
placeholderTextColor='rgb(218, 218, 218)'
value={nickName}
onChangeText={(text) =>
this.setNickName({ nickName: text })
}
/>
<TouchableOpacity
onPress={this.navigateToClassroomHandler}
style={{
backgroundColor: 'rgb(251, 158, 85)',
width: '100%',
height: 50,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 4,
}}
disabled={roomId === '' || nickName === ''}>
<Text
style={{
fontSize: 18,
color: '#fff',
fontWeight: 'bold',
}}>
Attend Class
</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</View>
</KeyboardAvoidingView>
</ImageBackground>
</>
);
}

Opening keyboard reduce size of view's and hides text of other view (React native)

Default
when open keyboard
function PINInsert({ navigation }){
clearText = () => {
_textInput.setNativeProps({text: ''});
}
var onoff = 0
hideText = () => {
if(onoff == 0){
_textInput.setNativeProps({secureTextEntry: false});
onoff = 1;
}else{
_textInput.setNativeProps({secureTextEntry: true})
onoff = 0;
}
}
return(
<KeyboardAvoidingView style={styles.container0}>
<View style={PINInsertstyles.div0}>
<View style={{
alignContent: "center",
justifyContent: "center"}}>
<Image style={PINInsertstyles.flag} source={require('./assets/en.png')} />
</View>
<View style={{
alignContent: "center",
justifyContent: "center"}}>
<Image style={PINInsertstyles.flag} source={require('./assets/br.png')} />
</View>
</View>
<View style={PINInsertstyles.div1}>
<View style={{
height: 100,
width: 100,
alignItems: "center",
justifyContent: "center"
}}>
<Image style={PINInsertstyles.logo} source={require('./assets/headphone.png')} />
</View>
<View>
<Text style={{fontSize: 40}}>SoundFly</Text>
</View>
</View>
<View style={PINInsertstyles.div2}>
<View style={{flexDirection: "row", justifyContent: "center", alignItems: 'center'}}>
<TextInput
ref={component => _textInput = component}
style={{
height: 40,
width: 200,
margin: 5,
marginTop: 20,
borderWidth: 1,
borderColor: '#ccc',
fontSize: 20,
backgroundColor: '#fff'
}}
maxLength={6}
secureTextEntry={true}
placeholder="PIN"
/>
<TouchableOpacity onPress={hideText} >
<Icon name="eye" size={20} />
</TouchableOpacity>
</View>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity onPress={clearText}
style={{margin: 5, marginTop: 20, backgroundColor: 'red', padding: 5}}
>
<Text style={{justifyContent: 'center', alignItems: 'center', fontSize: 20}}>Clear text</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() =>
navigation.navigate('banner')}
style={{margin: 5, marginTop: 20, backgroundColor: 'purple', padding: 5}}
>
<Text style={{justifyContent: 'center', alignItems: 'center', fontSize: 20}}>Buscar</Text>
</TouchableOpacity>
</View>
<View style= {{height: 50}}></View>
</View>
</KeyboardAvoidingView>
);
};
const PINInsertstyles = StyleSheet.create({
div0: {
flex: 0.4,
backgroundColor: '#00FFEC',
flexDirection: "row-reverse",
alignItems: "flex-start",
},
div1: {
flex: 0.6,
backgroundColor: '#00DCCC',
alignItems: "center",
// justifyContent: "center"
},
div2: {
flex: 1,
backgroundColor: '#00BFBF',
alignItems: "center",
// justifyContent: "center"
},
flag: {
height: 50,
width: 80,
margin: 5
},
logo:{
height: 80,
width: 80,
margin: 10,
alignContent: "center",
justifyContent: "center",
alignItems: "center"
}
})
How I want is "When open keyboard, whole views go up without some view reducing size of itself."
I've tried a lot of example but my start is really different comparing with them cause most example starts complaining about keyboard covers contents but mine just send Views up but resizing them.
What am I doing wrong here?
You need to get dimension of window using
const windowHeight = Dimensions.get('window').height;
And then, insert justify-content: flex-end to container0.
Add a view right inside KeyboardAvoidingView and set minHeight to window height.

How to align multiline text in react native

In my screen, I need to split the text into column view and need to align the right side text with the left side text. also, need to show the whole text line by line. Tested with giving some height, width, position: absolute but didn't work. Any idea how to solve this?
I'll post my current code and screenshot for your ref.
Many thanks for your help
<View style={styles.twoCol}>
<View style={styles.leftField}>
<Text style={styles.leftFieldTitle}>Location:</Text>
</View>
<View style={styles.locationRightSide}>
<Text style={styles.rightFieldTitle}>{location}</Text>
</View>
</View>
const styles = StyleSheet.create({
twoCol: {
alignItems: 'center',
flexDirection: 'row',
marginTop: 25,
},
leftField: {
alignItems: 'flex-end',
width: '25%',
},
leftFieldTitle: {
fontWeight: '700',
color: 'black'
},
},
locationRightSide: {
width: '70%',
alignItems: 'flex-start',
paddingLeft: 10
},
rightFieldTitle: {
fontSize: RF(2.8),
color: 'black'
},
)}
Problem solved!!! Thanks everyone!
<View style={{
padding: 10,
flexDirection: "row",
marginLeft: 10,
marginRight: 5,
marginTop: 5,
marginBottom: 3,
justifyContent: "flex-start",
width: '95%',
}} >
<View style={{
position: 'absolute',
marginTop: 10
}}>
<Text style={styles.leftFieldTitle}>Location:</Text>
</View>
<View style={{ marginLeft: '26%' }}>
<Text style={styles.rightFieldTitle}>{location}</Text>
</View>
</View>

Vertical centering in React Native doesn't work

I use a ScrollView and I am not able to center an icon in one of inner Views.
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
<ScrollView>
...
<View style={styles.detailRowContainer}>
<View style={{flex: 1}}>
<Text style={styles.label} numberOfLines={1}>
{'Phone Number'}
</Text>
<Text style={styles.value} numberOfLines={1}>
{phone}
</Text>
</View>
<View style={styles.round}>
<TouchableWithoutFeedback onPress={this._onPressPhone}>
<Icon size={22} name="phone" />
</TouchableWithoutFeedback>
</View>
</View>;
...
</ScrollView>
detailRowContainer: {
flexDirection: 'row',
justifyContent: 'center',
flex: 1,
marginTop: 10,
paddingBottom: 10,
borderBottomWidth: 1,
borderBottomColor: Colors.lightGray,
},
label: {
color: Colors.glofoxDark,
marginBottom: 3,
},
value: {
color: Colors.glofoxDark,
fontWeight: '800',
borderBottomWidth: 1,
borderBottomColor: Colors.lightGray,
},
round: {
backgroundColor: Colors.lightBlue,
width: 30,
height: 30,
borderRadius: 30,
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'flex-end',
flexDirection: 'row',
padding: 4,
},
The styles need to be modified in this way.
Right now you're doing
flexDirection: row along justifyContent: center. Since your first child element is taking complete parent flex, therefore it does not show its effect
paddingBottom is given but , for centering an equivalent paddingTop must be given
padding for the round style should be replaced with margin, otherwise it affects the position of the inner elements
alignItems in round , must not be flex-end, it should be replaced with center
Here are the styles that will fix the vertical centering
detailRowContainer: {
flexDirection: 'row',
alignItems: 'center',
flex: 1,
marginTop: 10,
paddingTop: 10,
paddingBottom: 10,
borderBottomWidth: 1,
borderBottomColor: Colors.lightGray,
},
round: {
backgroundColor: Colors.lightBlue,
width: 30,
height: 30,
borderRadius: 30,
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'center',
margin: 4
},

Update images of listView item on click in react-native

This is one item in my ListView
If you saw right side there is one grey circle. Here I want
when I tab on this Image it should became like this :
here I am able to do it seprately but it won't happen in list view here is my code :
constructor(props) {
super();
super(props);
const dataSource = new ListView.DataSource({rowHasChanged: (r1, r2) => r1.guid != r2.guid});
this.state = {
dataSource: dataSource.cloneWithRows(productArray),
isLoading: true,
item1Check: true,
item2Check: true
}
}
this is my renderFile :
<ListView
style={{paddingBottom: 40}}
dataSource={this.state.dataSource}
enderRow={(item, rowID) => this._renderMenuItem(item, rowID)}/>
this is item of listView
_renderMenuItem(item, rowID) {
var imgSource1 = this.state.item1Check? checkImg : crossImg;
var imgSource2 = this.state.item2Check? checkImg : crossImg;
console.log("sfsd1121212asas",rowID,this.state.item1Check,item.p1id)
return (
<View style={{
flex: 1, borderBottomWidth: 0, flexDirection: 'column', alignItems: 'center',
marginBottom: 25, marginRight: 10, marginLeft: 10
}}>
<Item style={[styles.squareLayout, {marginBottom: 8}]}>
<CachedImage source={{uri: '../orange.jpg'}}
style={{
width: 100, height: 100, borderRadius: 10, overflow: 'hidden',
borderColor: AppColors.grey2, borderWidth: 1
}}/>
<Item style={{
flex: 3,
flexDirection: 'column',
borderBottomWidth: 0,
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center'
}}>
<Text style={{
flex: 1, fontFamily: AppStyles.fontFamily, fontSize: 10, color: AppColors.grey1,
justifyContent: 'flex-start', alignItems: 'flex-start', alignSelf: 'flex-start',
paddingLeft: 8, paddingTop: 8
}} numberOfLines={1}>Our Apple fruit is Fresh, Delicious and crunchy. It is one of the most
popular fruit, favorite of health conscious, fitness lovers who believe in the concept
“health is wealth. The fresh Himachal apples are exported worldwide directly from farms at
very competitive prices.</Text>
<Text style={{
flex: 4, fontFamily: AppStyles.fontFamilyMedium, fontSize: 16, color: AppColors.black,
justifyContent: 'center', alignItems: 'center', alignSelf: 'flex-start',
paddingLeft: 8, paddingBottom: 8
}} numberOfLines={3}>Apple</Text>
</Item>
<Item style={{
flex: 1,
borderBottomWidth: 0,
justifyContent: 'flex-start',
alignItems: 'flex-start',
alignSelf: 'center'
}}>
<TouchableHighlight onPress={ () => this.setState({item1Check : !this.state.item1Check})}>
<Image source={this.state.item1Check ? require('../../assets/images/small_check_circle.png') : require('../../assets/images/small_x_circle.png')} />
</TouchableHighlight>
</Item>
</Item>
<Item style={[styles.squareLayout]}>
<CachedImage source={{uri:'../apple.jpg'}}
style={{
width: 100,
height: 100,
borderRadius: 10,
overflow: 'hidden',
borderWidth: 1,
borderColor: AppColors.grey2
}}/>
<Item style={{
flex: 3,
flexDirection: 'column',
borderBottomWidth: 0,
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center'
}}>
<Text style={{
flex: 1, fontFamily: AppStyles.fontFamily, fontSize: 10, color: AppColors.grey1,
justifyContent: 'flex-start', alignItems: 'flex-start', alignSelf: 'flex-start',
paddingLeft: 8, paddingTop: 8
}} numberOfLines={1}> 20 Carton/Cartons Navel Orange</Text>
<Text style={{
flex: 4, fontFamily: AppStyles.fontFamilyMedium, fontSize: 16, color: AppColors.black,
justifyContent: 'center', alignItems: 'center', alignSelf: 'flex-start',
paddingLeft: 8, paddingBottom: 8
}} numberOfLines={3}>Oranges</Text>
</Item>
<Item style={{
flex: 1,
borderBottomWidth: 0,
justifyContent: 'flex-start',
alignItems: 'flex-start',
alignSelf: 'center'
}}>
<TouchableHighlight onPress={ () => this.setState({item2Check : !this.state.item2Check})}>
<Image source={this.state.item2Check ? require('../../assets/images/small_x_circle.png') : require('../../assets/images/small_x_circle.png')} />
</TouchableHighlight>
</Item>
</Item>
</View>
);
}
}
this is my main code where I am trying to update my Images:
<TouchableHighlight onPress={ () => this.setState({item1Check : !this.state.item1Check})}>
<Image source={this.state.item1Check ? require('../../assets/images/small_check_circle.png') : require('../../assets/images/small_x_circle.png')} />
</TouchableHighlight>
How about adding ref to the image?
import resolveAssetSource from 'resolveAssetSource';
...
<TouchableHighlight onPress={ () => this.setState({item1Check : !this.state.item1Check})}>
<Image ref="list1img" source={this.state.item1Check ? require('../../assets/images/small_check_circle.png') : require('../../assets/images/small_x_circle.png')} />
</TouchableHighlight>
And detect changes to component and then change the image by the ref.
componentDidUpdate(){
this.handleCheck();
}
handleCheck(){
var img = this.state.item1Check ? require('pathforimage') : require('anotherpathforimage');
this.refs['list1img'].setNativeProps({
src: [resolveAssetSource(img)] //use source for ios instead of src
})
}