1.React Native

React Native official: Learn once, write anywhere… Nice doesn’t seem very nice

Summary of RN

  • Create native apps for Android and iOS using React and JavaScript

Combine the best parts of your development with React, a first-class JavaScript library for building user interfaces, and you can use React Native in existing Android and iOS projects or create an entirely new application from scratch. React Native works well with components in Objective-C, Java, or Swift. If you need to optimize several aspects of your application, you can simply use native code. The two are not in conflict.

Contrast with Flutter

advantage

  • Hot reloading = fast coding

Hot overloading speeds up the development process by allowing developers to inject new code directly into running applications. As a result, developers can see the changes immediately without having to rebuild the application.

  • One code base, two mobile platforms

This is exactly the same as Flutter: a single code base is written to power 2 applications — both Android and iOS. Even better, JavaScript helps you when writing cross-platform applications by sharing code with Web applications. This is done by creating abstract components that can be compiled for the target platform.

  • It uses a popular language, JavaScript.

React Native uses JavaScript: A programming language that many developers are familiar with (although Dart is still not as well known or used). And, if you’re a developer who prefers statically typed programming languages, you can even use TypeScript (a subset of JavaScript).

  • Freedom of choice for developers

React Native allows developers to decide exactly what solution they want to use. Both are based on the requirements of the project and the preferences of the developer. Suppose that if developers need to decide how to handle global state (how to store and manage data used in many components of an application), choose the router library or choose between JavaScript and TypeScript — they can decide whether D would prefer to use a custom UI library, or write it themselves.

  • Relative maturity.

The official React Native version was released four years ago, so the Facebook team had plenty of time to stabilize the API and focus on fixing problems and fixing them. Now, they are working on some exciting improvements – reducing the size of applications, for example.

  • A vibrant and expansive community.

React Native has a large developer community. Not only that, but there are countless tutorials, libraries, and UI frameworks that make it easy to learn the technology and develop it quickly and easily.

  • React is easy for developers to learn

This advantage in our list is very specific to React developers. If you have a Web development background and already use popular React solutions, you can easily use React Native without having to learn new libraries. You can use the same libraries, tools, and patterns.

disadvantages

  • It’s not a native UI.

Like any cross-platform solution, the UI experience and performance are not exactly the same as in native applications, but close to it. However, it’s easier to get a “natural feel” with React Native than with Flutter. If you want the Flutter application to have native components, you need to do something else.

  • Less components.

React Native only supports basic components out of the box (many of which are suitable for platforms out of the box, such as buttons, load indicators, or sliders). Flutter is designed to support Material Design out of the box, so the framework supports more widgets.

  • Weak user interface.

The fact that React Native uses Native components in the background should give you confidence that your application components will also be updated immediately after every OS UI update. That is to say – this can break the user interface of an application, but this rarely happens.

  • The application is larger than the native application.

Applications written with React Native must be able to run Javascript code (Javascript virtual machines). Android does not have this feature by default – meaning that the application needs to include a library that supports JavaScript code, resulting in the application being larger than its native Android equivalents. IOS apps made with React Native don’t suffer from this problem, but they’re still typically larger than Native apps.

2. Environment construction

Install dependencies

The dependencies you must install are Node, Watchman, Xcode, and CocoaPods. While you can use any editor to develop your app, you still have to install Xcode to get the tools and environment you need to compile your iOS app.

Install Node and Watchman using Homebrew

brew install node
brew install watchman
Copy the code

Install iOS emulator # in Xcode

To install the emulator simply open Xcode > Preferences… Menu, and then select the Components option to see the various emulators of different iOS versions available for installation.

CocoaPods

CocoaPods is a package manager written in Ruby

brew install cocoapods
Copy the code

Creating a new project

Use React Native’s built-in command-line tools to create a new project called “AwesomeProject”. This command line tool does not need to be installed and can be used using node’s NPX command (note that the init command creates the latest version by default) :

npx react-native init AwesomeProject
Copy the code

Optional You can use the –version argument to create a specific version of the project. Note that the version number must be accurate to two decimal points.

npx react-native init AwesomeProject --version X.XX.X
Copy the code

You can also use –template to use community-provided templates, such as those with TypeScript configuration:

npx react-native init AwesomeTSProject --template react-native-template-typescript
Copy the code

Compile and run the React Native application

CD AwesomeProject yarn ios # or yarn React-native run-iosCopy the code

Core components and apis

  • React Native provides some built-in core components for you to use.

To be clear, you’re not limited to these built-in components. React Native is the work of a large open source community, so you can also search github or NPM for a number of third-party components with the React Native keyword.

Based on the component

View

As the most basic component for creating a UI, the View is a container that supports Flexbox layouts, styles, touch responses, and several accessibility features.

Views are designed to be nested and can have any number of subviews of any type.

