Upgrade to Pro — share decks privately, control downloads, hide ads and more …

It all starts with navigation

It all starts with navigation

For the past 2.5 years I've been working on a bunch of projects, all aiming to expose some native capabilities to be controlled from JavaScript in React Native app. Most notable ones were: native driver support for Animated and two libraries: React Native Gesture Handler and Reanimated. All these projects were inspired by needs of navigation libraries and were meant to fill the gap between platform native navigation solutions and ones that are available in React Native.

Our React Native projects often starts by deciding whether to go with native navigation (react-native-navigation) or JS navigation library (react-navigation). But given all these improvements can we still call react-navigation "not native"? In this talk we will learn how Gesture Handler and Reanimated libraries came to live with navigation being the driving force. In this context I will discuss how far is react-navigation from finally proclaiming the badge of really native navigation library.

Krzysztof Magiera

September 05, 2018
Tweet

More Decks by Krzysztof Magiera

Other Decks in Technology

Transcript

  1. It all starts with navigation Krzysztof Magiera (@kzzzf)

  2. Evolution of navigation 8 16 24 32 40 Presence Months

    from now NavigatorIOS ex-navigator ex-navigation react-navigation react-native-navigation Navigator Experimental Navigator
  3. NavigatorIOS

  4. NavigatorIOS

  5. “Navigator” • Cross platform • Route configuration concept introduced •

    No special native components required
  6. Navigator – perf issues

  7. state = { fade: new Animated.Value(0) }; 1. Create value

    <Animated.View style={{ opacity: this.state.fade }} /> 2. Hook it up as a view attribute Animated.timing( this.state.fade, { toValue: 1, } ).start(); 3. Animate value 4. Or attach it to an event 5. Combine/process values const fade = Animated.multiply( this.state.factor, this.state.scrollY.interpolate({ inputRange: [0, 300], outputRange: [1, 0] }) ); <Animated.ScrollView onScroll={event L> { const yoffset = event.nativeEvent.contentOffset.y; this.state.scrollX.setValue(yoffset); }} > <Animated.ScrollView onScroll={Animated.event([ { // event.nativeEvent.contentOffset.y nativeEvent: { contentOffset: { y: this.state.scrollY } } } ])} > Animated
  8. NavigatorExperimental

  9. Navigator ¯\_(ϑ)_/¯

  10. react-native-navigation App App App App App

  11. react-native-navigation Style object format { // Common navBarTextColor: '#000000', //

    change the text color of the title (remembered across pushes) navBarTextFontSize: 18, // change the font size of the title navBarTextFontFamily: 'font-name', // Changes the title font navBarBackgroundColor: '#f7f7f7', // change the background color of the nav bar (remembered across pushes) navBarCustomView: 'example.CustomTopBar', // registered component name navBarComponentAlignment: 'center', // center/fill navBarCustomViewInitialProps: {}, // navBar custom component props navBarButtonColor: '#007aff', // Change color of nav bar buttons (eg. the back button) (remembered across pushes) topBarElevationShadowEnabled: false, // (Android - default: true, iOS - default: false). Disables TopBar elevation shadow on Lolipop and navBarHidden: false, // make the nav bar hidden navBarHideOnScroll: false, // make the nav bar hidden only after the user starts to scroll navBarTranslucent: false, // make the nav bar semi-translucent, works best with drawUnderNavBar:true navBarTransparent: false, // make the nav bar transparent, works best with drawUnderNavBar:true, navBarNoBorder: false, // hide the navigation bar bottom border (hair line). Default false drawUnderNavBar: false, // draw the screen content under the nav bar, works best with navBarTranslucent:true drawUnderTabBar: false, // draw the screen content under the tab bar (the tab bar is always translucent) navBarBlur: false, // blur the entire nav bar, works best with drawUnderNavBar:true tabBarHidden: false, // make the screen content hide the tab bar (remembered across pushes) statusBarHidden: false, // make the status bar hidden regardless of nav bar state statusBarTextColorScheme: 'dark', // text color of status bar, 'dark' / 'light' (remembered across pushes) navBarSubtitleColor: 'red', // subtitle color navBarSubtitleFontFamily: 'font-name', // subtitle font, 'sans-serif-thin' for example navBarSubtitleFontSize: 13, // subtitle font size screenBackgroundColor: 'white', // Default screen color, visible before the actual react view is rendered orientation: 'portrait' // Sets a specific orientation to a modal and all screens pushed to it. Default: 'auto'. Supported values: 'auto' disabledButtonColor: '#ff0000' // chnaged the navigation bar button text color when disabled. rootBackgroundImageName: 'iOS: <name of image in Images.xcassets>. Android: <name of drawable>', // Static while you transition between
  12. Gestures - PanResponder UI Thread JS Thread • Receive hardware

    events • Send to JS • Calculate pan translation • Generate pan event • Handle event & request UI update • Update UI
  13. react-native-gesture-handler Handler Parameters Event attributes Pan minDist, minPointers translationXY, absoluteXY

    Pinch scale, focalXY, velocity Tap numberOfTaps, maxDuration numberOfPointers Rotation rotation, anchorXY, velocity
  14. <RotationGestureHandler onGestureEvent={Animated.event( [{ nativeEvent: { rotation: this.rotationValue } }], {

    useNativeDriver: true } )} > <Animated.View style={animatedTransforms} /> </RotationGestureHandler>; react-native-gesture-handler
  15. react-navigation • Screen transition animations running on UI Thread –

    nativeDriver / reanimated • Native gestures for back swipe • Gesture-handler backed drawer
  16. native? react-navigation

  17. None
  18. None
  19. None
  20. None
  21. func willMove(toWindow newWindow: UIWindow?) Native view’s events func didMoveToWindow() void

    onAttachedToWindow() void onDetachedToWindow()
  22. Resource management • Memory • System resources like camera lock

    or GPS • CPU – view’s redraw loops
  23. Screens does not behave like regular Views

  24. Style object format { // Common navBarTextColor: '#000000', // change

    the text color of the title (remembered across pushes) navBarTextFontSize: 18, // change the font size of the title navBarTextFontFamily: 'font-name', // Changes the title font navBarBackgroundColor: '#f7f7f7', // change the background color of the nav bar (remembered across pushes) navBarCustomView: 'example.CustomTopBar', // registered component name navBarComponentAlignment: 'center', // center/fill navBarCustomViewInitialProps: {}, // navBar custom component props navBarButtonColor: '#007aff', // Change color of nav bar buttons (eg. the back button) (remembered across pushes) topBarElevationShadowEnabled: false, // (Android - default: true, iOS - default: false). Disables TopBar elevation shadow on Lolipop and navBarHidden: false, // make the nav bar hidden navBarHideOnScroll: false, // make the nav bar hidden only after the user starts to scroll navBarTranslucent: false, // make the nav bar semi-translucent, works best with drawUnderNavBar:true navBarTransparent: false, // make the nav bar transparent, works best with drawUnderNavBar:true, navBarNoBorder: false, // hide the navigation bar bottom border (hair line). Default false drawUnderNavBar: false, // draw the screen content under the nav bar, works best with navBarTranslucent:true drawUnderTabBar: false, // draw the screen content under the tab bar (the tab bar is always translucent) navBarBlur: false, // blur the entire nav bar, works best with drawUnderNavBar:true tabBarHidden: false, // make the screen content hide the tab bar (remembered across pushes) statusBarHidden: false, // make the status bar hidden regardless of nav bar state statusBarTextColorScheme: 'dark', // text color of status bar, 'dark' / 'light' (remembered across pushes) navBarSubtitleColor: 'red', // subtitle color navBarSubtitleFontFamily: 'font-name', // subtitle font, 'sans-serif-thin' for example navBarSubtitleFontSize: 13, // subtitle font size screenBackgroundColor: 'white', // Default screen color, visible before the actual react view is rendered orientation: 'portrait' // Sets a specific orientation to a modal and all screens pushed to it. Default: 'auto'. Supported values: 'auto' disabledButtonColor: '#ff0000' // chnaged the navigation bar button text color when disabled. rootBackgroundImageName: 'iOS: <name of image in Images.xcassets>. Android: <name of drawable>', // Static while you transition between // iOS only statusBarTextColorSchemeSingleScreen: 'light', // same as statusBarTextColorScheme but does NOT remember across pushes statusBarHideWithNavBar: false, // hide the status bar if the nav bar is also hidden, useful for navBarHidden:true statusBarBlur: false, // blur the area under the status bar, works best with navBarHidden:true disabledBackGesture: false, // default: false. Disable the back gesture (swipe gesture) in order to pop the top screen. disabledSimultaneousGesture: true, // default: true. Disable simultaneous gesture recognition.
  25. <ScreenContainer> <Screen active>{children}</Screen> </ScreenContainer>

  26. <ScreenContainer> <Screen>{tab1}</Screen> <Screen active>{tab2}</Screen> <Screen>{tab3}</Screen> </ScreenContainer>

  27. <ScreenContainer> <Screen>{root}</Screen> <Screen>{profile}</Screen> <Screen active>{details}</Screen> </ScreenContainer>

  28. <ScreenContainer> <Screen>{root}</Screen> <Screen active>{profile}</Screen> <Screen active>{details}</Screen> </ScreenContainer>

  29. <ScreenContainer> <Screen>{root}</Screen> <Screen active>{profile}</Screen> </ScreenContainer>

  30. react-native-screens

  31. react-native-screens react-navigation !

  32. react-native-screens react-navigation ! ! Expo

  33. None
  34. Thank you! Krzysztof Magiera krzys@swmansion.com @kzzzf