Views looks different in react native for android and ios

2k Views Asked by At

I am creating an app on react-native but views look different in both android and ios. Views are fine on android but on ios they look different. Can you look into sample component and let me know where I am doing wrong or how can I make both views consistent?

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  Image,
  View,
  ListView,
  TouchableOpacity,
  Dimensions,
  ScrollView,
  ActivityIndicator,
  AsyncStorage
} from 'react-native';
import Api from '../lib/api.js';
import { NavigationActions } from 'react-navigation';
import {Column as Col, Row} from 'react-native-flexbox-grid';

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

const photos= [{uri: 'https://portal.lancercorp.com/Content/Images/missing.png'}];

const tasks =[];

export default class CategoryDetailScreen extends React.Component {

  constructor(props){
    super(props)
    this._onScroll = this._onScroll.bind(this)
    this._statusStyle = this._statusStyle.bind(this)
    this._renderImage = this._renderImage.bind(this)

    this.categoryDetail(this.props.navigation.state.params.id);
    this.state = {

      totalPictures: photos.length,
      value: 1,
      name: '',
      photos: photos,
      location: '',
      tasks : tasks
    }
  }

  static navigationOptions = {
      title: '',
      headerStyle: {
        backgroundColor: '#544849',
      },
      tintColor: 'transparent',
      header: null,
      headerLeft: <TouchableOpacity><Image source={require('../../img/close.png')} style={{marginTop: 10, marginLeft:10}} /></TouchableOpacity>
    };

  _onScroll(e){
    var contentOffset = e.nativeEvent.contentOffset.x;
    this.setState(previousState => {
        return { value: ((contentOffset/width)+1).toFixed(0)};
    });
  }

  _statusStyle(status){
    if(status == 'Completed'){
      return {fontSize: 14, color: '#7da61d',fontWeight: 'bold'};
    }
    else if(status == 'InComplete'){
      return {fontSize: 14, color: 'orange',fontWeight: 'bold'}
    }
  }

  _renderImage(status){
    if(status == 'Completed'){
      return (
              <Image source={require('../../img/ic-check-circle-24px.png')} />
            );
    }
    else if(status == 'InComplete'){
      return null;
    }
  }

  categoryDetail(data) {
        // let current_user = await AsyncStorage.getItem('current_user');
        let current_user = AsyncStorage.getItem('current_user', async(error, result) => {
          result = JSON.parse(result);
          let headers = {
            "access-token": result["access-token"],
            "client": result["client"],
            "uid": result["uid"],
            "token-type": result["token-type"],
            "content-type": result["content-type"],
            "expiry": result["expiry"]
          };
        let response = await Api.apiCall('/api/v1/categories/' + data +'.json', 'GET', {}, headers);
        let categoryDetailData = response.body;

          this.setState({name: categoryDetailData['name'], location: categoryDetailData['location'], tasks: categoryDetailData['submissions']});
                            console.log("_______________________________________________")
                            console.log(tasks)
                            console.log("$$$$$$$$$$$$$$$$$$$$$$$$$$")
                            console.log(categoryDetailData['submissions'])

          if (categoryDetailData['photos'] == null || categoryDetailData['photos'] == ''){
              this.setState({totalPictures: 1, photos: [{uri: 'https://portal.lancercorp.com/Content/Images/missing.png'}]})
              return categoryDetailData;
          }else{
          this.setState({totalPictures: categoryDetailData['photos'].length, photos: categoryDetailData['photos']})
              return categoryDetailData;
          }

        })
  };

