This paper mainly introduces

  • RN development – Application adaptation solution
  • RN development – Routing solutions
  • RN development – How to achieve gradient
  • .

This tutorial assumes that you know the basics of using RN components. Basic use of RN components: juejin.cn/post/694537…

Dinner started

1. Optimize the directory interface

During project development, we optimized the directory structure of the project.

New directory:

  • API: HTTP request module, encapsulating all requests in the application, easy to reuse and later maintenance
  • Components: Common components, the common components of your application are in this directory
  • Asstes: Common resources (images and styles), this is where the images that are native to the application are stored
  • Views: View module, where all the page components are located
  • Utils: Utility module, where all utility functions used in an application are stored
  • Router: The routing module used to configure the route of the application

2. Adaptation of components

The default unit of RN is DP, and the design is usually PX. During development, there will be screen adaptation issues (several ios screen sizes and various Android screen sizes).

Core principles

Although the screen size of the device is not consistent, the proportion of component size and screen width is fixed, which is consistent with the effect drawing element size (PX)/ effect drawing width (PX) = component size (DP)/ screen width (DP), namely: Component size (DP) = Rendering element size (PX) * screen width (DP)/rendering width (PX)

Adapter tools

Create pxtodp.js in utils

// The tool used to complete the adaptation
import { Dimensions } from 'react-native';

// The device width is in dp
const deviceWidthDp = Dimensions.get('window').width;

// Width of the design (640px here), in px
const uiWidthPx = 540;

// convert px to dp (from px to dp in rn)
export default (uiElePx) => {
  return uiElePx * deviceWidthDp / uiWidthPx;
}
Copy the code

3. Route navigation

React Navigation is probably the most mature solution for implementing RN routing Navigation. React Navigation. Reactnavigation

React Navigation Indicates the routing Navigation mode

React Navigation provides tabNavigator, stackNavigator, and DrawerNavigator Navigation modes. Since the drawer Navigation mode is rarely used, we will focus on the first two modes.

React Naigation core dependency

  • React-native gesture-handler: used to switch pages with gestures.
  • React-native – Screens: For the native layer to free up unshown pages and improve app memory usage.
  • React-native safe-area-context: ensures that the page is displayed in a secure area (mainly for bangs).
  • React-native community/ marshall-view: Use the color Settings to return buttons in the header navigation bar.
  • @react-navigation/native: The core of react navigation.
  • React-native reanimated is the core dependency of DrawerNavigator, but it is still included in the core dependency of DrawerNavigator

Start installation:

yarn add @react-navigation/native
yarn add react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
Copy the code

TabNavigator

It can be used if you need to switch routes to wechat by clicking the TAB bar at the bottom of the screentabNavigator.

Basic configuration

  • 1. Install Tabnavigator dependencies
yarn add @react-navigation/bottom-tabs
Copy the code
  • 2, Mount the navigation route container component to the page (router/index.js)
import React, { Component } from 'react';
import { NavigationContainer } from '@react-navigation/native';
function App() {
  return (
    <NavigationContainer>. Add TAB navigation route/Stack navigation route</NavigationContainer>
  );
}
export default App;
Copy the code
  • 3. Configure bottom navigator and navigation view (router/tabNavigator.js)
import React, { Component } from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
// Import the routing view component
import LifeScreen from '.. /views/life/index';
import AmuseScreen from '.. /views/amuse';
import HomeScreen from '.. /views/home/index';
import ServiceScreen from '.. /views/service';
import MineScreen from '.. /views/mine';
// Import the adaptation tool
import pxTodp from '.. /utils/adaptive.js'
// Create a TAB navigator
const Tab = createBottomTabNavigator();

