Writing in the front

During my two years of work on React Native (hereinafter referred to as RN) development, I and my team members often encountered some puzzling screen adaption problems, such as: the full-screen mask style could not cover the whole screen, the 1-pixel frame could not be displayed sometimes, and the layout of special models was confused. In addition, some members are confused about the meaning of the value returned by Dimensions. Get (‘window’) and dimension. get(‘screen’), the API for RN to get screen parameters. In fact, the adaptation of RN is relatively simple. In this paper, I will elaborate the adaptation principle, put forward the adaptation scheme, and explain the reasons for some special problems one by one. In principle, it can cover the adaptation of all models. If there is any omission or impropriation, please point out and communicate with us.

Recommended articles from past highlights:



Perhaps the most useful React Native exception solution in the web

Suitable for Reading Groups

  • Have some experience in RN development, understand how RN JS module communicates with native module;
  • Have experience with RN adaptation, understand but not fully understand the kind of;
  • Want to know about RN adaptation;

Why do you need adaptations

Ensure that the interface can be displayed on different device screens according to the effect of the design, so as to unify the user’s vision and operation experience

Explanation of common appropriate nouns

If you go online and search for screen adapters, you’ll probably come up with a list of the following terms and their explanations

  1. Adaptation: the element display effect is consistent under different screens
  2. Screen Size: Refers to the length of the diagonal of the screen
  3. PX: PX is actually short for Pixel. According to Wikipedia, it is the basic unit of image display. It is neither a definite physical quantity, nor a dot or square, but an abstract concept. So be sure to be aware of the context when talking about pixels!
  4. Resolution: refers to the maximum number of physical pixels that can be displayed in width and height
  5. Device physical pixel: refers to the smallest physical unit that the device can control the display. It refers to the dots on the display. From the day the screen is produced in a factory, the device pixels on it are fixed, depending on the size of the screen
  6. Device Independent Pixel (Device Logic Pixel) : A point in a computer coordinate system that represents a virtual pixel (e.g., CSS Pixel) that can be used by a program. The point has no fixed size, the smaller the clearer, and is converted to a physical pixel by the related system
  7. CSS pixels: The correlation between CSS px and physical pixels, which is related to viewport scaling, is 1px for one physical pixel when scale = 1/ DPR
  8. DPI: Density of printing points in printing equipment. How many points per inch
  9. PPI: physical pixel density of the device. How many physical pixels per inch
  10. DPR: Device Pixel Ratio = Device Physical Pixels/Device Individual Pixels (CSS Pixels)

How most people feel after reading these nouns: I get it, but I don’t fully understand it! ~ Let’s forget about these nouns and just remember the following 4 concepts:

  • Adaptation: the element display effect is consistent under different screens
  • Device independent pixels = Device logic pixels =CSS pixels
  • DPR: Device Pixel Ratio = Device Physical Pixels/Device Individual Pixels (CSS Pixels)
  • The dimensions in the design and code are CSS pixels

OK, now, let’s start the course! Guests, please follow me.


Rn is a unit of size

To do an RN fit, you must first understand the size units of the RN style. It is clearly marked on the official website of RN:

All dimensions in React Native are unitless, and represent density-independent pixels.


Dimensions in React Native are unitless and represent logical pixels that are independent of device pixel density.

Why unitless logical pixels?

Because RN is a cross-platform framework, the size is usually described by logical pixel unit PT on iOS, and the size is usually described by logical pixel unit DP on Android. It is not a good choice for RN. Since we all have the same idea, we simply do not use units, and the default rendering unit will be used on any platform. RN provides the developer with a logical pixel size that has already been converted by DPR (device pixel ratio). Developers do not need to worry about the size numerical calculation caused by different device DPR. In some blog posts, it is mentioned that RN has been adapted, which is what it means.

Adaptation scheme

Note: The design drawings in the examples and descriptions are 375X667 (iPhone6/7/8).

For RN adaptation, I summarized the following formula: one idea, one pixel, one proportion; Local boxes are all proportioned; Encounter the whole page layout in the vertical direction of a flick; Android has to deal with the status bar.

A concept

What about the idea that elements look the same on different screens? For example, suppose there is an element labeled 375X44 on a 375X667 design, that is, the width of the entire screen and the height of 44px. If we have the RN screen fit right, then: on iPhone 6/7/8(375X667) and iPhone X(375X812), this element will render the full screen width; On iPhone 6/7/8 Plus(414X736), this element should also fill the screen width;


