The goal is to use React-Native to create the react-Native App, which is inspired by GitHub’s popular Chinese-Poetry program and its spinoff, app-poems. Chinese-poetry Project is the most comprehensive database of Chinese ancient poetry, with nearly 14,000 ancient poets in tang and Song dynasties, nearly 55,000 Tang poems and 260,000 Song poems. During the Song Dynasty, there were 1,564 ci writers and 21,050 ci poems. Our App will use these data to realize the recommendation, list display, detail display and other functions of ancient poems. Now we are going to carry out the first stage of work, which is the basic construction of the project. In this stage, we will mainly involve the following aspects:

  1. react-nativedebugging
  2. usereact-navigationImplementing Route Management
  3. usereact-native-vector-iconsRealize the icon

  1. After startup, the welcome page will be displayed, and then the home page will be automatically redirected
  2. The home page displays poems in vertical rows
  3. Poetry information list display, click to jump to the details page

start

After installing the react-native environment, run the react-native init RNPoetry command to generate the project, enter the directory and run the yarn run ios or Android command to start the project. First of all, let’s not rush into project development but learn some debugging techniques in React-Native.

First, let’s take a look at RN’s Developer Menu. Developer Menu is a react-Native Developer Menu to help developers debug RN applications. To open RN, invoke Command to + M in the Android emulator. ⌘ to open quickly in the iOS emulator by using the Command + D shortcut. There are many options in Developer Menu, among which we often use:

  1. ReloadManually reload the project with the shortcut key in the Android emulatorR,RIn the iOS simulator, the shortcut key isThe Command ⌘ + RThe reloaded content is JS, and the project needs to be restarted if native modifications are involved.
  2. DebugEnable js remote debugging, which will actively open Chrome to create a”http://localhost:8081/debugger-ui. “TAB in the tabs open developers function can to debug the RN.
  3. Show InspectorThis feature is the same as the review element feature in Chrome, which mainly looks at the layout and style of elements, and can be used to find out why your style is not the way you want it to be.
  4. Enable Live ReloadThis option provides dynamic loading of projects. When your JS code changes, RN automatically generates the bundle and transfers it to the emulator or phone.

Now that you know about debugging techniques in RN, let’s get started on the project!

Install the required packages

yarn add react-navigation react-native-reanimated react-native-gesture-handler react-native-screens react-navigation-stack react-navigation-tabs react-native-vector-icons
Copy the code

Install and configure the react-Navigation package

Install the react-navigation component by running yarn add react-navigation. Run yarn add react-native-reanimated react-native- gear-handler react-native screens to install the relevant dependency packages. For iOS, make sure you have Cocoapods installed and run the following command:

cd ios
pod install
cd.Copy the code

(Android /app/build.gradle) (Android /app/build.gradle) (Android /app/build.gradle)

implementation 'androidx. Appcompat: appcompat: 1.1.0 - rc01'
implementation 'androidx. Swiperefreshlayout: swiperefreshlayout: 1.1.0 - alpha02'
Copy the code

To complete the react-native Gesture-handler installation, the following changes must be made in mainActivity.java:

package com.reactnavigation.example;

importcom.facebook.react.ReactActivity; <! -- Add content -->import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

public class MainActivity extends ReactActivity {
    @Override
    protected String getMainComponentName(a) {
        return "Example"; } <! -- Add content -->@Override
    protected ReactActivityDelegate createReactActivityDelegate(a) {
        return new ReactActivityDelegate(this, getMainComponentName()) {
            @Override
            protected ReactRootView createRootView(a) {
                return new RNGestureHandlerEnabledRootView(MainActivity.this); }}; }}Copy the code

The above operations need to be performed in RN 0.6 or later. If it is 0.6, link operation is also required. See here for details.

Using react navigation will definitely use the navigator. The navigator can also be considered a normal React component. You can use the navigator to define the navigation structure of your APP. The navigator can also render general-purpose elements, such as configurable title bars and TAB bars.