export default function TabNavigator() {
   return({/* TAB navigator component */}
     <Tab.Navigator 
       {/* Default active route */}
       initialRouteName="Home"
       screenOptions={({ route }) = > ({
         tabBarIcon: ({ focused, size }) = > {
           let sourceImg;
           {/* Switch the active TAB page */}
           if (route.name === 'Life') {
             sourceImg = focused
             ? require('.. /asstes/tabBar/life_active_big.png')
             : require('.. /asstes/tabBar/life_default_big.png');
           } else if (route.name === 'Amuse') {
             sourceImg = focused
             ? require('.. /asstes/tabBar/amuse_active_big.png')
             : require('.. /asstes/tabBar/amuse_default_big.png');
           } else if (route.name === 'Home') {
             sourceImg = focused
             ? require('.. /asstes/tabBar/home_active_big.png')
             : require('.. /asstes/tabBar/home_default_big.png');
           } else if (route.name === 'Service') {
             sourceImg = focused
             ? require('.. /asstes/tabBar/service_active_big.png')
             : require('.. /asstes/tabBar/service_default_big.png');
           } else if (route.name === 'Mine') {
             sourceImg = focused
             ? require('.. /asstes/tabBar/mine_active_big.png')
             : require('.. /asstes/tabBar/mine_default_big.png');
           }
           return <Image 
                   source={sourceImg} 
                   focused={focused} 
                   style={{ width: pxTodp(40), height: pxTodp(40) }} 
                 />; }, {})}/* Navigator configuration object */}
       tabBarOptions={{
         {/* Active navigator text color */}
         activeTintColor: 'red',
         {/* Navigator default text color */}
         inactiveTintColor: 'gray',
         {/* Bottom navigator tabbar style */}
         tabStyle : {
           backgroundColor: '#ddd'.paddingBottom: 15.borderRightWidth: 1.borderRightColor: '#fff'> {},}}/* Routing view component */}
       {/* name: indicates the route name. The route matching rule is similar to that of the front-end path. */}
       <Tab.Screen name="Life" component={LifeScreen} 
         {/* title: configures the navigator text */}
         options={{ title:'life'}} / ><Tab.Screen name="Amuse" options={{ title:"Entertainment"}}component={AmuseScreen} />
       <Tab.Screen name="Home" options={{ title:"Home ",}}component={HomeScreen} />
       <Tab.Screen name="Service" options={{ title:"Services"}}component={ServiceScreen} />
       <Tab.Screen name="Mine" options={{ title:"Mine"}}component={MineScreen} />
      </Tab.Navigator>
   )
}
Copy the code
  • 4, Mount TAB navigator to router/index.js
// Import the TAB navigator component
import TabNavigator from './tabNavigator';
function App() {
  return (
    <NavigationContainer>
        <TabNavigator/>
    </NavigationContainer>
  );
}
Copy the code
  • 5. Effect preview

Problems you might encounter

  • When you pull up the soft keyboard, lift the bottom navigator. The following figure



Modify theandroid\app\src\main\AndroidManifest.xml

 
 <activity
      android:name=".MainActivity"
      android:label="@string/app_name"
      android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
      android:launchMode="singleTask"
      android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustResize">
      / / the android: windowSoftInputMode attribute is set to: "stateAlwaysHidden | adjustPan | adjustResize"
      <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
Copy the code

Add animation

The tabNavigator route navigation function is already implemented, and we can add a tabbar animation to it. When the route is active, the Tabbar icon goes from small to large entry animation. The effect is as follows:

  • 1. Import the Animated component
import { Animated } from 'react-native';
Copy the code
  • 2. Declare the animation values in the tabNavigator component to control all tabbar animation states