import React from "react"; import { View, Text } from "react-native"; const ViewBoxesWithColorAndText = () => { return ( <View style={{ flexDirection: "row", height: 100, padding: 20}} > <View style={{backgroundColor: "blue", flex: 0.3}} /> <View style={{backgroundColor: "red", flex: /> <Text>Hello World! </Text> </View> ); }; export default ViewBoxesWithColorAndText;Copy the code

Composite click event

For View response properties (for example, onResponderMove)

  • nativeEvent

ChangedTouches – Array of Touch touches since the last event.

Identifier – The ID of the touch event.

LocationX – The X coordinate of the touch event relative to the element’s position.

LocationY – The Y coordinate of the touch event relative to the element’s position.

PageX – The X coordinate of the touch event relative to the root element position.

Pagey-the Y coordinate of the touch event relative to the root element position.

Target – THE ID of the element that receives the touch event.

Timestamp – The time mark of the touch event, used to calculate the speed.

Touches – An array of all current touch events on the screen.

The sample
{changedTouches: [PressEvent], Identifier: 1, locationX: 8, locationY: 4.5, pageX: 24, pageY: 49.5, target: Touches: []}Copy the code

Text

React component for displaying text, and it also supports nesting, styling, and touch handling.

import React, { useState } from "react"; import { Text, StyleSheet } from "react-native"; const TextInANest = () => { const [titleText, setTitleText] = useState("Bird's Nest"); const bodyText = useState("This is not really a bird nest."); const onPressTitle = () => { setTitleText("Bird's Nest [pressed]"); }; return ( <Text style={styles.baseText}> <Text style={styles.titleText} onPress={onPressTitle}> {titleText} {"\n"} {"\n"}  </Text> <Text numberOfLines={5}>{bodyText}</Text> </Text> ); }; const styles = StyleSheet.create({ baseText: { fontFamily: "Cochin" }, titleText: { fontSize: 20, fontWeight: "bold" } }); export default TextInANest;Copy the code

Nested text
import React from 'react';
import { Text, StyleSheet } from 'react-native';
const BoldAndBeautiful = () => {
  return (
    <Text style={styles.baseText}>
      I am bold
      <Text style={styles.innerText}> and red</Text>
    </Text>
  );
};
const styles = StyleSheet.create({
  baseText: {
    fontWeight: 'bold'
  },
  innerText: {
    color: 'red'
  }
});
export default BoldAndBeautiful;
Copy the code

Nested views (iOS only)
import React, { Component } from 'react'; import { Text, View } from 'react-native'; export default class BlueIsCool extends Component { render() { return ( <Text> There is a blue square <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} /> in between my text. </Text> ); }}Copy the code

Image

React component for displaying different types of images, including network images, static resources, temporary local images, and images on local disks (such as albums).

The following example demonstrates how to display images provided from the local cache, the network, and even in the base64 URI of ‘data:’

mport React from 'react'; import { View, Image, StyleSheet } from 'react-native'; const styles = StyleSheet.create({ container: { paddingTop: 50, }, tinyLogo: { width: 50, height: 50, }, logo: { width: 66, height: 58, }, }); const DisplayAnImage = () => { return ( <View style={styles.container}> <Image style={styles.tinyLogo} source={require('@expo/snack-static/react-native-logo.png')} /> <Image style={styles.tinyLogo} source={{ uri: 'https://reactnative.dev/img/tiny_logo.png', }} /> <Image style={styles.logo} source={{ uri: 'data:image/png; base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab 8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==', }} /> </View> ); } export default DisplayAnImage;Copy the code

GIF and WebP images are supported on Android

GIF and WebP formats are not supported by Android by default. You need to manually add the following modules to the Android /app/build.gradle file as needed:

Dependencies {/ / if you need to support Android4.0 (API level 14) version before implementation 'com. Facebook. Fresco ": animated - base - support: 1.3.0' / / if you need to support the GIF diagram implementation 'com. Facebook. Fresco ": animated - GIF: 2.0.0' / / if you need support WebP, Including dynamic figure WebP implementation 'com. Facebook. Fresco ": animated - WebP: 2.1.0' implementation 'com. Facebook. Fresco" : webpsupport: 2.0.0' / / if you only need to support the WebP implementation without the need for a dynamic diagram 'com. Facebook. Fresco ": webpsupport: 2.0.0'}Copy the code
resizeMode

Determines how to resize an image when the component size is out of proportion to the image size. The default value is cover.

Cover: Scale the image while maintaining its aspect ratio until both the width and height are greater than or equal to the container view size (minus if the container has a padding lining). So that the image completely covers or even exceeds the container, leaving no space in the container.

Contain: Zoom in and out of the image until the width and height of the image are equal to or less than the container view size (minus if the container has a padding lining). So the image is completely wrapped in the container, the container may have a blank space.

Stretch: Stretches the image without maintaining a width to height ratio until it fills the container.

Repeat: Tile the image until the container is filled. The image will remain the original size, but when it is larger than the container, it will be scaled to wrap around the container while maintaining the aspect ratio.

Center: not stretched

source

Image source data (remote URL address or local data).

methods
Image.abortPrefetch(requestId);
Copy the code

Interrupt the preload operation.

RequestId :number= ID returned by prefetch()

Image.getSize(uri, success, [failure]);
Copy the code

Gets the width, in pixels, of the image before displaying it. This method will also fail if the image address is incorrect or the download fails.

To get the size of the image, you first need to load or download the image (which is also cached). This means that in theory you can use this method to preload images, although this method is not optimized for this use, and in the future there may be implementations that do not need to download the entire image to get the size. So a better preloading solution is to use the specific preloading method below.

This method cannot be used for static image resources.

Uri :string = Image address

Success :function= return the width and height of the image

Failure :function= failed callback function

Image.prefetch(url);
Copy the code

Preload a remote image (download it to the local disk cache).

Url :string = remote address of the image

Image.queryCache(urls);
Copy the code

Example Query the image cache status. Returns cache status based on the image URL, such as “disk” (cached in a disk file) or “memory” (cached in memory).

Urls :array= array of image urls to query cache status.

TextInput

TextInput is a basic component that allows users to enter text from the keyboard in an application. The properties of this component provide the configuration of various features, such as autocomplete, automatic capitalization, placeholder text, and various keyboard types (such as numeric keypads), and so on.

The simplest way to use it is to drop a TextInput into the application and subscribe to its onChangeText event to read user input. Notice, take the value from TextInput that’s the only way to do it right now! That is, using setState in onChangeText to write user input to state and then fetch the value from this.state where it is needed. It also has a number of other events, such as onSubmitEditing and onFocus. A simple example is as follows:

import React, { Component } from 'react';
import { TextInput } from 'react-native';
const UselessTextInput = () => {
  const [value, onChangeText] = React.useState('Useless Placeholder');
  return (
    <TextInput
      style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
      onChangeText={text => onChangeText(text)}
      value={value}
    />
  );
}
export default UselessTextInput;
Copy the code

methods

focus(); Makes the native input request focus.

blur();
Copy the code

Makes the native input lose focus.

clear();
Copy the code

Clear the contents of the input field.

isFocused();
Copy the code

The return value indicates whether the current input box is in focus.

ScrollView

A component that encapsulates the platform’s ScrollView and also integrates a touch-locked “responder” system.

Remember that ScrollView must have a certain height to work properly, because all it really does is pack a series of child components of an uncertain height into a container of a certain height (by scrolling). To give a ScrollView a definite height, either set the height directly to it (not recommended) or make sure all parent containers have a definite height. Normally we will set The ScrollView to Flex: 1 to automatically fill the free space of the parent container, but only if all the parent containers have Flex set themselves or specified a height, otherwise it will not scroll properly. You can use the element viewer to find out which layer height is incorrect.

Other responders inside the ScrollView cannot yet prevent the ScrollView itself from becoming a responder.

How to choose between ScrollView and FlatList? ScrollView simply renders all the child elements at once. Its principle is easy to understand, the use of the most natural and simple. However, such simple rendering logic naturally leads to performance limitations. Imagine that you have an extremely long list to display, perhaps several screens high. Creating and rendering JS components and native views that are off-screen is obviously a huge drag and waste on rendering performance and memory footprint.

That’s why we also have a dedicated FlatList component. FlatList lazily renders child elements, starting rendering only when they are about to appear on the screen. This lazy rendering logic is much more complex, and therefore the API is much more cumbersome to use. Unless you are rendering very little data, you should always use flatLists, even if they are more cumbersome to use.

FlatList also makes it easy to render line separators, support multi-column layouts, infinite scrolling loading, and more.

import React from 'react';
import { StyleSheet, Text, SafeAreaView, ScrollView, StatusBar } from 'react-native';
const App = () => {
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        <Text style={styles.text}>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </Text>
      </ScrollView>
    </SafeAreaView>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: StatusBar.currentHeight,
  },
  scrollView: {
    backgroundColor: 'pink',
    marginHorizontal: 20,
  },
  text: {
    fontSize: 42,
  },
});
export default App;
Copy the code