There are several types of navigators in react navigation to suit different application scenarios:

  • CreateStackNavigator: Similar to a normal Navigator, the navigation bar is the square of the navigation bar
  • CreateTabNavigator: deprecated, use createBottomTabNavigator,
  • CreateMaterialTopTabNavigator alternative
  • Inside the UITabBarController, in createBottomTabNavigator: the equivalent of the IOS screen all tabs
  • CreateMaterialTopTabNavigator: the top of the screen Material design theme TAB bar
  • CreateDrawerNavigator: Drawer effect with sides sliding out
  • CreateSwitchNavigator: SwitchNavigator in use is a display one page a page, commonly used for the welcome page page front page or login page, this page page without fallback.

We can create the App through different navigators. We can choose one of them or a combination of them, depending on the specific scenario. In our project we will use createStackNavigator for basic page jumps, createBottomTabNavigator for navigation of the bottom TAB bar, and createSwitchNavigator for launching the welcome page. CreateSwitchNavigator is in the React-Navigation we already installed, createStackNavigator is in the React-Navigation – Stack CreateBottomTabNavigator is in the React-Navigation – Tabs, so we need to add these two projects to our project:

yarn add react-navigation-stack react-navigation-tabs
Copy the code

The react – native – vector – the installation of the ICONS

React-native – Vector-icons is an icon component library that contains multiple icon libraries and supports the use of custom ICONS. Install it by running yarn add react-native vector-icons, then link react-native link react-native vector-icons, Gradle: android/app/build.gradle:

apply from: ".. /.. /node_modules/react-native-vector-icons/fonts.gradle"
Copy the code

In iOS, link operation may report an error, I encountered the following error:

Build system information
error: Multiple commands produce '/Users/zhangxiangchen/Code/demo/RNPoetry/ios/build/RNPoetry/Build/Products/Debug-iphonesimulator/RNPoetry.app/Entypo.tt f':
1) Target 'RNPoetry' (project 'RNPoetry') has copy command from '/Users/zhangxiangchen/Code/demo/RNPoetry/node_modules/react-native-vector-icons/Fonts/Entypo.ttf' to '/Users/zhangxiangchen/Code/demo/RNPoetry/ios/build/RNPoetry/Build/Products/Debug-iphonesimulator/RNPoetry.app/Entypo.tt f'
2) That command depends on command in Target 'RNPoetry' (project 'RNPoetry'): script phase "[CP] Copy Pods Resources"Copy the code

The solution is to open the project with Xcode and go to Target -> Build Phase > Copy Pods Resources -> Output Files, Remove ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}. This problem may be caused by cocoaPod version or can be resolved by upgrading cocoaPod

gem install cocoapods --pre
Copy the code

In addition to the link method, you can also import font files in other ways. The link operation can also cause problems in other ways, as you can see here.

Build the page

Added directory structure:

Build routes using react- Navigation

The createStackNavigator(RouteConfigs, StackNavigatorConfig) method accepts two values:

  • RouteConfigs(Mandatory) : A routing configuration object is a mapping from the routing name to the routing configuration, telling the navigator what the route presents.
  • StackNavigatorConfig(Optional) : Configure the navigation path (default first screen, navigationOptions, Paths, etc.) style (for example, transition mode, header mode, etc.).

RouteConfigs supports screen, Path, and navigationOptions.

  • screen(Mandatory) : Specifies a React component as the main display of the screen. When this component is loaded by createStackNavigator, it will be assigned a Navigation prop.
  • navigationOptions(Optional) Configures global screen navigation options such as title, headerRight, and headerLeft.

StackNavigatorConfig is more complex and supports a lot of parameters. We will not list them in detail.

  • initialRouteName: Sets the default page component, which must be registered above.
  • initialRouteParams: Indicates the parameter of the initial route.
  • initialRouteKey– Optional identifier of the initial route.
  • defaultNavigationOptions: Default option for on-screen navigation.
  • navigationOptions: Navigation options of the navigator itself, used to configure the parent navigator
  • mode: Page switching mode: Left and right card(equivalent to push in iOS), top and bottom modal(equivalent to modal in iOS)
    • card: Switch between left and right for common app.
    • modal: Switches up and down.

Then we use Poetry and PoetryDetail to implement the most basic StackNavigator:

import {createStackNavigator} from 'react-navigation-stack';
const PoetryStackNavigator = createStackNavigator(
  {
    Poetry: Poetry,
    PoetryDetail: {
      screen: PoetryDetail,
    },
  },
  {
    initialRouteName: 'Poetry',});export default PoetryStackNavigator;
