cross platform compatibility

I must say the whole react-native expo development experience has been quite the challenge and quite the disappointment.

I’ve built an app using create-react-native-app and running on expo. On a IOS device phone, tablet, real device, simulator everything works and I’ve been able to create an app that looks like I want. The app contains video playback at it’s heart and this works fine with the Video package from expo.

Running on Android is a whole other matter. formatting is different, component layout is different, videos don’t play. The cross-platform compatibility seems seriously flawed. The promise of cross-platform development & deployment doesn’t seem like a real thing at all.

Maybe I’m just frustrated because the whole Angular path was much the same.

Any suggestions/tutorials appreciated.

Hey @ptmagnuson,

Sorry your experience with the RN/Expo ecosystem has been unpleasant so far. For the most part, things usually do translate pretty cleanly between iOS and Android but there are certainly some nuances you have to be mindful of between the two. Could you elaborate on the following:

  • Formatting is different
  • Component layout is different
  • Videos don’t play (Where are you loading from? What file types?)

With more information, I might be able to lend a hand and see if we can get your Android version in a place where you want it to be. Some code examples would be great for the formatting and component layout issues.

Cheers,

Adam

button colors are different - Prev, Next
title text is centered on IOS not on android

static navigationOptions = ({ navigation }) => ({
    title: 'The Buddha Path',
    headerTitleStyle: { color: dcolor.bronze },
    headerTintColor: dcolor.bronze,
    headerStyle: { backgroundColor: dcolor.logoburgundy },
    headerRight: (
      <View style={{ flex: 2, flexDirection: 'row' }}>
        <Button
          title="Prev"
          onPress={() => navigation.state.params.handlePrev()}
          color={dcolor.bronze}
        />
        <Button
          title="Next"
          onPress={() => navigation.state.params.handleNext()}
          color={dcolor.bronze}
        />
      </View>
    ),
    headerLeft: (
      <TouchableHighlight
        onPress={() =>
          //navigation.pop()} title="press">
          navigation.navigate('DrawerOpen')
        }
      >
        {/* <Image
          source={require('../assets/icons/ic_menu_black_48dp.png')}
          style={{ height: 30, width: 30 }}
        /> */}
        <Text style={loc.leftmenu}> Menu</Text>
      </TouchableHighlight>
    )
  })

ios

android

using the following code to format text strings into all caps and larger font of the first character of each word. works fine on IOS, crashes on android

invoked with

<Mantra text='HAA!  HAA!  HAA!  HAA!' allcaps  />

produces:
haa

code implementation

export default class Mantra extends React.Component {
  render () {
    console.log('mantra ', this.props.audio)
    return (
      <Text>
        {this.props.text.split(' ').map((word, i) => (
          <Text key={i}>
            {!this.props.allcaps ? (
              <Text>
                <Text style={styles.caps}>
                  {word.substr(0, 1).toUpperCase()}
                </Text>
                <Text style={styles.rest}>{word.substr(1).toUpperCase()} </Text>
              </Text>
            ) : (
              <Text style={styles.caps}>{word.toUpperCase()} </Text>
            )}
          </Text>
        ))}
        {this.props.audio ? (
          <Text>
            <Text>{'  '}</Text>
            <Maudio src={this.props.audio} />
          </Text>
        ) : null}
      </Text>
    )
  }
}

error log

Unexpected view type nested under text node: class abi26_0_0.com.facebook.react.uimanager.LayoutShadowNode
buildSpannedFromShadowNode
    ReactBaseTextShadowNode.java:108
buildSpannedFromShadowNode
    ReactBaseTextShadowNode.java:96
spannedFromShadowNode
    ReactBaseTextShadowNode.java:175
onBeforeLayout
    ReactTextShadowNode.java:162
notifyOnBeforeLayoutRecursive
    UIImplementation.java:933
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
notifyOnBeforeLayoutRecursive
    UIImplementation.java:931
updateViewHierarchy
    UIImplementation.java:689
dispatchViewUpdates
    UIImplementation.java:654
onBatchComplete
    UIManagerModule.java:663
onBatchComplete
    NativeModuleRegistry.java:136
onBatchComplete
    CatalystInstanceImpl.java:145
run
    NativeRunnable.java
handleCallback
    Handler.java:751
dispatchMessage
    Handler.java:95
dispatchMessage
    MessageQueueThreadHandler.java:31
loop
    Looper.java:154
run
    MessageQueueThreadImpl.java:194
run
    Thread.java:761

Video plays on ios but not on Android. video is loaded from a local asset.

import React from "react";
import { StyleSheet, Text, View } from "react-native";
import { Sound, Video } from "expo";

export default class WarmUp extends React.Component {
  constructor(props) {
    super(props);
    this.playbackObject = null;
    const { params } = this.props.navigation.state;
    this.startTime = params ? params.startTime : 0;
    this.endTime = params ? params.endTime : 772000;

    console.log("WarmUp", this.startTime, this.endTime);
  }

  _handleVideoRef = component => {
    this.playbackObject = component;
    // console.log('handlevideo');
  };

  _onPlaybackStatusUpdate = playbackStatus => {
    if (playbackStatus.positionMillis > this.stopTime) {
      console.log("over");
      this.playbackObject.stopAsync();
      this.props.navigation.goBack();
    }
  };

  // componentDidMount() {
  //   this.playbackObject.presentFullscreenPlayer();
  // }

  render() {
    return (
      <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
        <Video
          source={require("./assets/Routine.mov")}
          ref={this._handleVideoRef}
          positionMillis={this.startTime}
          shouldPlay
          onPlaybackStatusUpdate={this._onPlaybackStatusUpdate}
          resizeMode="contain"
          useNativeControls
          usePoster={false}
          style={{ width: 900, height: 550 }}
        />
      </View>
    );
  }
}

ios screen

android screen

Adam,

thank you very much for offering to look at these issues. I very much appreciate your interest.

Font loading appears to be different on android. Have followed tutorials on expo Font loading.

async componentWillMount() {
    try {
      await Font.loadAsync({
        pinyon: require('./assets/fonts/PinyonScriptRegular.ttf'),
        wingdings: require('./assets/fonts/wingdings.ttf'),
        times: require('./assets/fonts/TimesNewRoman.ttf'),
        timesbold: require('./assets/fonts/TimesNewRomanBold.ttf'),
        timesbolditalic: require('./assets/fonts/TimesNewRomanBoldItalic.ttf'),
        timesitalic: require('./assets/fonts/TimesNewRomanItalic.ttf'),
        mantra: require('./assets/fonts/Times-RomanSC.otf'),
        ionicons: require('./node_modules/@expo/vector-icons/fonts/Ionicons.ttf')
      })
      this.setState({ fontsLoaded: true })
      Text.defaultProps.style = {
        fontFamily: 'times',
        fontSize: 18,
        textAlign: 'center'
      }
      console.log('fonts loaded')
    } catch (error) {
      console.log('error loading icon fonts', error)
    }
  }

on ios using the wingdings font

export default function WW () {
  return <Text style={styles.ww}>]</Text>
}

ww: {
    fontFamily: 'wingdings'
  },

usage is

<Text style={loc.h1}><WW /> The Truth Regarding Suffering <WW /></Text> 

on ios this produces
wing%20ios

on android
wing%20android

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.