methods

scrollTo(
  ([y]: number),
  object,
  ([x]: number),
  ([animated]: boolean),
  ([duration]: number)
);
Copy the code

Scroll to the specified x, y offset. The third parameter is whether smooth scrolling animation is enabled. The duration parameter is an Android only scrolling duration.

scrollTo({x: 0, y: 0, animated: true})
Copy the code

Example of specifying scroll duration (Android only):

scrollTo({x: 0, y: 0, duration: 500})

crollToEnd(([options]: { animated: boolean, duration: number }));
Copy the code

Scroll to the bottom of the view (scroll to the far right for horizontal views).

Add the animation parameter scrollToEnd({animated: true}) to enable smooth scrolling or call scrollToEnd({animated: false}) to jump immediately.

flashScrollIndicators()
Copy the code

Briefly displays the scroll indicator.

StyleSheet

StyleSheet provides an abstraction similar to CSS stylesheets.

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

const App = () => (
  <View style={styles.container}>
    <Text style={styles.title}>React Native</Text>
  </View>
);
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: "#eaeaea"
  },
  title: {
    marginTop: 16,
    paddingVertical: 8,
    borderWidth: 4,
    borderColor: "#20232a",
    borderRadius: 6,
    backgroundColor: "#61dafb",
    color: "#20232a",
    textAlign: "center",
    fontSize: 30,
    fontWeight: "bold"
  }
});
export default App;
Copy the code

methods

static compose(style1: object, style2: object): object | array<object>
Copy the code

Combines two styles such that style2 will override any styles in style1. If either style is falsy, the other one is returned without allocating an array, saving allocations and maintaining reference equality for PureComponent checks.

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const App = () => (
  <View style={container}>
    <Text style={text}>React Native</Text>
  </View>
);
const page = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: '#fff',
  },
  text: {
    fontSize: 30,
    color: '#000'
  },
});
const lists = StyleSheet.create({
  listContainer: {
    flex: 1,
    backgroundColor: '#61dafb',
  },
  listItem: {
    fontStyle: 'italic',
    fontWeight: 'bold'
  },
});
const container = StyleSheet.compose(page.container, lists.listContainer);
const text = StyleSheet.compose(page.text, lists.listItem);
export default App;
Copy the code
static create(obj: object): object
Copy the code

reates a StyleSheet style reference from the given object.

 static flatten(style: array<object>): object
Copy the code

Flattens an array of style objects, into one aggregated style object. Alternatively, this method can be used to lookup IDs, returned by StyleSheet.register.

import React from "react";
import { StyleSheet, Text, View } from "react-native";
const App = () => (
  <View style={page.container}>
    <Text style={flattenStyle}>React Native</Text>
    <Text>Flatten Style</Text>
    <Text style={page.code}>
      {JSON.stringify(flattenStyle, null, 2)}
    </Text>
  </View>
);
const page = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    alignItems: "center"
  },
  text: {
    color: "#000",
    fontSize: 14,
    fontWeight: "bold"
  },
  code: {
    marginTop: 12,
    padding: 12,
    borderRadius: 8,
    color: "#666",
    backgroundColor: "#eaeaea"
  }
});
const typography = StyleSheet.create({
  header: {
    color: "#61dafb",
    fontSize: 30,
    marginBottom: 36
  }
});
const flattenStyle = StyleSheet.flatten([
  page.text,
  typography.header
]);
export default App;
Copy the code

absoluteFill

Absolute padding can be used to facilitate and reduce the repetition of these repetitive styles. AbsoluteFill can be used to create custom entries in a stylesheet if desired

import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; const App = () => ( <View style={styles.container}> <View style={styles.box1}> <Text style={styles.text}>1</Text> </View> <View style={styles.box2}> <Text style={styles.text}>2</Text> </View> <View style={styles.box3}> <Text style={styles.text}>3</Text> </View> </View> ); const styles = StyleSheet.create({ container: { flex: 1 }, box1: { position: 'absolute', top: 40, left: 40, width: 100, height: 100, backgroundColor: 'red' }, box2: { ... StyleSheet.absoluteFill, width: 100, height: 100, backgroundColor: 'blue' }, box3: { position: 'absolute', top: 120, left: 120, width: 100, height: 100, backgroundColor: 'green' }, text: { color: '#FFF', fontSize: 80 } }); export default App;Copy the code

Interactive controls

Button

import React from 'react'; import { StyleSheet, Button, View, SafeAreaView, Text, Alert } from 'react-native'; import Constants from 'expo-constants'; const Separator = () => { return <View style={styles.separator} />; } const App = () => { return ( <SafeAreaView style={styles.container}> <View> <Text style={styles.title}> The title and onPress handler are required. It is recommended to set accessibilityLabel to help make your app usable by everyone. </Text> <Button title="Press me" onPress={() => Alert.alert('Simple Button pressed')} /> </View> <Separator /> <View> <Text style={styles.title}> Adjust the color in a way that looks standard on each platform. On iOS, the color prop controls the color of the text. On Android, the color adjusts the background color of the button. </Text> <Button title="Press me" color="#f194ff" onPress={() => Alert.alert('Button with adjusted color pressed')} /> </View> <Separator /> <View> <Text style={styles.title}> All interaction for the component are disabled. </Text> <Button title="Press me" disabled onPress={() => Alert.alert('Cannot  press this one')} /> </View> <Separator /> <View> <Text style={styles.title}> This layout strategy lets the title define the width of the button. </Text> <View style={styles.fixToText}> <Button title="Left button" onPress={() => Alert.alert('Left button pressed')} /> <Button title="Right button" onPress={() => Alert.alert('Right button pressed')} /> </View> </View> </SafeAreaView> ); } const styles = StyleSheet.create({ container: { flex: 1, marginTop: Constants.statusBarHeight, marginHorizontal: 16, }, title: { textAlign: 'center', marginVertical: 8, }, fixToText: { flexDirection: 'row', justifyContent: 'space-between', }, separator: { marginVertical: 8, borderBottomColor: '#737373', borderBottomWidth: StyleSheet.hairlineWidth, }, }); export default App;Copy the code