Copy the code

Then implement the Home and My navigators in the same way, and then use createBottomTabNavigator to implement the bottom navigation:

createBottomTabNavigator(
  {
    Home: {
      screen: HomeStackNavigator,
      navigationOptions: {
        tabBarLabel: 'home',}},Poetry: {
      screen: PoetryStackNavigator,
      navigationOptions: {
        tabBarLabel: 'poetry',}},My: {
      screen: MyStackNavigator,
      navigationOptions: {
        tabBarLabel: 'I',},},}, {initialRouteName: 'Home'});Copy the code

Now the bottom navigation bar has no ICONS, we import the react-native vector-icons Icon from ‘react-native vector-icons/FontAwesome’ and add an image in the bottom navigation bar. Import the icon and then add it in StackNavigatorConfig of createBottomTabNavigator:

defaultNavigationOptions: ({navigation}) = > ({
  tabBarIcon: ({tintColor}) = > {
    const {routeName} = navigation.state;
    const mapIcon = {
      Home: 'home'.My: 'user-circle'.Poetry: 'tasks'};return <Icon name={mapIcon[routeName]} size={20} color={tintColor} />;
  },
}),
tabBarOptions: {
  activeTintColor: '#C20C0C',
  inactiveTintColor: 'gray',
},
Copy the code

The return value of tabBarIcon is the displayed image. We get the routeName from navigation. State and map it to different ICONS. TabBarOptions Sets the color of the bottom navigation bar in active and inactive states.

Finally, we will implement switchNavigator, the code implementation is relatively simple:

const switchNavigator = createSwitchNavigator({
  Init: WelcomeStackNavigator,
  Main: TabNavigator,
});
Copy the code

Now that the basic structure of our project is complete, let’s start our project! When we start the project, we’ll find that we’re stuck in Welcome because our page hasn’t done anything. Let’s finish implementing the page.

Page implementation

Welcome page is the first page we see when we start. The main function of this page is as a continuation page. After staying for a while, the user should automatically jump to the home page, use StyleSheet to create a simple style, and then use timer to jump to the home page:

const styles = StyleSheet.create({
  container: {
    flex: 1.alignItems: 'center'.justifyContent: 'center'.backgroundColor: '#C20C0C',},tips: {
    fontSize: 30.color: '#fff',}});class Welcome extends Component {
  componentDidMount() {
    setTimeout((a)= > {
      this.props.navigation.navigate('Main');
    }, 2000);
  }
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.tips}>Poetry and painters</Text>
      </View>); }}Copy the code

writing-mode
writing-mode

  • horizontal-tbContent is horizontal from left to right and vertical from top to bottom. The next horizontal line is below the previous one.
  • vertical-rlContent flows vertically from top to bottom and horizontally from right to left. The next vertical line is to the left of the previous row.
  • vertical-lrContent flows vertically from top to bottom and horizontally from left to right. The next vertical line is to the right of the previous row.
  • sideways-rlContent flows vertically from top to bottom, and all glyphs (even in vertical scripts) are set to the right.
  • sideways-lrContent flows vertically from top to bottom, with all glyphs (even in vertical scripts) set to the left.

RN also has a similar property called writingDirection, but only supports three properties ‘auto’, ‘LTR ‘, and’ RTL ‘. There is no vertical setting for RN, so we have to use other methods for vertical setting. My solution was to nest the Text in the View and give the View a width that allows the Text to display only one word per line. Visually it worked, but the punctuation support wasn’t perfect.

const styles = StyleSheet.create({
  container: {
    flex: 1.alignItems: 'center'.justifyContent: 'center'.backgroundColor: '#efefef',},wrapper: {
    backgroundColor: '#fff'.width: '80%'.height: '80%'.flexDirection: 'row-reverse'.padding: 24.position: 'relative',},section: {
    width: 40,},contentText: {
    fontSize: 30,},title: {
    width: 20.position: 'absolute'.right: 24.bottom: 24,},titleText: {
    fontSize: 16,}});class Home extends Component {
  static navigationOptions = {
    headerTitle: 'home'}; render() {return (
      <View style={styles.container}>
        <View style={styles.wrapper}>
          <View style={styles.section}>
            <Text style={styles.contentText}>Not out of the light spicy, qianshan Wanshan such as fire.</Text>
          </View>
          <View style={styles.section}>
            <Text style={styles.contentText}>He went to heaven for a moment and chased the broken star away from the moon.</Text>
          </View>
          <View style={styles.title}>
            <Text style={styles.titleText}>"Japanese poetry" Song Taizu</Text>
          </View>
        </View>
      </View>); }}Copy the code