For example, in real life, according to the size of Engel’s coefficient, the United Nations has a standard for the living standard of all countries in the world, that is, a country’s average family Engel’s coefficient is greater than 60% is poor; 50%-60% for food and clothing; 40%-50% are well-off; 30-40% are relatively wealthy; 20% to 30% are affluent; Less than 20% are extremely wealthy. Assuming that in order to achieve a well-off life, no matter what country you live in, developed or developing, your family’s Engel coefficient must reach 40 to 50 percent. Here, the country can be understood as the mobile phone screen, the standard of living is understood as the element rendering effect. For some of the above terms, such as: physical pixel, pixel ratio, etc., you can understand the country’s currency and currency exchange rate. After all, programming comes from life.

So, you are moving bricks, well off ~?


A pixel

All dimensions in RN style, Including but not limited to width, height, margin, padding, top, left, bottom, right, fontSize, lineHeight, transform and so on are logical pixels (web players can understand CSS pixels).

H3: {color: '#4A4A4A', fontSize: 13, lineHeight: 20,// Logi marginLeft: 25, marginRight: 25,},

A proportion of

In order to provide better vision and user operation experience, currently popular mobile terminal adapters are all width adapters in terms of size and freely arranged in vertical direction in layout. This has the advantage of ensuring that the elements on the page are scaled to the same size as the design, so that the content only covers the width of the screen. If the content is off the screen vertically, you can scroll up and down to see more of the page. Of course, if you want to go in a special way, it’s designed to be highly adaptive, and horizontal gliding is also possible. Going back to the “one idea” example above, on iPhone 6/7/8 Plus(414X736), rendering a design with a 375-size element can easily work out what width we actually want to set: 375 * 414/375 = 414. The 414/375 here is the logical pixel width ratio for the device

Formula: WLR = Device Width Logical Pixel/Design Width

WLR(Width Logic Rate abbreviation), English in bulk, lol.


Here, the width of the device logical pixel I recommend to use
Dimensions.get('window').widthI’ll explain why.
[Q1]

Then, the formula to calculate the size on the target device is: size = size * WLR In fact, all adaptations are done around a scale, such as web side scaling, REM adaptation, PostCSS Plugin, etc. There are many roads, but all roads lead to the same place!

Local boxes are all to scale

For the sake of understanding, “box” here means the same thing as the “box model” on the Web.

Local boxes are all to scale. RN page element size, position, inside and outside margins, etc. related to size, all according to the aboveA proportion ofTo calculate the size of the formula. As shown in the figure below:



The effect of this rendering will maximize the retention of the size and layout of the design.

Why to say the maximum, here is left as a question, later in the article explained.
[Q2]

At this point, some novice students may ask: why not use the device height logical pixel ratio to calculate in the vertical direction? Because device height logical pixels/design height does not necessarily equal device width logical pixels/design width, it can cause box stretching. For example, now render a 100X100px square box on iPhone X(375X812) with a width logical pixel ratio of 1 and a height logical pixel ratio of 812/667≈1.22. If the width and height are calculated according to the previous two ratios, then the final box model size will be:

  view1: {
    width: 100,
    height: 122,
  },



Well, a good square has been stretched to grow into a square!



This is clearly undesirable.

At this point, RN adaption is actually 70% complete, that’s right, playing with multiplication and division

Encounter the entire page layout in the vertical direction of a flick

What is a full page layout?

The content just fills the page and doesn’t spill over the screen.

The flick here refers to the Flex layout. In RN, the default layout is all Flex, and the direction is Column, from top to bottom.

Why do you play it?

Let’s first look at the common layout design of the upper, middle and lower sections of the whole page on mobile terminals, taking the UI design of the old version of a single TCL IoT product as an example:



By design, a 6/7/8 iPhone (375X667) would fill the page exactly, and an iPhone 6/7/8 Plus (414X736) would also fill the page approximately according to the fitting method described above, because414/375 material 736/667. However, on the iPhone X(375X812), if you lay it out from the top down, you’ll see a gap at the bottom:



There are two ways to do this:

  1. Bottom – control menu bar area using absolute positioningbottom:0Fixed at the bottom, the top – status bar + title bar is fixed at the top, do not need to deal with, then calculate and use absolute positioning fine-tune the top – device information display area, the middle – device status area position, so that they exactly split the extra blank space, make the page look more coordinated;
  2. JustifyContent :’space-between’ is set to justifyContent:’space-between’ in RN Flex to justify the top and bottom of the box. The middle area divides the extra white space between the top and the bottom. First, each device needs to calculate the size of the blank area, and then fine-tune the position of elements, which is very troublesome. I recommend the second one, which is easier to code. Those of you who are worried that the second method will cause the middle area to be very large vertically and the page to look inconsistent. However, in practice, the height of the logical pixel on the screen of the device is rarely much larger than 667, and the extra blank area is relatively small, so the UI effect is still OK. At present, N products we have launched are also using this way, please feel free to eat.


At this point, RN adaptation should be complete if you follow past Web side adaptations, but there are still some snags.

Android has to deal with the status bar

RN is cross-platform, but it doesn’t render the same on iOS and Android. The most obvious one is the status bar. As shown in the figure below:



Android is not setStatusBartranslucentProperties fortrueIs drawn from the bottom of the status bar. This is not consistent with our adaptation goals, because in our design, the full page layout is designed to cover the status bar. Therefore, it is recommended to put the Android status bartranslucentAttribute is set totrue, the whole page to us developers to layout.

<StatusBar translucent={true} />

If you’ve seen this far, congratulations, you’ve mastered RN adaptation, which can handle more than 90% of scenarios.


But there are also some weird scenarios and some APIs that you may not understand, which are included in the remaining 10% of adaptation scenarios or in which to help you understand and debug. Never mind, I’ll go on. Some of them involve source code, so if you’re interested, you can follow me through.


There’s a lot going on here, but for me personally, this is the most important part of what I want to share with you.

Something weird and funny

This section is very extensive, please read it as you wish

1. DimensionsAPI

Dimensions is an API provided by RN to retrieve device size information. We can use it to get the width and height of the screen, which is the core API for doing adaptations. It provides two ways to get it:

const {windowWidth,windowHeight} = Dimensions.get('window');
const {screenWidth,screenHeight} = Dimensions.get('screen');

The official documentation does not explain the meaning and difference between the two methods of obtaining results. In the actual development, sometimes the results obtained by these two methods are the same, and sometimes they are different, which makes some students confused: which one is the right one to use? I recommend that you always use Dimension.get (‘window’). It’s only the results we get from it that we can really control the area we’re drawing. First, clarify the meaning of the results obtained by these two methods:

  • Dimensions.get('window')— Obtain viewport parameters: width, height, scale, fontScale
  • Dimensions. Get (‘screen’) — select width, height, scale, fontScale (); By default, the width and height of screen are always greater than or equal to the width and height of window when the device screen is in the same state, because the parameters obtained by window exclude the height of status bar (when translucent is false) and the height of virtual menu bar at the bottom. When the android has the status bar translucent set to true and the virtual menu bar is not turned on, Dimensions. Get (‘window’) will be the same as Dimensions. Get (‘screen’) width and height, otherwise different. This is the answer to the sometimes identical and sometimes different question at the beginning of this paragraph.


    This is not by conjecture or groundless, direct source arrangement on:

    Due to the limited equipment of the author, the source code of this paper is only analyzed from the Android platform. For the source code of IOS, students with IOS experience can refer to it by themselves according to their ideas.


    Preparation: in accordance with
    The official documentationCreate a new Demo RN project. For stability, we use a previous version of RN, 0.62.0. The command is as follows:


    NPX React - Native Init Demo -- Version 0.62.0

Step 1. Find the JS file of the RN API first. node_modules\react-native\Libraries\Utilities\Dimensions.js

/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format * @flow */ 'use strict'; import EventEmitter from '.. /vendor/emitter/EventEmitter'; import RCTDeviceEventEmitter from '.. /EventEmitter/RCTDeviceEventEmitter'; import NativeDeviceInfo, { type DisplayMetrics, type DimensionsPayload, } from './NativeDeviceInfo'; import invariant from 'invariant'; type DimensionsValue = { window? : DisplayMetrics, screen? : DisplayMetrics, ... }; const eventEmitter = new EventEmitter(); let dimensionsInitialized = false; let dimensions: DimensionsValue; class Dimensions { /** * NOTE: `useWindowDimensions` is the preffered API for React components. * * Initial dimensions are set before `runApplication` is called so they should * be available before any other require's are run, but may be updated later. * * Note: Although dimensions are available immediately, they may change (e.g * due to device rotation) so any rendering logic or styles that depend on * these constants should try to call this function on every render, rather * than caching the value (for example, using inline styles rather than * setting a value in a `StyleSheet`). * * Example: `const {height, width} = Dimensions.get('window'); ` * * @param {string} dim Name of dimension as defined when calling `set`. * @returns {Object? } Value for the dimension. */ static get(dim: string): Object { invariant(dimensions[dim], 'No dimension set for key ' + dim); return dimensions[dim]; } /** * This should only be called from native code by sending the * didUpdateDimensions event. * * @param {object} dims  Simple string-keyed object of dimensions to set */ static set(dims: $ReadOnly<{[key: string]: any, ... } >) : void { // We calculate the window dimensions in JS so that we don't encounter loss of // precision in transferring the dimensions (which could be non-integers) over // the bridge. let {screen, window} = dims; const {windowPhysicalPixels} = dims; if (windowPhysicalPixels) { window = { width: windowPhysicalPixels.width / windowPhysicalPixels.scale, height: windowPhysicalPixels.height / windowPhysicalPixels.scale, scale: windowPhysicalPixels.scale, fontScale: windowPhysicalPixels.fontScale, }; } const {screenPhysicalPixels} = dims; if (screenPhysicalPixels) { screen = { width: screenPhysicalPixels.width / screenPhysicalPixels.scale, height: screenPhysicalPixels.height / screenPhysicalPixels.scale, scale: screenPhysicalPixels.scale, fontScale: screenPhysicalPixels.fontScale, }; } else if (screen == null) { screen = window; } dimensions = {window, screen}; if (dimensionsInitialized) { // Don't fire 'change' the first time the dimensions are set. eventEmitter.emit('change', dimensions); } else { dimensionsInitialized = true; } } /** * Add an event handler. Supported events: * * - `change`: Fires when a property within the `Dimensions` object changes. The argument * to the event handler is an object with `window` and `screen` properties whose values * are the same as the return values of `Dimensions.get('window')` and * `Dimensions.get('screen')`, respectively. */ static addEventListener(type: 'change', handler: Function) { invariant( type === 'change', 'Trying to subscribe to unknown event: "%s"', type, ); eventEmitter.addListener(type, handler); } /** * Remove an event handler. */ static removeEventListener(type: 'change', handler: Function) { invariant( type === 'change', 'Trying to remove listener for unknown event: "%s"', type, ); eventEmitter.removeListener(type, handler); } } let initialDims: ? $ReadOnly<{[key: string]: any, ... }> = global.nativeExtensions && global.nativeExtensions.DeviceInfo && global.nativeExtensions.DeviceInfo.Dimensions; if (! initialDims) { // Subscribe before calling getConstants to make sure we don't miss any updates in between. RCTDeviceEventEmitter.addListener( 'didUpdateDimensions', (update: DimensionsPayload) => { Dimensions.set(update); }); // Can't use NativeDeviceInfo in ComponentScript because it does not support NativeModules, // but has nativeExtensions instead. initialDims = NativeDeviceInfo.getConstants().Dimensions; } Dimensions.set(initialDims); module.exports = Dimensions;

The dimension.js module initializes the Dimensions parameter information that our dimension.get () method retrieves. Also, the module indicates the source of the information:

/ /... initialDims = NativeDeviceInfo.getConstants().Dimensions; / /... Dimensions.set(initialDims); let {screen, window} = dims const {windowPhysicalPixels} = dims const {screenPhysicalPixels} = dims //... dimensions = {window, screen};

The data source is from the DeviceInfo module in the native module. Well, let’s go straight to the Android source code and see what it has to offer.

step2: Get the Android source jar package from node_modules\react-native\android\com\ Facebook \react-native\0.62.0\react-native-0.62.0-sources.jar



Download it and save it locally.

step3: The use of toolsjava decompilerdecompilingThe react - native - 0.62.0 - sources. The jar:



As you can see, there are many packages. We headed tocom.facebook.react.modulesThis module is where most of the APIs provided for RN JSC are native.



step4: Open thecom.facebook.react.modules.deviceinfo.DeviceInfoModule.java:

Look at the red box in the picture, which is in the JS module above

initialDims = NativeDeviceInfo.getConstants().Dimensions; 

The initial size information of the device is derived from this.

step5:Open theDisplayMetricsHolder.javaTo findgetDisplayMetricsMap()Methods:



How’s thatwindowPhysicalPixels & screenPhysicalPixelsIs that familiar? And their property fieldswidth,height,scale,fontScale,densityDpiDo you often use a part of it? Yeah, you started itDimensions.jsWe’ve seen them in:



Strictly speaking,Dimensions.jsDid I miss onedensityDpi(device pixel density) is not deconstructed ~

OK, so let’s look at their original data source:

result.put("windowPhysicalPixels", getPhysicalPixelsMap(sWindowDisplayMetrics, fontScale));
result.put("screenPhysicalPixels", getPhysicalPixelsMap(sScreenDisplayMetrics, fontScale));

From: SwindowDisplayMetrics, SScreenDisplayMetrics. Among them, SwindowDisplayMetrics passes

DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics);

Settings; SScreenDisplayMetrics through

DisplayMetrics screenDisplayMetrics = new DisplayMetrics(); screenDisplayMetrics.setTo(displayMetrics); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Assertions.assertNotNull(wm, "WindowManager is null!" ); Display display = wm.getDefaultDisplay(); // Get the real display metrics if we are using API level 17 or higher. // The real metrics include system decor elements (e.g. soft menu bar). // // See: // http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { display.getRealMetrics(screenDisplayMetrics); } else { // For 14 <= API level <= 16, we need to invoke getRawHeight and getRawWidth to get the real // dimensions. // Since react-native only supports API level 16+ we don't have to worry about other cases. // // Reflection exceptions are rethrown at runtime. // // See: // http://stackoverflow.com/questions/14341041/how-to-get-real-screen-height-and-width/23861333#23861333 try { Method mGetRawH = Display.class.getMethod("getRawHeight"); Method mGetRawW = Display.class.getMethod("getRawWidth"); screenDisplayMetrics.widthPixels = (Integer) mGetRawW.invoke(display); screenDisplayMetrics.heightPixels = (Integer) mGetRawH.invoke(display); } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { throw new RuntimeException("Error getting real dimensions for API level < 17", e); } } DisplayMetricsHolder.setScreenDisplayMetrics(screenDisplayMetrics);

Settings.

In the androidcontext.getResources().getDisplayMetrics();Only the size information of the drawing area will be obtained. By default, the top status bar and the bottom virtual menu bar will be removed. When ScreenDisplayMetrics is set, although there is version differentiation, it ultimately captures the physical resolution of the entire screen.

So you can really explain what happened at the beginning. And it goes completely from the JS layer to the native layerDimensionsAPI, okay, I’m going to talk about this one for a long time, do you guys see that?

The full-screen mask style does not cover the entire screen

This is a problem with some older Android phones, around the middle and low end of 2016 to 2018, and most of them are Honor models. These phones come with a virtual menu bar at the bottom, which can be automatically/manually hidden when used. Problem situation: When a custom Modal with a mask pops up, if the mask height is set to dimensions.get (‘window’).height, after hiding the virtual menu bar at the bottom, there will be an empty section at the bottom that cannot be masked by the mask. Cause of the problem: The height of the page’s drawing area has changed since the menu bar was hidden, and the rendered view is the same as the last time the menu bar was not hidden. Solution: Listen for screen state changes, which is actually pointed out on the website (https://www.react-native.cn/d… Using Dimensions. The addEventListener () to monitor and set the height of mask, the key is to change the state, by state driving view update. Dimensions are, of course, remember to remove the event listeners. The removeEventListener ()

1 pixel borders are sometimes not displayed

RN’s 1-pixel border, usually refers to:

StyleSheet.hairlineWidth

It is a constant and will render to the smallest standard for the current platform.

However, when setting the subitems in the list, often some of the subitems in the list will lose this line, and weirdly, the same line, some mobile phones show normal, some mobile phones do not show, and even some models on the line will be more “fat”.



The old rules, the source code to move:

It can be found in node_modules\react-native\Libraries\StyleSheet\ stylesheet.js:

Let hairlineWidth: number = PixelRatio roundToNearestPixel (0.4); if (hairlineWidth === 0) { hairlineWidth = 1 / PixelRatio.get(); }

Then find it in node_modules\react-native\Libraries\Utilities\PixelRatio. Js:

/** * Rounds a layout size (dp) to the nearest layout size that corresponds to * an integer number of pixels. For Example, on a device with a PixelRatio * of 3, ` PixelRatio. RoundToNearestPixel ` (8.4) = 8.33, 9. Which brickscan to * exactly (8.33 * 3) = 25 pixels. */ Static RoundtoneArestPixel (LayoutSize: Number): number { const ratio = PixelRatio.get(); return Math.round(layoutSize * ratio) / ratio; }

This principle is to render a line around 0.4 logical pixels, the value is not necessarily 0.4, according to the RoundtoneRustPixel converted to a value that occupies the most integer physical pixels, related to the device DPR, is also the scale property value in the above Dimensions. The worst case is 1 / pixelRatio. Get () for a DPR less than 1.25. Calculate according to the above rules, however, it should be displayed anyway. However, we will introduce two concepts first — pixel mesh alignment and JavaScript number precision:

We can specify any precision when we set the logical pixels, but when the device renders, the actual physical pixels are displayed one by one, and the physical pixels are always whole. In order to ensure correct display at any accuracy, RN renders pixel mesh alignment; JavaScript doesn’t really have integers. Its number types are implemented based on the IEEE 754 standard, using the 64-bit binary “double precision” format. There is a “machine precision” error between the values, usually Math.pow(2,-52).

With the concept out of the way, let’s look at an example:

Let’s say I have an Android with a DPR of 1.5. Render 2 above and below the pageheight = StyleSheet.hairlineWidth View, according to the above calculation rules, at this time0.66666667 height = StyleSheet. HairlineWidth material, ideally occupying 1px of a physical pixel. But the reality may be:



Because of the JS digital accuracy problem,Math.round(0.4 * 1.5) / 1.5Take the1.5Not necessarily equal to1It could be greater than 1, it could be less than 1, and of course, it could be equal to 1.

Confused?

Let me show you one of the most frequently met questions:

0.1+0.2 === 0.3 // false

How’s that? Got it? Ha ha

The physical pixel is the whole. If it is greater than 1, it will occupy 2 physical pixels; if it is less than 1, it may occupy 1 or not; if it is equal to 1, it will be displayed normally. This is the pixel mesh alignment that causes the stylesheet.hairlinewidth display to be set in 3 situations:

  • Display is thicker than expected;
  • Display normal;
  • Don’t show;

Solution: For the most part, stylesheet.hairlinewidth actually behaves well. If this problem occurs, you can try a value between 0.4 and 1 to set the size:

wrapper:{
  height:.8,
  backgroundColor:'#333'
}

Then look at the render and choose the one that works best.

conclusion

In this paper, I first introduced the RN adaptation scheme, and summed up an adaptation formula for everyone. If you understand this formula, you’ve basically mastered RN adaptation; Then, from the point of view of source code, we trace back to the source of the core API – Dimensions meaning and the source of its value; Finally, it explains the phenomenon or problem that “the full screen mask cannot cover the whole screen” and “the 1 pixel border sometimes cannot be displayed”. Hope you found this article useful! If you think it is good, welcome thumb up and collection and recommend to friends around, thank you for your encouragement and recognition! Any questions are also welcome to leave a message or private message I original is not easy, reproduced to obtain my consent.

FQA

  1. Bangs screen, irregular screen how to adapt?

    Enabling “immersive” drawing is recommended. This is enabled by default on iOS and required for Android<StatusBar translucent={true} />. Then set the height of the top status bar + title bar according to the actual situation of fringe and special-shaped screen.
  2. How do you fit into a larger tablet like the iPad?

    You need to look at the actual business. If the demand only needs to be consistent with the mobile terminal, then I can directly use this scheme. If landscape and portrait adaptations are also required, then you need to use themDimensions.addEventListener()Monitor and set the RN viewport parameters at this time. When calculating the proportion, the monitored value is taken as the standard, and then ADAPTS.
  3. Why is adaptation the ultimate restoration of design? ([Q2] in the text) I mentioned pixel mesh alignment and JS digital precision issues in the section “1 Pixel Bounds Sometimes Can’t Be Displayed”. In the process of adaptation, the values we finally set are calculated according to the proportion, which may result in accuracy error. In addition, the pixel grid alignment may result in some special cases after rendering, such as the continuous rendering of a large number of small element nodes in a certain area, which may lead to subtle differences with the design drawing.