picker

 yarn add @react-native-picker/picker
Copy the code
import {Picker} from '@react-native-picker/picker'

const [selectedLanguage, setSelectedLanguage] = useState();
<Picker
  selectedValue={selectedLanguage}
  onValueChange={(itemValue, itemIndex) =>
    setSelectedLanguage(itemValue)
  }>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="JavaScript" value="js" />
</Picker>
Copy the code

slider

yarn add @react-native-community/slider
Copy the code
import Slider from '@react-native-community/slider'

 <Slider
    style={{width: 200, height: 40}}
    minimumValue={0}
    maximumValue={1}
    minimumTrackTintColor="#FFFFFF"
    maximumTrackTintColor="#000000"
  />
Copy the code

Switch

import React, { useState } from "react"; import { View, Switch, StyleSheet } from "react-native"; const App = () => { const [isEnabled, setIsEnabled] = useState(false); const toggleSwitch = () => setIsEnabled(previousState => ! previousState); return ( <View style={styles.container}> <Switch trackColor={{ false: "#767577", true: "#81b0ff" }} thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"} ios_backgroundColor="#3e3e3e" onValueChange={toggleSwitch} value={isEnabled} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center" } }); export default App;Copy the code

List view

FlatList

  • A high-performance simple list component that supports the following common functions:

Fully cross-platform.

Horizontal layout mode is supported.

The callback event can be configured when the row component is displayed or hidden.

Support for separate header components.

Support for separate tail components.

Supports custom line separators.

Supports drop-down refresh.

Supports pull-up loading.

Supports jumping to a specified row (ScrollToIndex).

Supports multi-column layouts.

If you need groups/classes/sections, use SectionList.

import React from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text, StatusBar } from 'react-native';
const DATA = [
  {
    id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
    title: 'First Item',
  },
  {
    id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
    title: 'Second Item',
  },
  {
    id: '58694a0f-3da1-471f-bd96-145571e29d72',
    title: 'Third Item',
  },
];
const Item = ({ title }) => {
  return (
    <View style={styles.item}>
      <Text style={styles.title}>{title}</Text>
    </View>
  );
}
const App = () => {
  const renderItem = ({ item }) => (
    <Item title={item.title} />
  );
  return (
    <SafeAreaView style={styles.container}>
      <FlatList
        data={DATA}
        renderItem={renderItem}
        keyExtractor={item => item.id}
      />
    </SafeAreaView>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: StatusBar.currentHeight || 0,
  },
  item: {
    backgroundColor: '#f9c2ff',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
  },
  title: {
    fontSize: 32,
  },
});
export default App;
Copy the code

SectionList

  • A high-performance section list component that supports the following common features:

Fully cross-platform.

The callback event can be configured when the row component is displayed or hidden.

Support for separate header components.

Support for separate tail components.

Supports custom line separators

Header components that support grouping.

A dividing line that supports grouping.

Support for multiple data source structures

Supports drop-down refresh.

Supports pull-up loading.

If your list doesn’t need sections, use the simpler

.

import React from "react";
import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from "react-native";

const DATA = [
  {
    title: "Main dishes",
    data: ["Pizza", "Burger", "Risotto"]
  },
  {
    title: "Sides",
    data: ["French Fries", "Onion Rings", "Fried Shrimps"]
  },
  {
    title: "Drinks",
    data: ["Water", "Coke", "Beer"]
  },
  {
    title: "Desserts",
    data: ["Cheese Cake", "Ice Cream"]
  }
];
const Item = ({ title }) => (
  <View style={styles.item}>
    <Text style={styles.title}>{title}</Text>
  </View>
);
const App = () => (
  <SafeAreaView style={styles.container}>
    <SectionList
      sections={DATA}
      keyExtractor={(item, index) => item + index}
      renderItem={({ item }) => <Item title={item} />}
      renderSectionHeader={({ section: { title } }) => (
        <Text style={styles.header}>{title}</Text>
      )}
    />
  </SafeAreaView>
);
const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: StatusBar.currentHeight,
    marginHorizontal: 16
  },
  item: {
    backgroundColor: "#f9c2ff",
    padding: 20,
    marginVertical: 8
  },
  header: {
    fontSize: 32,
    backgroundColor: "#fff"
  },
  title: {
    fontSize: 24
  }
});
export default App;
Copy the code

IOS unique ComponentsActionSheetIOS