  render() {
    const { navigate } = this.props.navigation;
    return (
      <View style={styles.mainContainer}>
        <View style={styles.headerContainer}>
              <TouchableOpacity
                  onPress={this._onPressButton}>
               <Image source={require('../../img/back.png')}>
               </Image>
            </TouchableOpacity>
            <Text style={styles.headerText}>
              {this.state.name}
            </Text>
            <View style={{width:20}}>
            </View>
        </View>
        <View style={styles.upperContainer}>
          <ScrollView horizontal={true} pagingEnabled={true} showsHorizontalScrollIndicator={false} onScroll={this._onScroll} >
            {this.state.photos.map((source, i) => {
              return (
                <Image
                  key={i} // we will use i for the key because no two (or more) elements in an array will have the same index
                  style={styles.images}
                  source={source}
                />
              );
            })}
          </ScrollView>
          <View style={styles.locationContainer}>
            <Image source={require('../../img/location_white.png')}>
            </Image>
            <Text style={styles.locationText}>
              {this.state.location}
            </Text>
          </View>
          <View style={styles.numberContainer}>
            <Text style={styles.numberText}>
              {this.state.value}/{this.state.totalPictures}
            </Text>
          </View>
        </View>
        <View style={styles.lowerContainer}>
            <ScrollView showsVerticalScrollIndicator={false}>
              <Row size={12}>
              {this.state.tasks.map((mySource, j)=>{
                return (
                mySource.map((source, i)=>{
                  return (
                  <Col sm={6} md={4} lg={3} style={styles.submissionBox}>
                    <TouchableOpacity onPress={() => navigate('SubmissionForm', {data: source})}>
                      <View style={styles.rowContainer}>
                        <View style={styles.contentContainer}>
                          <View style={styles.contentSubContainer1}>
                            {this._renderImage(source.status)}
                          </View>
                          <View style={styles.contentSubContainer2}>
                            <Text key={i} style={styles.idText}>
                              {source.id}
                            </Text>

                            <Text style={this._statusStyle(source.status)}>
                              {source.status}
                            </Text>
                          </View>
                        </View>
                      </View>
                    </TouchableOpacity>
                  </Col>
                  );})
                );}
              )}
              </Row>
            <TouchableOpacity  onPress={() => navigate('SubmissionForm')}>
              <View style={{backgroundColor: 'transparent', marginLeft: 25}}>
                <Image source={require('../../img/btn.png')} style={styles.buttonImage}>
                  <Text style={styles.buttonText}>
                    NEW SUBMISSION
                  </Text>
                </Image>
              </View>
            </TouchableOpacity>
            </ScrollView>
        </View>
      </View>
    );
  }

}

const styles = StyleSheet.create({
  mainContainer: {
    flex: 1,
  },
  upperContainer:{
    flex: 1,
  },
  lowerContainer:{
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'flex-start',
    padding: 6,
  },
  rowContainer:{
    flex: 1,
    flexDirection: 'row',
    marginBottom: 12,
    backgroundColor: 'black',
  },
  contentContainer:{
    flex: 1,
    flexDirection: 'column',
    padding: 10,
    height: 132,
    backgroundColor: 'white',
  },
  contentSubContainer1:{
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
  contentSubContainer2: {
    flex: 3,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
  headerContainer: {
      padding: 12,
      flexDirection: 'row',
      justifyContent: 'space-between',
      alignItems: 'center',
      backgroundColor: '#544849',
  },
  submissionBox: {
      padding: 6,
  },
  headerText:{
    color: '#ffffff',
    fontWeight: 'bold',
    fontSize: 20,
  },
  buttonText:{
    fontSize: 18,
    color: 'white',
    marginBottom: 12,
    padding:18,
    textAlign: 'center'
  },
  buttonImage:{
    justifyContent:'center',
    alignItems: 'center',
  },
  headerSmallText:{
    color: '#ffffff',
    fontWeight: 'bold',
    fontSize: 12,
  },
  images:{
    width: width,
    height: height/2-35,
  },
  locationContainer:{
    flexDirection: 'row',
    justifyContent: 'flex-start',
    position: 'absolute',
    top: (height/2)-80,
    left: 20,
  },
  locationText:{
    color: '#ffffff',
    fontWeight: 'bold',
    marginLeft: 10,
    fontSize: 12,
  },
  numberText:{
    color: '#ffffff',
    fontWeight: 'bold',
    fontSize: 12,
  },
  numberContainer:{
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    position: 'absolute',
    width: 30,
    top: 10,
    left: width-40,
    backgroundColor: 'rgba(52, 52, 52, 0.9)',
    borderRadius:10,
  },
  idText:{
    fontSize: 15,
    color: '#4a4a4a',
    fontWeight: 'bold'
  },
});

Android Screen: enter image description here

IOS Screen:

enter image description here

Main issue is with transparent bg and headers.

2

There are 2 best solutions below

0
On

you can set statusbar to hidden <StatusBar hidden />

0
On

Put this in your root app. In my case it was App.js

<StatusBar animated={true} backgroundColor="#fff" barStyle="dark-content"/>

Hope this helps