Arvindh
Arvindh

Reputation: 620

Proper way to Handle different screen sizes in react native ,

As , I developed a react native using physical device with screen size of 6 inch , it looked great and then when I tested with 5.5 it some what great , as still few components got spreader ! Then I tried with 4.3 inch , omg most of the components went beyond the screen . Then I googled , and found few packages which helps with screen size , it corrected the prop with 5.5 but still the prop persist at 4.3 inch !

I have converted most of the width and height as % , only padding is valued with int .

How to make the ui, responsively ! And one of my majore doubt is, I have created a top level View component with flex :1 and width and height with screen size. Even though , how come the sir goes beyond in small screen mobiles ?

As it should consider the screen size only bcoz , I have declared the width and height of screen by fetching the screen size. So every other components should be inside these values , but how comes it goes beyond ?

Please guide me with this , thanks in advance !

Update: Here is the code.

import React, { Component } from 'react';
import { View, Image, Dimensions } from 'react-native';
import { connect } from 'react-redux';
import { oneDayPlanSelected, monthlyPlanSelected } from '../../actions';
import { Text, Button, Card } from 'react-native-elements';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 
'react- 
native-responsive-screen';

const windowW= Dimensions.get('window').width;
const windowH = Dimensions.get('window').height;

class PlanSelection extends Component {

onMonthlyPlanButtonPressed() {
    this.props.monthlyPlanSelected();
}

onOneDayPlanButtonPressed(){
    this.props.oneDayPlanSelected();
}

render () {

    const cowMilk = require('../../Images/cow_plan.png');
    const buffaloMilk = require('../../Images/buffalo_plan.png');

    return (
        <View style={styles.containerStyle}>

            <View style={styles.topContainerStyle}>
                <View style={styles.topBlueBoxContainer}>

                    <Text h4 style={styles.introTextStyle}>
                        Now, Choose how you wish to buy ? We have two 
plans.
                    </Text>
                    <View style={styles.imageContainerStyle}>
                        <Image 
                            source={ this.props.milkType === 'Cow Milk' ? 
cowMilk : buffaloMilk }
                            style={styles.topContainerImageStyle}
                        />
                        <View style={styles.choosePlanTextContainerStyle}>
                            <Text h4 style={styles.choosePlanTextStyle}>
                                Choose your plan.
                            </Text>
                        </View>
                    </View>

                </View>
            </View>

            <View style={{flexDirection:'row', justifyContent: 'space- 
evenly'}}>

                <View>
                    <Card
                    containerStyle={{borderRadius: 5, width: windowW/2.2 
}} 
                    >
                        <View style={{ alignItems: 'center' }}>
                            <View style={{flexDirection: 'row'}}>
                                <Text style= 
{styles.planNumberTextStyle}>1</Text>
                                <Text style={{ fontSize: 12, top: 40, 
fontWeight: 'bold' }}>Day</Text>
                            </View>
                            <View style={{ padding: 0 }}>
                            <Text style={styles.planDescpStyle}>Buy One 
day plan, by which we will deliver Cow Milk by Today.</Text>
                            </View>
                            <View style={{ padding: 0 }}>
                            <Text style={styles.planNameTextStyle}>One Day 
Plan</Text>
                            </View>
                        </View>
                        <Button
                        backgroundColor='#2980b9'
                        rightIcon={{name: 'arrow-forward'}}
                        title='Buy'
                        raised
                        onPress= 
{this.onOneDayPlanButtonPressed.bind(this)}
                        />
                    </Card>
                </View>

                <View>
                    <Card
                    containerStyle={{borderRadius: 5,  width: windowW/2.2  
}} 
                    >
                        <View style={{ alignItems: 'center' }}>
                            <View style={{flexDirection: 'row'}}>
                                <Text style= 
{styles.planNumberTextStyle}>30</Text>
                                <Text style={{ fontSize: 12, top: 40, 
fontWeight: 'bold' }}>Day's</Text>
                            </View>
                            <View style={{ padding: 0 }}>
                                <Text style={styles.planDescpStyle}>We 
have various monthly plans, Check In for more info</Text>
                            </View>
                            <View style={{ padding: 0 }}>
                                <Text style= 
{styles.planNameTextStyle}>Monthly Plan</Text>
                            </View>
                        </View>
                        <Button
                        backgroundColor='#2980b9'
                        rightIcon={{name: 'arrow-forward'}}
                        title='Buy'
                        raised
                        onPress= 
{this.onMonthlyPlanButtonPressed.bind(this)}
                        />
                    </Card>
                </View>

            </View>
            <View style={styles.noteContainerStyle}>
                <Text style={styles.noteTextStyle}>We are excited ! Kindly 
select any one plan, and note that Monthly plan has various sub plans. For 
more info kindly choose the plan. </Text>
            </View>

        </View>
    );
   }
}

 const styles = {

containerStyle: {
    flex: 1,
    height: windowH,
    width: windowW, 
},
topBlueBoxContainer:{
    backgroundColor: '#f0ffff',
    height: windowH/1.7,
    justifyContent: 'space-evenly',
},
imageContainerStyle: {
    alignSelf: 'center'
},
topContainerImageStyle: {
    resizeMode: 'contain',
    height: windowH/3
},
introTextStyle: {
    fontSize: 20,
    paddingBottom: windowH/28,
    paddingLeft: windowW/8,
},
choosePlanTextStyle: {
    fontSize: 22
},
choosePlanTextContainerStyle:{
    alignSelf: 'center',
    padding: 15
},
planNameTextStyle: {
    fontSize: 16,
    fontWeight: 'bold'
},
planNumberTextStyle: {
    fontSize: 50,
    fontWeight: 'bold',
    color: '#37BBE1'
},
planDescpStyle: {
    fontSize: 13,
    flexWrap: 'wrap',
    textAlign: 'center'

},
noteTextStyle: {
    fontSize: 10,
    color: '#b2bec3'
},
noteContainerStyle: {
    paddingTop: windowH/30,
    paddingLeft: windowW/25,
    paddingRight: windowW/10,
    bottom: windowW/22
}

};

const mapStateToProps = state => {
return {
    milkType: state.order.milktype
};
};

export default connect(mapStateToProps,  
{oneDayPlanSelected,monthlyPlanSelected})(PlanSelection);

Ui in 4.3 Inch Screen :

enter image description here

Ui in 6 Inch screen :

enter image description here

Check the bottom of the screen, button components and few words are been overflowed. And i have been using react native elements for button and card, is this because of that ? Any idea and Suggestion ?

Upvotes: 4

Views: 18608

Answers (6)

Muhammed Salim
Muhammed Salim

Reputation: 1

useWindowDimentions() will be useful there https://reactnative.dev/docs/usewindowdimensions

Upvotes: 0

RegularGuy
RegularGuy

Reputation: 3686

Ok adding answer (Sorry for the delay) I've found and fixed some problems with your styling

In your root view

containerStyle: {
    flex: 1, //This already tells that it should fill all space available, no need for width or height
    //height: windowH,
    //width: windowW, 
},

topContainerStyle doesn't exist in your code so i have no idea

UPDATE 2 hours later...

i've rebuilt the whole ui only to demonstrate how flex should be used, keep in mind that i have cut some text out, that's because if you need the text to be shown it needs to be short, or be wrapped in a scrollview . I've replaced the card, since it was giving some problems with flex , just style a view, give it some padding and you have a custom card.

I wanted to use react-native-size-matters but i've spent too much time in this , however, a quick tip is , if you can rotate the phone, and the ui is not completelly trash, you have a great UI! c:

https://snack.expo.io/rygco3J74

You can even implement your own button... i personally don't use react-native-elements because i like to do things my own ;) check the expo and try rotating the phone, you can even add a listener to the rotation and change the font size according to the rotation.

Upvotes: 0

RegularGuy
RegularGuy

Reputation: 3686

My way is to use a combination of flex [to fill what i want no matter the size], with the aspectRatio property [to have the same aspect ratio in every screen no matter the size], and the library react-native-size-matters [to have the size units scaled accordint to the screen], so far, the ui is responsive to smartphones and tablets c:. Oh, and never, NEVER i use absolute values, ite makes the ui , as you said , overflow [xd].

Another neat tricks is just not use the height or width property, since they accomodate to their children. I have a bar, with width:'100%', and inside i have a text component with fontSize:moderateScale(30) [react-native-size-matters], and also padding:moderateScale(5). That simple setup renders the same bar , with responsive ui [it´s normal on small screens and bigger on big screens] 7u7

Upvotes: 0

angelos_lex
angelos_lex

Reputation: 1661

Although Dimensions like Harshit mentioned is an option, i don't like it, because when user changes direction from landscape to portrait for example, the values are not updated accordingly and you have an ugly ui.
I prefer setting it up with flex, and make sure that views with lots of content are ScrollViews(for smaller devices).
Also for horizontal space, if it is essential, you can set like 320-340 fixed dp for mobiles, and 820-840 fixed dp for tablets on container view..

Upvotes: 0

TalESid
TalESid

Reputation: 2524

try using flex properties (flex, flexDirection) and alignment with alignItems & jsutifyContent alongwith desired margins & paddings.

Upvotes: 0

HarshitMadhav
HarshitMadhav

Reputation: 5089

You should not use % for providing width and height for components instead you should use Dimensions to get the width and height of the screen and then adjust the component style accordingly like marginTop, marginBottom, etc

const { width, height } = Dimensions.get('window');

OR,

you can do something like this

const windowW= Dimensions.get('window').width
const windowH = Dimensions.get('window').height

and use this as dims:{ height:windowH/2, width: windowW}

Moreover, you can adjust the width and height using windowW/2-30 etc..

Make sure to import Dimensions using-

import {StyleSheet, Dimensions} from 'react-native';

Upvotes: 1

Related Questions