import React, { useState } from "react"; import { ActionSheetIOS, Button, StyleSheet, Text, View } from "react-native"; Const App = () => {const [result, setResult] = useState("🔮"); const onPress = () => ActionSheetIOS.showActionSheetWithOptions( { options: ["Cancel", "Generate number", "Reset"], destructiveButtonIndex: 2, cancelButtonIndex: 0, userInterfaceStyle: 'dark' }, buttonIndex => { if (buttonIndex === 0) { // cancel action } else if (buttonIndex === 1) { setResult(Math.floor(Math.random() * 100) + 1); } else if (buttonIndex === 2) {setResult("🔮"); }}); return ( <View style={styles.container}> <Text style={styles.result}>{result}</Text> <Button onPress={onPress} title="Show Action Sheet" /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center" }, result: { fontSize: 64, textAlign: "center" } }); export default App;Copy the code

Methods showActionSheetWithOptions

static showActionSheetWithOptions(options, callback)
Copy the code
  • Display an ActionSheet popup box on an iOS device, where the options parameter is an object whose properties must contain one or more of the following:

Options (String array) – Text for a set of buttons (required)

CancelButtonIndex (Integer) – Position of the cancel button in options (index)

DestructiveButtonIndex (integer) – The position of the delete button in options (index)

Title (string) – The title at the top of the pop-up box

Message (string) – The message below the title at the top of the pop-up box

anchor (number) – the node to which the action sheet should be anchored (used for iPad)

TintColor (String) – Specifies the color of the text of the delete button

disabledButtonIndices (array of numbers) – a list of button indices which should be disabled

userInterfaceStyle (string) – the interface style used for the action sheet, can be set to light or dark, otherwise the default system style will be used

eg:

ActionSheetIOS. ShowActionSheetWithOptions ({options: [' cancel ', 'delete'], destructiveButtonIndex: 1, cancelButtonIndex: 0,}, (buttonIndex) => {if (buttonIndex === 1) {/* If (buttonIndex == 1) {Copy the code

showShareActionSheetWithOptions

static showShareActionSheetWithOptions(options, failureCallback, successCallback)
Copy the code
  • Display a share pop-up box on an iOS device, where the options parameter is an object with the following properties (it must have at least a message or URL) :

Url (string) – THE URL address to share

Message (string) – The message to share

Subject (string) – The subject of information to share

ExcludedActivityTypes (Array) – Specifies activities that are not displayed in the Actionsheet

Note: If the URL points to a local file, or if it is a Base64 encoded URL, the corresponding file is read and shared directly. You can share pictures, videos, PDFS and more in this way.

  • The ‘successCallback’ function takes two arguments:

A Boolean value indicating success or failure

Returns a string indicating how to share on success

Android Unique Components

BackHandler

The BackHandler API listens for back button events on devices and can call your own functions to handle the back behavior. This API is only available on Android.

  • Callbacks are executed in reverse order (that is, the function added later is executed first).

If a function returns true, none of the subsequent functions are called.

If no listeners are added, or if all listeners return false, the default behavior is executed and the application exits.

import React, { useEffect } from "react"; import { Text, View, StyleSheet, BackHandler, Alert } from "react-native"; const App = () => { useEffect(() => { const backAction = () => { Alert.alert("Hold on!" , "Are you sure you want to go back?" , [ { text: "Cancel", onPress: () => null, style: "cancel" }, { text: "YES", onPress: () => BackHandler.exitApp() } ]); return true; }; const backHandler = BackHandler.addEventListener( "hardwareBackPress", backAction ); return () => backHandler.remove(); } []); return ( <View style={styles.container}> <Text style={styles.text}>Click Back button! </Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center" }, text: { fontSize: 18, fontWeight: "bold" } }); export default App;Copy the code

import React, { useEffect } from "react"; import { Text, View, StyleSheet, BackHandler, Alert } from "react-native"; const App = () => { const backAction = () => { Alert.alert("Hold on!" , "Are you sure you want to go back?" , [ { text: "Cancel", onPress: () => null, style: "cancel" }, { text: "YES", onPress: () => BackHandler.exitApp() } ]); return true; }; useEffect(() => { BackHandler.addEventListener("hardwareBackPress", backAction); return () => BackHandler.removeEventListener("hardwareBackPress", backAction); } []); return ( <View style={styles.container}> <Text style={styles.text}>Click Back button! </Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center" }, text: { fontSize: 18, fontWeight: "bold" } }); export default App;Copy the code

DrawerLayoutAndroid

The React component encapsulates the Android DrawerLayout. The drawer (usually used for navigation switches) is rendered using the renderNavigationView method, and the direct subview of DrawerLayoutAndroid becomes the main view (used to place the content).

import React, { useState } from "react"; import { Button, DrawerLayoutAndroid, Text, StyleSheet, View } from "react-native"; const App = () => { const [drawerPosition, setDrawerPosition] = useState("left"); const changeDrawerPosition = () => { if (drawerPosition === "left") { setDrawerPosition("right"); } else { setDrawerPosition("left"); }}; const navigationView = ( <View style={styles.navigationContainer}> <Text style={{ margin: 10, fontSize: 15 }}>I'm in the Drawer! </Text> </View> ); return ( <DrawerLayoutAndroid drawerWidth={300} drawerPosition={drawerPosition} renderNavigationView={() => navigationView} > <View style={styles.container}> <Text style={{ margin: 10, fontSize: 15 }}> DrawerLayoutAndroid example </Text> <Button title="Change Drawer Position" onPress={() => changeDrawerPosition()}  /> <Text style={{ margin: 10, fontSize: 15 }}> Drawer on the {drawerPosition}! Swipe from the side to see! </Text> </View> </DrawerLayoutAndroid> ); }; const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center", paddingTop: 50, backgroundColor: "#ecf0f1", padding: 8 }, navigationContainer: { flex: 1, paddingTop: 50, backgroundColor: "#fff", padding: 8 } }); export default App;Copy the code

PermissionsAndroid

PermissionsAndroid has access to the permission model provided by Android M(i.e. 6.0). Some permissions are written in androidmanifest.xml and are automatically acquired at installation, but some “dangerous” permissions require pop-ups for users to select. This API is used in the latter case.

import React from "react"; import { StyleSheet, Text, View, SafeAreaView, PermissionsAndroid, Button } from "react-native"; import Constants from "expo-constants"; const requestCameraPermission = async () => { try { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.CAMERA, { title: "Cool Photo App Camera Permission", message: "Cool Photo App needs access to your camera " + "so you can take awesome pictures.", buttonNeutral: "Ask Me Later", buttonNegative: "Cancel", buttonPositive: "OK" } ); if (granted === PermissionsAndroid.RESULTS.GRANTED) { console.log("You can use the camera"); } else { console.log("Camera permission denied"); } } catch (err) { console.warn(err); }}; const App = () => ( <View style={styles.container}> <Text style={styles.item}>Try permissions</Text> <Button title="request permissions" onPress={requestCameraPermission} /> </View> ); const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", paddingTop: Constants.statusBarHeight, backgroundColor: "#ecf0f1", padding: 8 }, item: { margin: 24, fontSize: 18, fontWeight: "bold", textAlign: "center" } }); export default App;Copy the code

ToastAndroid

This module exports the native ToastAndroid module as a JS module for displaying a floating prompt on an Android device. This module contains a show method that takes the following arguments:

  • Message A string representing the text content to be displayed.
  • Duration Indicates the duration for which the message is displayed. It can be toastAndroid. SHORT or toastAndroid. LONG
mport React from "react"; import { View, StyleSheet, ToastAndroid, Button, StatusBar } from "react-native"; const App = () => { const showToast = () => { ToastAndroid.show("A pikachu appeared nearby !" , ToastAndroid.SHORT); }; const showToastWithGravity = () => { ToastAndroid.showWithGravity( "All Your Base Are Belong To Us", ToastAndroid.SHORT, ToastAndroid.CENTER ); }; const showToastWithGravityAndOffset = () => { ToastAndroid.showWithGravityAndOffset( "A wild toast appeared!" , ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50 ); }; return ( <View style={styles.container}> <Button title="Toggle Toast" onPress={() => showToast()} /> <Button title="Toggle Toast With Gravity" onPress={() => showToastWithGravity()} /> <Button title="Toggle Toast With Gravity & Offset" onPress={() => showToastWithGravityAndOffset()} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", paddingTop: StatusBar.currentHeight, backgroundColor: "#888888", padding: 8 } }); export default App;Copy the code

Imperative hack
import React, { useState, useEffect } from "react"; import { View, StyleSheet, ToastAndroid, Button, StatusBar } from "react-native"; const Toast = ({ visible, message }) => { if (visible) { ToastAndroid.showWithGravityAndOffset( message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50 ); return null; } return null; }; const App = () => { const [visibleToast, setvisibleToast] = useState(false); useEffect(() => setvisibleToast(false), [visibleToast]); const handleButtonPress = () => { setvisibleToast(true); }; return ( <View style={styles.container}> <Toast visible={visibleToast} message="Example" /> <Button title="Toggle Toast"  onPress={() => handleButtonPress()} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", paddingTop: StatusBar.currentHeight, backgroundColor: "#888888", padding: 8 } }); export default App;Copy the code

methods
static show(message, duration)
static showWithGravity(message, duration, gravity)
static showWithGravityAndOffset(message, duration, gravity, xOffset, yOffset)
Copy the code
attribute

Indicates the duration on the screen.

ToastAndroid.SHORT;
Copy the code

Indicates the duration on the screen.

ToastAndroid.LONG;
Copy the code

Indicates the position on the screen.

ToastAndroid.TOP;
Copy the code

other

ActivityIndicator

Displays a circular loading prompt.

import React from "react";
import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
const App = () => (
  <View style={[styles.container, styles.horizontal]}>
    <ActivityIndicator />
    <ActivityIndicator size="large" />
    <ActivityIndicator size="small" color="#0000ff" />
    <ActivityIndicator size="large" color="#00ff00" />
  </View>
);
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center"
  },
  horizontal: {
    flexDirection: "row",
    justifyContent: "space-around",
    padding: 10
  }
});
export default App;
Copy the code

Alert

Launches a prompt dialog box with the corresponding title and information.

import React, { useState } from "react";
import { View, StyleSheet, Button, Alert } from "react-native";
const App = () => {
  const createTwoButtonAlert = () =>
    Alert.alert(
      "Alert Title",
      "My Alert Msg",
      [
        {
          text: "Cancel",
          onPress: () => console.log("Cancel Pressed"),
          style: "cancel"
        },
        { text: "OK", onPress: () => console.log("OK Pressed") }
      ]
    );

  const createThreeButtonAlert = () =>
    Alert.alert(
      "Alert Title",
      "My Alert Msg",
      [
        {
          text: "Ask me later",
          onPress: () => console.log("Ask me later pressed")
        },
        {
          text: "Cancel",
          onPress: () => console.log("Cancel Pressed"),
          style: "cancel"
        },
        { text: "OK", onPress: () => console.log("OK Pressed") }
      ]
    );
  return (
    <View style={styles.container}>
      <Button title={"2-Button Alert"} onPress={createTwoButtonAlert} />
      <Button title={"3-Button Alert"} onPress={createThreeButtonAlert} />
    </View>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "space-around",
    alignItems: "center"
  }
});
export default App;
Copy the code

methods
static alert(title, message? , buttons? , options?)Copy the code

title:string The dialog’s title. Passing null or empty string will hide the title.

message:string An optional message that appears below the dialog’s title.

buttons:Buttons An optional array containg buttons configuration.

options:Options-Android An optional Alert configuration for the Android.

static prompt(title, message? , callbackOrButtons? , type? , defaultValue? , keyboardType?)Copy the code

title string Required The dialog’s title.

message string An optional message that appears above the text input.

callbackOrButtons:function|Buttons If passed a function, it will be called with the prompt’s value (text: string) => void, when the user taps ‘OK’. If passed an array, buttons will be configured based on the array content.

Type :AlertType This configures the text input.

defaultValue:string The default text in text input.

keyboardType:string The keyboard type of first text field (if exists). One of TextInput keyboardTypes.

Animated

The Animated library is designed to make animations smooth, powerful, and easy to build and maintain. Animated focuses on declarative relationships between inputs and outputs and configurable transformations between them, as well as simple start/stop methods for controlling time-based animation execution.

Please do not modify the animation value directly! You can use the useRef Hook to return a modified ref reference. The current property of the REF object is given the given animation value when initialized and is saved without destruction for the life of the component.

import React, { useRef } from "react"; import { Animated, Text, View, StyleSheet, Button } from "react-native"; const App = () => { // fadeAnim will be used as the value for opacity. Initial Value: 0 const fadeAnim = useRef(new Animated.Value(0)).current; const fadeIn = () => { // Will change fadeAnim value to 1 in 5 seconds Animated.timing(fadeAnim, { toValue: 1, duration: 5000 }).start(); }; const fadeOut = () => { // Will change fadeAnim value to 0 in 5 seconds Animated.timing(fadeAnim, { toValue: 0, duration: 5000 }).start(); }; return ( <View style={styles.container}> <Animated.View style={[ styles.fadingContainer, { opacity: fadeAnim // Bind opacity to animated value } ]} > <Text style={styles.fadingText}>Fading View! </Text> </Animated.View> <View style={styles.buttonRow}> <Button title="Fade In" onPress={fadeIn} /> <Button title="Fade  Out" onPress={fadeOut} /> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center" }, fadingContainer: { paddingVertical: 8, paddingHorizontal: 16, backgroundColor: "powderblue" }, fadingText: { fontSize: 28, textAlign: "center", margin: 10 }, buttonRow: { flexDirection: "row", marginVertical: 16 } }); export default App;Copy the code

Configuration of the animation

Animated offers three animation types. Each animation type provides a specific function curve that controls how the animation value changes from the initial value to the final value:

  • Animated. Decay () starts at a specified initial speed and then slows down until it stops.
  • Animated. Spring () provides a basic spring physics model.
  • Animated. Timing () moves the values over time using easing.
Use animation

Start the animation by calling start() on the animation. Start () can pass in a callback function to be called on notification when the animation is complete. If the animation works properly, the completion callback receives the value {finished: true}. If the animation ends because stop() was called (for example, because it was interrupted by a gesture or other animation), it receives {finished: false}.

Animated. Timing ({}). Start (({finished}) = > {/ * animation complete callback function * /});Copy the code
Combination of animation

Animations can also be combined in complex ways using composition functions:

  • Imated.delay () starts the animation after the given delay.
  • Imated.parallel () starts multiple animations at the same time.
  • Imatted.sequence () starts the animations in sequence and waits for each animation to complete before starting the next animation.
  • Mated.stagger() at a given delay interval.
The event

Gestures, such as panning or scrolling, and other events can be mapped directly to Animated values using kinetic.event (). This is done through structured mapping syntax so that values can be extracted from complex event objects. The first level argument is an array in which you can specify multiple parameter mappings, which can be nested objects.

For example, when using horizontal scrolling gesture, to the event. NativeEvent. ContentOffset. X is mapped to a scrollX (Animated. The Value), you need to do the following:

onScroll={Animated.event(
   // scrollX = e.nativeEvent.contentOffset.x
   [{ nativeEvent: {
        contentOffset: {
          x: scrollX
        }
      }
    }]
 )}
Copy the code

Dimensions

This module is used to obtain the width and height of the device screen.

import { Dimensions } from 'react-native';
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
Copy the code

KeyboardAvoidingView

This component addresses a common awkwardness: the pop-up keyboard on the phone often blocks the current view. This component can automatically adjust its height or bottom padding according to the height of the keyboard to avoid occlusion.

import React from 'react';
import { View, KeyboardAvoidingView, TextInput, StyleSheet, Text, Platform, TouchableWithoutFeedback, Button, Keyboard  } from 'react-native';
const KeyboardAvoidingComponent = () => {
  return (
    <KeyboardAvoidingView
      behavior={Platform.OS == "ios" ? "padding" : "height"}
      style={styles.container}
    >
      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <View style={styles.inner}>
          <Text style={styles.header}>Header</Text>
          <TextInput placeholder="Username" style={styles.textInput} />
          <View style={styles.btnContainer}>
            <Button title="Submit" onPress={() => null} />
          </View>
        </View>
      </TouchableWithoutFeedback>
    </KeyboardAvoidingView>
  );
};
const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  inner: {
    padding: 24,
    flex: 1,
    justifyContent: "space-around"
  },
  header: {
    fontSize: 36,
    marginBottom: 48
  },
  textInput: {
    height: 40,
    borderColor: "#000000",
    borderBottomWidth: 1,
    marginBottom: 36
  },
  btnContainer: {
    backgroundColor: "white",
    marginTop: 12
  }
});
export default KeyboardAvoidingComponent;
Copy the code

Linking

Linking provides a common interface to interact with incoming and outgoing App links.

Open Links and Deep Links (Universal Links)

import React, { useCallback } from "react"; import { Alert, Button, Linking, StyleSheet, View } from "react-native"; const supportedURL = "https://google.com"; const unsupportedURL = "slack://open? team=123456"; const OpenURLButton = ({ url, children }) => { const handlePress = useCallback(async () => { // Checking if the link is supported for links with custom URL scheme. const supported = await Linking.canOpenURL(url); if (supported) { // Opening the link with some app, if the URL scheme is "http" the web link should be opened // by some browser in the mobile await Linking.openURL(url); } else { Alert.alert(`Don't know how to open this URL: ${url}`); } }, [url]); return <Button title={children} onPress={handlePress} />; }; const App = () => { return ( <View style={styles.container}> <OpenURLButton url={supportedURL}>Open Supported URL</OpenURLButton> <OpenURLButton url={unsupportedURL}>Open Unsupported URL</OpenURLButton> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center" }, }); export default App;Copy the code

Open Custom Settings

import React, { useCallback } from "react";
import { Button, Linking, StyleSheet, View } from "react-native";
const OpenSettingsButton = ({ children }) => {
  const handlePress = useCallback(async () => {
    // Open the custom settings if the app has one
    await Linking.openSettings();
  }, []);
  return <Button title={children} onPress={handlePress} />;
};
const App = () => {
  return (
    <View style={styles.container}>
      <OpenSettingsButton>Open Settings</OpenSettingsButton>
    </View>
  );
};
const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: "center", alignItems: "center" },
});
export default App;
Copy the code

Get Deep Link

import React, { useState, useEffect } from "react";
import { Linking, StyleSheet, Text, View } from "react-native";
const useMount = func => useEffect(() => func(), []);
const useInitialURL = () => {
  const [url, setUrl] = useState(null);
  const [processing, setProcessing] = useState(true);
  useMount(() => {
    const getUrlAsync = async () => {
      // Get the deep link used to open the app
      const initialUrl = await Linking.getInitialURL();
      // The setTimeout is just for testing purpose
      setTimeout(() => {
        setUrl(initialUrl);
        setProcessing(false);
      }, 1000);
    };
    getUrlAsync();
  });
  return { url, processing };
};
const App = () => {
  const { url: initialUrl, processing } = useInitialURL();
  return (
    <View style={styles.container}>
      <Text>
        {processing
          ? `Processing the initial url from a deep link`
          : `The deep link is: ${initialUrl || "None"}`}
      </Text>
    </View>
  );
};
const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: "center", alignItems: "center" },
});
export default App;
Copy the code

Send the Intents (Android)

import React, { useCallback } from "react";
import { Alert, Button, Linking, StyleSheet, View } from "react-native";
const SendIntentButton = ({ action, extras, children }) => {
  const handlePress = useCallback(async () => {
    try {
      await Linking.sendIntent(action, extras);
    } catch (e) {
      Alert.alert(e.message);
    }
  }, [action, extras]);

  return <Button title={children} onPress={handlePress} />;
};
const App = () => {
  return (
    <View style={styles.container}>
      <SendIntentButton action="android.intent.action.POWER_USAGE_SUMMARY">
        Power Usage Summary
      </SendIntentButton>
      <SendIntentButton
        action="android.settings.APP_NOTIFICATION_SETTINGS"
        extras={[
          { "android.provider.extra.APP_PACKAGE": "com.facebook.katana" },
        ]}
      >
        App Notification Settings
      </SendIntentButton>
    </View>
  );
};
const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: "center", alignItems: "center" },
});
export default App;
Copy the code

Modal

A Modal component is a simple way to display content on top of other views.

import React, { useState } from "react"; import { Alert, Modal, StyleSheet, Text, TouchableHighlight, View } from "react-native"; const App = () => { const [modalVisible, setModalVisible] = useState(false); return ( <View style={styles.centeredView}> <Modal animationType="slide" transparent={true} visible={modalVisible} onRequestClose={() => { Alert.alert("Modal has been closed."); setModalVisible(! modalVisible); }} > <View style={styles.centeredView}> <View style={styles.modalView}> <Text style={styles.modalText}>Hello World! </Text> <TouchableHighlight style={{ ... styles.openButton, backgroundColor: "#2196F3" }} onPress={() => { setModalVisible(! modalVisible); }} > <Text style={styles.textStyle}>Hide Modal</Text> </TouchableHighlight> </View> </View> </Modal> <TouchableHighlight  style={styles.openButton} onPress={() => { setModalVisible(true); }} > <Text style={styles.textStyle}>Show Modal</Text> </TouchableHighlight> </View> ); }; const styles = StyleSheet.create({ centeredView: { flex: 1, justifyContent: "center", alignItems: "center", marginTop: 22 }, modalView: { margin: 20, backgroundColor: "white", borderRadius: 20, padding: 35, alignItems: Opacity: 0, height: 2}, shadowOffset: {width: 0, height: 2}, shadowRadius: BackgroundColor: "#F194FF", borderRadius: 20, padding: 10, elevation: 2 }, textStyle: { color: "white", fontWeight: "bold", textAlign: "center" }, modalText: { marginBottom: 15, textAlign: "center" } }); export default App;Copy the code

PixelRatio

PixelRatio gets the pixel density and font size ratio of the device.

import React from "react";
import { Image, PixelRatio, ScrollView, StyleSheet, Text, TextInput, View } from "react-native";
const size = 50;
const cat = {
  uri: "https://reactnative.dev/docs/assets/p_cat1.png",
  width: size,
  height: size
};
const App = () => (
  <ScrollView style={styles.scrollContainer}>
    <View style={styles.container}>
      <Text>Current Pixel Ratio is:</Text>
      <Text style={styles.value}>{PixelRatio.get()}</Text>
    </View>
    <View style={styles.container}>
      <Text>Current Font Scale is:</Text>
      <Text style={styles.value}>{PixelRatio.getFontScale()}</Text>
    </View>
    <View style={styles.container}>
      <Text>On this device images with a layout width of</Text>
      <Text style={styles.value}>{size} px</Text>
      <Image source={cat} />
    </View>
    <View style={styles.container}>
      <Text>require images with a pixel width of</Text>
      <Text style={styles.value}>
        {PixelRatio.getPixelSizeForLayoutSize(size)} px
      </Text>
      <Image
        source={cat}
        style={{
          width: PixelRatio.getPixelSizeForLayoutSize(size),
          height: PixelRatio.getPixelSizeForLayoutSize(size)
        }}
      />
    </View>
  </ScrollView>
);
const styles = StyleSheet.create({
  scrollContainer: {
    flext: 1,
    marginTop: "2em",
    justifyContent: "center",
  },
  container: {
    justifyContent: "center",
    alignItems: "center"
  },
  value: {
    fontSize: 24,
    marginBottom: 12,
    marginTop: 4
  }
});
export default App;
Copy the code

RefreshControl

This component can be used inside a ScrollView or FlatList to add drop-down refresh capabilities to it. When the ScrollView is in the vertical starting position (scrollY: 0), the drop down triggers an onRefresh event.

import React from 'react'; import { ScrollView, RefreshControl, StyleSheet, Text, SafeAreaView, } from 'react-native'; import Constants from 'expo-constants'; const wait = (timeout) => { return new Promise(resolve => { setTimeout(resolve, timeout); }); } const App = () => { const [refreshing, setRefreshing] = React.useState(false); const onRefresh = React.useCallback(() => { setRefreshing(true); wait(2000).then(() => setRefreshing(false)); } []); return ( <SafeAreaView style={styles.container}> <ScrollView contentContainerStyle={styles.scrollView} refreshControl={ <RefreshControl refreshing={refreshing} onRefresh={onRefresh} /> } > <Text>Pull down to see RefreshControl indicator</Text> </ScrollView> </SafeAreaView> ); } const styles = StyleSheet.create({ container: { flex: 1, marginTop: Constants.statusBarHeight, }, scrollView: { flex: 1, backgroundColor: 'pink', alignItems: 'center', justifyContent: 'center', }, }); export default App;Copy the code

Note: Refreshing is a controlled property, so you must set it to true in the onRefresh function otherwise the loading indicator will stop immediately.

StatusBar

The component that controls the application status bar.

Considerations for using with navigator #

Since StatusBar can be loaded in any view, you can place multiple, later-loaded ones that override the ones loaded first. Therefore, when using with the navigator, it is important to consider the placement order of the StatusBar.

import React, { useState } from "react"; import { Button, Text, StyleSheet, StatusBar, View } from "react-native"; import Constants from "expo-constants"; const App = () => { const styleTypes = ['default','dark-content', 'light-content']; const [visibleStatusBar, setVisibleStatusBar] = useState(false); const [styleStatusBar, setStyleStatusBar] = useState(styleTypes[0]); const changeVisibilityStatusBar = () => { setVisibleStatusBar(! visibleStatusBar); }; const changeStyleStatusBar = () => { const styleId = styleTypes.indexOf(styleStatusBar) + 1; if(styleId === styleTypes.length){ return setStyleStatusBar(styleTypes[0]); } return setStyleStatusBar(styleTypes[styleId]); }; return ( <View style={styles.container}> <View> <Text style={styles.textStyle}>StatusBar Style: {styleStatusBar}</Text> <Text style={styles.textStyle}>StatusBar Visibility: {! visibleStatusBar ? 'Visible': 'Hidden'}</Text> </View> <StatusBar backgroundColor="blue" barStyle={styleStatusBar} /> <View> <StatusBar hidden={visibleStatusBar} /> </View> <View style={styles.buttonContainer}> <Button title="Toggle StatusBar" onPress={() => changeVisibilityStatusBar()} /> </View> <View style={styles.buttonContainer}> <Button title="Change StatusBar Style" onPress={() => changeStyleStatusBar()} /> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', paddingTop: Constants.statusBarHeight, backgroundColor: '#ECF0F1', padding: 8 }, buttonContainer:{ padding: 10 }, textStyle:{ textAlign: 'center' } }); export default App;Copy the code