NavigationOptions for each page is used to set the Header style of the page. It can be an object or a function. For example, in our PoetryDetail page, our title name changes depending on the content, and we update the title name by getting the information passed to the page:

static navigationOptions = ({navigation}) => {
    const item = navigation.state.params.item;
    return {
      headerTitle: item.title,
    };
};
Copy the code

It’s best to implement the Poetry and PoetryDetail pages. Poetry is a list page that we implement using RN’s FlatList component, which is an efficient list component that maintains a limited rendering window with visible elements, All elements outside the rendering window are replaced with appropriate fixed-length blank space, which improves the use of memory and improves the rendering performance in the case of a large amount of data. The render window responds to scrolling behavior, with lower priority as far away as the visible area of the element is, and higher priority as near as it is. However, when the user swipes too fast, there is a brief blank space. It also supports pull-up loading, pull-down refresh and other functions.

For list elements we implement click events and effects via TouchableHighlight, which produces a darken effect. In RN we often use the following components for corresponding user click events:

  • TouchableWithoutFeedback: Responds to user click events, which is a great option if you want to process click events without showing any visual feedback.
  • TouchableHighlight: Adds the effect that the background darkens when pressed, based on TouchableWithoutFeedback.
  • TouchableOpacity: Unlike TouchableHighlight, which darkens the background when pressed, TouchableOpacity lowers the transparency of the button when the user’s finger is pressed without changing the color of the background.
  • TouchableNativeFeedback: Also available on Android, TouchableNativeFeedback creates a visual effect similar to water ripples when a user’s finger is pressed down. Note that this component only supports Android.

Bind the onPress event to TouchableHighlight, jump to the PoetryDetail page and pass the array element as an argument:

class PoetryItem extends Component {
  render() {
    const {item, handler} = this.props;
    return (
      <TouchableHighlight onPress={()= > handler()}>
        <View style={styles.item}>
          <View style={styles.itemHeader}>
            <Text style={styles.titleText}>{item.title}</Text>
            <Text style={styles.authorText}>[song] {item. The author}</Text>
          </View>
          <View>
            <Text style={styles.contentText}>{item.paragraphs[0]}</Text>
          </View>
        </View>
      </TouchableHighlight>); }}class Poetry extends Component {
  static navigationOptions = {
    headerTitle: 'poetry'}; render() {const {navigation} = this.props;
    return (
      <View style={styles.contianer}>
        <FlatList
          data={list}
          renderItem={({item}) => (
            <PoetryItem
              item={item}
              handler={() => navigation.navigate('PoetryDetail', {item})}
            />
          )}
        />
      </View>
    );
  }
}
Copy the code

The PoetryDetail is a little bit simpler, you finish the page as you design it, you dynamically change the title in addition to the navigationOptions mentioned earlier, and you’re left with some basic styling.

The finished effect is as shown in the figure above; Another problem is that when we jump to the PoetryDetail page, the bottom navigation bar is still there. When we write the route, StackNavigator is included in the BottomTabNavigator. Even if the StackNavigator route changes, The bottom navigation bar of the BottomTabNavigator will still not be affected. We are going to handle the bottom navigation in StackNavigator, showing the bottom navigation on the first route and not on subsequent routes:

PoetryStackNavigator.navigationOptions = ({navigation}) = > {
  let tabBarVisible = true;
  if (navigation.state.index > 0) {
    tabBarVisible = false;
  }
  return {
    tabBarVisible,
  };
};
Copy the code

other

In the next article, we will acquire data through network request, use Redux and React-Navigation to manage data, and use more functions of FlatList component to improve our App.

Project warehouse address: github.com/x007xyz/RNP…