export default function TabNavigator() {
  // Set the initial value of the TAB - activated zoom animation
  let tabAnimate = {
    Life: new Animated.Value(1),
    Amuse: new Animated.Value(1),
    Home: new Animated.Value(1),
    Service: new Animated.Value(1),
    Mine: new Animated.Value(1),}return <Tab.Navigator
            initialRouteName="Home"
            .
          </Tab.Navigator>
Copy the code
  • 3. During route switchover, animated route configuration is activated and executed
<Tab.Navigator
    initialRouteName="Home"
    screenOptions={({ route }) = > ({
      tabBarIcon: ({ focused, size }) = > {
        let sourceImg;
        // Switch the active TAB page
        if (route.name && focused) {
          // Set TAB icon to 0
          tabAnimate[route.name].setValue(0)
          // Set TAB icon to scale 0 to 1 animation and execute the animation
          Animated.timing(tabAnimate[route.name], { duration: 200.toValue: 1.useNativeDriver: true }).start();
        }
        if (route.name === 'Life') {
          sourceImg = focused
            ? require('.. /asstes/tabBar/life_active_big.png')
            : require('.. /asstes/tabBar/life_default_big.png');
        } else if (route.name === 'Amuse') {
          sourceImg = focused
            ? require('.. /asstes/tabBar/amuse_active_big.png')
            : require('.. /asstes/tabBar/amuse_default_big.png');
        } else if (route.name === 'Home') {
          sourceImg = focused
            ? require('.. /asstes/tabBar/home_active_big.png')
            : require('.. /asstes/tabBar/home_default_big.png');
        } else if (route.name === 'Service') {
          sourceImg = focused
            ? require('.. /asstes/tabBar/service_active_big.png')
            : require('.. /asstes/tabBar/service_default_big.png');
        } else if (route.name === 'Mine') {
          sourceImg = focused
            ? require('.. /asstes/tabBar/mine_active_big.png')
            : require('.. /asstes/tabBar/mine_default_big.png');
        }
        // Use the Animated.Image component and bind the zoom animation value to transform.scale
        return <Animated.Image source={sourceImg} focused={focused} style={{ width: pxTodp(40), height: pxTodp(40), transform: [{ scale: focused ? tabAnimate[route.name] : 1 }] }} />; }})} >... </Tab.Navigator>Copy the code

StackNavigator

This is a stack routing mode, the use of stack page navigation to achieve each interface jump.

Basic configuration

  • 1. Install stackNavigator dependencies
yarn add @react-navigation/stack
Copy the code
  • 2, Mount the navigation route container component to the page (router/index.js)
import React, { Component } from 'react';
import { NavigationContainer } from '@react-navigation/native';
function App() {
  return (
    <NavigationContainer>. Add TAB navigation route/Stack navigation route</NavigationContainer>
  );
}
export default App;
Copy the code
  • Router/StackNavigator.js
import React from 'react'
import { createStackNavigator } from '@react-navigation/stack';
// Import the navigation view component
import LifeScreen from '.. /views/life/index.js';
import AmuseScreen from '.. /views/amuse';
import HomeScreen from '.. /views/home/index';
import ServiceScreen from '.. /views/service';
import MineScreen from '.. /views/mine';
// Generate a Stack navigator
const Stack = createStackNavigator();
export default function stackNavigtor() {
  return (
      <Stack.Navigator initialRouteName="Main">{/* initialRouteName: the route used to configure the default match */} {/* The navigator title at the top of the page defaults to name, which can be customized with options.title */}<Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Life" component={LifeScreen} options={{
          // titleConfigure the top navigator titletitle:'Life ',}}/>
        <Stack.Screen name="Amuse" component={AmuseScreen} options={{ title:}} />
        <Stack.Screen name="Service" component={ServiceScreen} />
        <Stack.Screen name="Mine" component={MineScreen} />
        <Stack.Screen name="Search" component={Search} options={{ 
        // headerShownHide the top navigatorheaderShown: false}} / >
      </Stack.Navigator>)}Copy the code
  • 4, Mount TAB navigator to navigation routing container (router/ stackNavigation.js)
import StackNavigator from './stackNavigator.js';
function App() {
  return (
    <NavigationContainer>
        <StackNavigator/>
    </NavigationContainer>
  );
}
Copy the code
  • 5. Effect preview

Routing modes are nested

In actual business scenarios, our application often uses TabNavigator and StackNavigator navigation modes at the same time. For example, TabNavigator related routes are displayed after the application is entered, and some routing screens need to jump to non-TabNavigator pages. As shown in the following figure, nesting of the two routing modes is required for this scenario

  • 1, Mount the navigation route container component to the page (router/index.js)
  • Router/StackNavigator.js = router/stackNavigator.js
    import React from 'react'
    import { createStackNavigator } from '@react-navigation/stack';
    // Import the navigation view component
    import DetailScreen from '.. /views/detail';
    import ListScreen from '.. /views/list';
    / /... Other non-tab pages
    const Stack = createStackNavigator();
    export default function stackNavigtor() {
      return (
        <Stack.Navigator>
          <Stack.Screen name="Detail" component={DetailScreen} />
          <Stack.Screen name="List" component={ListScreen} />{/* Other screen components...... * /}</Stack.Navigator>)}Copy the code
  • 3. Configure Tab navigator (Router/TabNavigator.js) : The same as the basic configuration in tabNavigator
  • 4, Import Tab navigator and mount it to Stack navigator (router/ StackNavigator.js)
    // Import Tab navigator
    import TabNavigator from './tabNavigator.js';
    export default function stackNavigtor() {
     return (
       <Stack.Navigator
          initialRouteName="Main"
       >{/* initialRouteName="Main" displays Tab navigation routes */}<Stack.Screen name="Main" component={TabNavigator} />
         <Stack.Screen name="Detail" component={DetailScreen} />
         <Stack.Screen name="List" component={ListScreen} />{/ *... * /}</Stack.Navigator>)}Copy the code
  • Import and mount the Stack navigator to the navigation route container component (router/index.js)
    import StackNavigator from './stackNavigator.js';
         function App() {
           return (
             <NavigationContainer>
                 <StackNavigator/>
             </NavigationContainer>
           );
    }
    Copy the code

Programmatic navigation

When using the Stack navigator, we sometimes need to switch routes through code, such as clicking on a point on the page or the button navigation of a custom navigator: the navigator passes in the props property navigation for each screen component through which to switch routes

Navigation. Navigate (routerName)

  • Effects: : Switching to a routing page. Switching to the current page is invalid. For example, A switch from the detail page of commodity A to the detail page of commodity B is essentially A switch from the detail page to the detail page only with different routing parameters.
  • Parameter: routerName (Route name)

Navigation. Push (routerName)

  • Effect: Switch route page, add to stack can switch to the current page
  • Parameter: routerName (Route name)

Navigation. Replace (routerName)

  • Function: Switch to a new route and replace the old route record
  • Parameter: routerName (Route name)

Navigation. Goback ()

  • Function: Returns the previous routing page

Navigation. PopToTop ()

  • Returns to the first routing page in the routing stack
import React from 'react'
import { View, Text, Button } from 'react-native'
import pxTodp from '.. /.. /utils/adaptive';
export default function Home(props) {
  return (
    <View style={{ flex: 1.justifyContent: "center", alignItems: "center}} ">
      <View style={{ flexDirection: "row", justifyContent: "center", alignItems: "center", height: pxTodp(500) }}>
        <Text style={{ marginRight: pxTodp(20) }}>Navigate to the life page</Text>
        <Button title="Jump" onPress={()= > { props.navigation.navigate("Life")}}></Button>
      </View>
      <View style={{ flexDirection: "row", justifyContent: "center", alignItems: "center", height: pxTodp(500) }}>
        <Text style={{ marginRight: pxTodp(20) }}>Jump to Life page (Push)</Text>
        <Button title="Jump" onPress={()= > { props.navigation.push("Life")}}></Button>
      </View>
      <View style={{ flexDirection: "row", justifyContent: "center", alignItems: "center", height: pxTodp(500) }}>
        <Text style={{ marginRight: pxTodp(20) }}>Go to the life page Replace</Text>
        <Button title="Jump" onPress={()= > { props.navigation.replace("Life")}}></Button>
      </View>
      <View style={{ flexDirection: "row", justifyContent: "center", alignItems: "center", height: pxTodp(500) }}>
        <Text style={{ marginRight: pxTodp(20) }}>Return to superior page</Text>
        <Button title="Jump" onPress={()= > { props.navigation.goback()}}></Button>
      </View>
        <View style={{ flexDirection: "row", justifyContent: "center", alignItems: "center", height: pxTodp(500) }}>
        <Text style={{ marginRight: pxTodp(20) }}>Jump page</Text>
        <Button title="Jump" onPress={()= > { props.navigation.popToTop()}}></Button>
      </View>
     </View >
  )
}
Copy the code

Routing parameters

Passing parameters

The second argument to most navigation apis is the Params object through which routing parameters are passed

<Button
   title="Skip to details"
   onPress={() = > {
       navigation.navigate('Details', {
           itemId: 86.otherParam: 'You want to pass parameters'}); }} / >Copy the code

Accept parameters

Obtain the parameters from route.params of props

function DetailsScreen({ route, navigation }) {
 const { itemId } = route.params;
 const { otherParam } = route.params;
 return(...). }Copy the code

Initialize route parameters

<Stack.Screen
 name="Details"
 component={DetailsScreen}
 initialParams={{ itemId: 42}} / > <Copy the code

4, gradient

RN gradient can be realized by the component of React-native Linear-gradient

  • Install dependencies
yarn add react-native-linear-gradient
Copy the code
  • Use in pages
import React from 'react';
import {Text, View} from 'react-native';
import LinearGradinet from 'react-native-linear-gradient';

export default class Home extends React.Component {
  render() {
    return (
      <View style={{ flex: 1.justifyContent: "center", alignItems: "center}} ">
      <View style={{ flexDirection: "column", justifyContent: "center", alignItems: "center">
        <Text>Home page</Text>{/*start: the location where the gradient starts, x and y are 0-1 *end: the location where the gradient ends, x and y are 0-1 *colors: array, each element of the array represents the total number of colors *locations: Used to control the range of color gradient, the value is array, each element of the array represents the end position of the last color gradient and the start position of the current color gradient size range 0-1 */}<LinearGradinet
          start={{ x: 0.y: 0 }}
          end={{ x: 1.y: 0 }}
          colors={['#9b63cd', '#e0708c', '#000000']}
          style={{ width: 200.height: 200}} / >{/* Use the default location */}<LinearGradinet
          start={{ x: 0.y: 0 }}
          end={{ x: 1.y: 0 }}
          colors={['#9b63cd', '#e0708c', '#000000']}
          style={{ width: 200.height: 200 }}
          locations={[0, 0.5.1]} / >{/* Custom location */}<LinearGradinet
          start={{ x: 0.y: 0 }}
          end={{ x: 1.y: 0 }}
          colors={['#9b63cd', '#e0708c', '#000000']}
          style={{ width: 200.height: 200 }}
          locations={[0.1, 0.2.0.5]} / >
      </View></View > ); }}Copy the code

5. Rotation chart

Swiper can be implemented using the React-native swiper component

  • Install dependencies
yarn add react-native-linear-gradient
Copy the code
  • Use in pages
import React, { useState } from 'react'
import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native'
import Swiper from 'react-native-swiper';
import pxTodp from '.. /.. /utils/adaptive';
export default function bannerSwiper() {
  const [state, setState] = useState({
    swiperList: [{imgURL: "http://image2.suning.cn/uimg/cms/img/161641067864122785.jpg?format=_is_1242w_610h".jumpLink: "www.baidu.com"
      },
      {
        imgURL: "http://oss.suning.com/aps/aps_learning/iwogh/2021/03/22/10/iwoghBannerPicture/894481af3bb740aeb9ff24c91ca63f4b.png?form at=_is_1242w_610h".jumpLink: "www.baidu.com"
      },
      {
        imgURL: "http://oss.suning.com/aps/aps_learning/iwogh/2021/03/22/10/iwoghBannerPicture/b5160fc4515d41a2bff2552adaef8510.png?form at=_is_1242w_610h".jumpLink: "www.baidu.com"
      },
      {
        imgURL: "https://oss.suning.com/adpp/creative_kit/material/picture/20200706-0b704b452c38418897f43d944583da53693a083846d5484c.jpg ".jumpLink: "www.baidu.com"}]})return (
    <View style={styles.container}>
      <View style={styles.swiperContainer} >{/* removeClippedSubviews={false}<Swiper
          style={styles.wrapper}
          showsButtons={false}
          autoplay={true}
          paginationStyle={styles.paginationStyle}
          dotStyle={styles.dotStyle}
          activeDotStyle={styles.activeDotStyle}
          removeClippedSubviews={false}
        >
          {state.swiperList.map(e => {
            return <TouchableOpacity key={e.imgURL} style={{
              borderRadius: pxTodp(20),
              overflow: "hidden",
              height: pxTodp(150),}}activeOpacity={1}><Image source={{ uri: e.imgURL }} style={styles.bannerImg} />
            </TouchableOpacity>
          })}
        </Swiper>
      </View></View > ) } const styles = StyleSheet.create({ container: { flexDirection: "row", justifyContent: "center", backgroundColor: "white", height: pxTodp(165) }, swiperContainer: { width: pxTodp(497), height: pxTodp(150), }, paginationStyle: { position: "absolute", bottom: 0 }, activeDotStyle: { opacity: 1, backgroundColor: Opacity: 0.5, width: pxTodp(10), height: pxTodp(10), borderRadius: pxTodp(10) }, wrapper: { }, bannerImg: { width: pxTodp(497), height: pxTodp(150), resizeMode: "cover", } })Copy the code

The last

The process of establishing RN may not be smooth, if you need help or technical communication with the same monkey welcome to add V: GG_0632