Writing in the front
During my two-year work in React Native (RN for short) development, I and my team members often encountered some puzzling screen adaptation problems, such as the inability of the full-screen mask style to cover the entire screen, the inability to display the 1-pixel border, and the incorrect layout of special models. In addition, some members have doubts about the meaning of the values returned by RN’s API for retrieving screen parameters — dimension.get (‘window’) and dimension.get (‘screen’). In fact, the adaptation of RN is relatively simple. In this paper, I will elaborate the adaptation principle, put forward adaptation solutions, and explain the reasons for some special problems one by one. In principle, it can cover the adaptation of all models. If there are omissions and improper place, welcome to point out, common communication.
This is probably the most practical React Native exception solution on the web.
Suitable for reading groups
- Have some experience in RN development, understand how RN JS modules communicate with native modules;
- Experienced in RN adaptation, understood but not fully understood;
- I want to know about RN adaptation;
Why do we need adaptation
Ensure that the interface can be displayed on different device screens according to the design effect, and unify the user’s vision and operation experience
It is often illustrated with nouns
If you search the Internet for screen adaptations, you’ll probably come up with a list of terms and explanations
- Adaptation: The display effect of elements on different screens is consistent
- Screen size: Refers to the diagonal length of the screen
- Px (unit) : Px actually stands for Pixel. According to Wikipedia, px is the basic unit of image display, neither a definite physical quantity, nor a dot or square, but an abstract concept. So be aware of the context when talking about pixels!
- Resolution: The maximum number of physical pixels that can be displayed in width and height
- Device physical pixel: refers to the smallest physical unit that the device can control the display. It refers to the points on the display. From the day a screen is manufactured in a factory, the pixels on the device are fixed, depending on the size of the screen
- Device-independent pixel (device-logical pixel) : A point in a computer coordinate system that represents a virtual pixel (e.g., CSS pixel) that can be used by a program. This point has no fixed size, and the smaller the pixel, the clearer the pixel, is converted into a physical pixel by the relevant system
- CSS pixel: the mapping between CSS PX and physical pixels is related to the zoom of viewport. When scale = 1/ DPR, 1px corresponds to a physical pixel
- DPI: printing point density of the printing device. How many points per inch
- PPI: physical pixel density of the device. How many physical pixels per inch
- DPR: Device pixel ratio = device physical pixels/device independent pixels (CSS pixels)
Let’s forget about these nouns for a moment and just remember these four concepts:
- Adaptation: The display effect of elements on different screens is consistent
- Device independent pixels = device logical pixels =CSS pixels
- DPR: Device pixel ratio = device physical pixels/device independent pixels (CSS pixels)
- The dimensions in the design and coding are CSS pixels
OK, next, the main course begins! Guest officers, please follow me.
A dimensional unit of RN
To do RN fit, you need to understand the size units of RN style. It is clearly marked on RN’s official website:
All dimensions in React Native are unitless, and represent density-independent pixels.
The sizes in React Native are unitless and represent logical pixels that are independent of the pixel density of the device.
Why unitless logical pixels?
RN is a cross-platform framework. On IOS, the size is usually described in logical pixel unit pt, while on Android, the size is usually described in logical pixel unit DP. It is not good to choose RN either. RN provides developers with logical pixel sizes that have been converted through DPR (device pixel ratio). Developers do not need to worry about size numerical calculation problems caused by different device DPR. In some blog posts, RN has been adapted, which is what it actually means.
Adaptation scheme
Note: The design drawings in both the examples and descriptions are 375X667 (iphone6/7/8).
For RN adaptation, I summarize it as the following formula: one idea, one pixel, one proportion; Local boxes are all proportional; Encounter the whole page layout in the vertical direction of a play; Android needs to handle the status bar.
A concept
How do you understand the idea that adaptation is the same thing on different screens? For example, let’s say there is an element that is 375X44 on a 375X667 design that is the width of the entire screen and 44px high. If we screen fit RN, it will fill the screen width on iPhone 6/7/8(375X667) and iPhone X(375X812); On iPhone 6/7/8 Plus(414X736), this element should also fill the screen width;
Take an example in real life: According to the Size of the Engel coefficient, the United Nations has a standard to divide the living standards of all countries in the world, that is, a country with an average family engel coefficient greater than 60% is poor; 50-60% food and clothing; 40-50% well-off; 30-40% are relatively wealthy; 20-30% are affluent; Less than 20% are considered extremely wealthy. Assuming that in order to achieve a well-off life, no matter what country you are from, developed or developing, the Engel coefficient of your family must reach 40-50%. Here, countries can be understood as mobile phone screens, and living standards can be understood as element rendering effects. For some of the above terms, such as physical pixel, pixel ratio, etc., you can think of them as national currency and currency exchange rate. After all, programming comes from life.
So, are you moving brick, well-off ~?
A pixel
All sizes in RN style, Including but not limited to width, height, margin, padding, top, left, bottom, right, fontSize, lineHeight, transform, etc. are all logical pixels (CSS pixels for Web players).
h3: {
color: '#4A4A4A'.fontSize: 13.lineHeight: 20.// Logical pixels
marginLeft: 25.marginRight: 25,},Copy the code
A proportion of
In order to provide better vision and user operation experience, the current popular mobile terminal adaptation scheme adopts width adaptation in size and free vertical arrangement in layout. The advantage of doing this is to ensure that elements on the page are scaled to the same scale as the design, so that the content can only be spread across the screen width. If vertical content is out of the screen, you can swipe up and down to see more content on the page. Of course, if you want to go in a particular direction and design it to be highly adaptable, you can also slide horizontally. Going back to the “one idea” example above, rendering a design 375 element on the iPhone 6/7/8 Plus(414X736) makes it easy to calculate the actual width we want to set: 375 * 414/375 = 414. Here 414/375 is the logical pixel width ratio of the device
Formula :WLR = device width Logical pixels/design width
WLR(Width Logic Rate abbreviation), bulk English, ha ha. In this case, the width of the device is the logical pixel I recommend using the Dimensions. Get (‘window’).width, for reasons explained later. [Q1]
So, in the target device to set the size of the calculation formula is: size = set diagram element size * WLR primary four operations, very simple! In fact, all adaptations are done around a proportion, such as Web scaling, REM adaptation, postCSS plugin, etc., all roads lead to the same destination!
Partial boxes are all proportional
For ease of understanding, “box” here means the same as “box model” on the Web.
Partial boxes are all proportional. It means that the size, position, inner and outer margins of elements in RN page are all calculated according to the size calculation formula in the above proportion. As shown below:
The result of this rendering will retain the size and layout of the design as much as possible.
Why is it the maximum? Here is a question for later explanation. [Q2]
At this point, newbies may ask: Why not use the device’s high logical pixel ratio in the vertical direction? Because the height of the device logical pixel/design drawing does not necessarily equal the width of the device logical pixel/design drawing, it will cause the box to stretch. For example, now render a 100X100px square box on iPhone X(375X812) according to the design drawing. The ratio of width logical pixel is 1, and the ratio of height logical pixel is 812/667≈1.22. If the width and height are calculated according to the previous two ratios respectively, then the size of the final box model will become:
view1: {
width: 100.height: 122,},Copy the code
Well, a square has been stretched into a square!
This is obviously undesirable.
So, RN adaptation is actually 70% done, right, multiplication and division
Hit the whole page layout vertically
What is a full page layout?
Content just fills the page without spilling over the screen.
The flick here refers to the Flex layout. In RN, the default is flex layout, and the orientation is column, from top to bottom.
Why do you have to play it?
Let’s first look at the common layout design of the top, middle and bottom sections of the whole page on mobile terminals, taking the UI design of the old version of TCL IOT products as an example:By design, the entire page is exactly covered on the iPhone 6/7/8 model (375X667), and on the iPhone 6/7/8 model plus(414X736), it is also approximately covered according to the above adaptation method, because414/375 material 736/667
. On the iPhone X(375X812), however, if you lay it out from top to bottom, you’ll see a gap at the bottom:
There are two ways to handle this:
- Bottom – Controls the menu bar area using absolute positioning
bottom:0
Fixed at the bottom, the top – status bar + title bar is fixed at the top, do not need to deal with, and then calculate and absolute positioning fine-tune the top – device information display area, middle – device status area, so that they exactly equal the extra blank space, so that the page looks more coordinated; - Top – device display area, middle – Device status area, bottom – Controls menu bar area wrapped with parent container, take advantage of RN Flex’s flexible layout features, set
justifyContent:'space-between'
Make the three areas vertically aligned up and down, and the middle area bisect the extra blank area.
First, each device needs to calculate the size of the white space, and then fine-tune the element position, which is very troublesome. I recommend the second option, which is much simpler to code. This is the “flick”. Some of you will be worried that the second method will cause the middle area to have a very large vertical span and the page will look uncoordinated. However, in practice, the height of logical pixels 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 ok. At present, N products we have launched also use this method, please rest assured to eat it.
At this point, RN adaptation should be complete if we are any guide to web side adaptation, but there are still some pitfalls.
Android needs to handle the status bar
RN is cross-platform, but renders differently on ios and Android. The most obvious is the status bar. As shown below:
Android is not setStatusBar
的 translucent
Properties fortrue
Is drawn from below the status bar. This didn’t fit our goals, because in our design, the entire page layout was designed to cover the status bar. Therefore, it is recommended to put the Android status bartranslucent
Attribute is set totrue
, the whole page is left to us developers to layout.
<StatusBar translucent={true} / >Copy the code
If you’ve seen this, congratulations, student, you’ve mastered the adaptation of RN, you can handle more than 90% of the scenarios.
But there are also some weird scenarios and some apis that you may not understand, and this is in the remaining 10% of the adaptation scenarios or in them to help you understand and debug. That’s ok, I’ll go on. Some will involve source code, if you are interested, you can continue to follow me.
There are a lot of things below, but for me personally, this is the most important part I want to share with you.
Something weird and interesting
This section is very extensive, please read it as appropriate
1. Dimensions
API
Dimensions is an API provided by RN to get device size information. We can use it to get the width and height of the screen, which is the core API for adaptation. It provides two ways to get it:
const {windowWidth,windowHeight} = Dimensions.get('window');
const {screenWidth,screenHeight} = Dimensions.get('screen');
Copy the code
The official documentation does not specify what the difference is between the two methods of obtaining results. In actual development, the results obtained by these two methods are sometimes the same and sometimes different, which makes some students confused: which one should I use on earth is the right one? I recommend that you always use Dimensions. Get (‘window’). Only the results we get from it are the areas we can really manipulate to draw. First, clarify the meaning of the results obtained in these two ways:
Dimensions.get('window')
Get viewport parameters width, height, scale, fontScaleDimensions.get('screen')
Get screen parameters width, height, scale, fontScale
In the default case of the device screen, Screen always becomes greater than or equal to window, as the parameter window always excludes the status bar height (when false) and the bottom virtual menu bar height. 3. When this Android always sets the status bar to true and the virtual menu bar is not opened, dimensions.get (‘window’) is always the same as the width and height obtained by dimension.get (‘screen’), otherwise it is different. This is the answer to the sometimes identical and sometimes different question at the beginning of this paragraph.
This is not by guesswork or idle wind, direct source arrangement on:
Because the author’s equipment is limited, the source code of this article is only analyzed from the Android platform, and the source code of ios. Students with ios experience can refer to it according to their ideas. Preparation: Create a Demo RN project according to the official document. For stability, we use the previous RN version 0.62.0. NPX react-native init Demo –version 0.62.0
Step1. First find the js file for this API in RN. 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
*/
staticset(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); }}letinitialDims: ? $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;
Copy the code
This edition.js module initializes the Dimensions parameter information, which is retrieved by our edition.get () method. 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};Copy the code
The data source is DeviceInfo Module in the native module. Well, let’s go straight to the Android source code and see what it has to offer.
step2: Node_modules \react-native\android\com\ Facebook \react\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 for the com. Facebook. React. Modules, this module is to provide the vast majority of native to RN JSC API.
step4:Open thecom.facebook.react.modules.deviceinfo.DeviceInfoModule.java
:
See where the red box marks in the picture, which is in the js module above
initialDims = NativeDeviceInfo.getConstants().Dimensions;
Copy the code
The initial size information of the device comes from this source. Step5: open DisplayMetricsHolder. Java, find getDisplayMetricsMap () method:
How’s thatwindowPhysicalPixels
& screenPhysicalPixels
Does that sound familiar? And their property fieldswidth
,height
,scale
,fontScale
,densityDpi
Do you often use part of it? Yeah, you started itDimensions.js
Have seen them before:
Strictly speaking,Dimensions.js
Did I miss onedensityDpi
(Device pixel density) is not deconstructed ~ OK, let’s look at their original data source:
result.put("windowPhysicalPixels", getPhysicalPixelsMap(sWindowDisplayMetrics, fontScale));
result.put("screenPhysicalPixels", getPhysicalPixelsMap(sScreenDisplayMetrics, fontScale));
Copy the code
Respectively from: sWindowDisplayMetrics, sScreenDisplayMetrics. Where sWindowDisplayMetrics passes
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics);
Copy the code
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);
Copy the code
Settings. In Android, context.getResources().getDisplayMetrics(); Only drawable area size information is obtained, and the top status bar and the bottom virtual menu bar are removed by default. When setting screenDisplayMetrics, although versions are removed, the physical resolution of the entire screen is ultimately captured. So the beginning can be explained with real justification. The DimensionsAPI is completely covered from the js layer to the native layer.
The full-screen mask style does not cover the entire screen
The problem appears to be with some older Android phones, mid – to low-end models from around 2016 to 2018, mostly Honor models. These phones come with a virtual menu bar at the bottom and can be hidden automatically/manually when in use. Problem situation: When a custom Modal with a mask pops up, if the mask height is set to dimension.get (‘window’).height, after the bottom virtual menu bar is hidden, a section at the bottom will be left empty and cannot be masked by the mask. Cause: After hiding the menu bar, the height of the drawable area of the page has changed, and the current rendered view is the same as the one without the menu bar hidden last time. Solution: Listen for screen state changes, which is specifically pointed out on the website (www.react-native.cn/docs/dimens… Using Dimensions. The addEventListener () to monitor and set the height of mask, the key is to change the state, by state driving view update. There are, of course, remember to remove the event listeners: Dimensions. The removeEventListener ()
The 1 pixel border sometimes doesn’t show up
The 1-pixel border of RN is usually referred to as StyleSheet. HairlineWidth, which is a constant and will render to the thinnest standards of the current platform. However, when setting in the list sub-items, there will often be some list sub-items missing this line, and the weird thing is, the same line, some phones display normal, some phones do not display, and even some models on the line will be “fat”.
Node_modules \react-native\Libraries\StyleSheet\ stylesheet.js
let hairlineWidth: number = PixelRatio.roundToNearestPixel(0.4);
if (hairlineWidth === 0) {
hairlineWidth = 1 / PixelRatio.get();
}
Copy the code
Then find 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, Buta pile to * exactly (8.33 * 3) = 25 pixels. */
static roundToNearestPixel(layoutSize: number): number {
const ratio = PixelRatio.get();
return Math.round(layoutSize * ratio) / ratio;
}
Copy the code
The principle is to render a line of 0.4 logical pixels or so. The value is not necessarily 0.4, but the roundToNearestPixel is converted to a value that takes up the most integral number of physical pixels, which is related to the device DPR and also the scale property in Dimensions above. The worst case is 1 / PixelRatio. Get () when DPR is less than 1.25. According to the above calculation rules, no matter what, it should still be displayed. However, here we introduce two concepts — pixel mesh alignment and JavaScript number precision:
We can specify any precision we want when setting the logical pixels, but the device renders the physical pixels one by one, and the physical pixels are always whole. RN renders pixel mesh alignment to ensure correct display at arbitrary precision. JavaScript doesn’t really have integers. Its numeric type is based on IEEE 754 standard implementation, using 64-bit binary “double precision” format. There is a ** “machine accuracy” ** error between values, usually math.pow (2,-52).
With the concept out of the way, let’s look at examples:
Let’s say we have an Android with DPR=1.5, and we render two views at height = stylesheet. hairlineWidth up and down the page, according to the calculation rules above, At this point, height = StyleSheet. HairlineWidth ≈0.66666667, ideally occupying 1px physical pixels. But the truth may be:
Because of the accuracy of the JS numbers,Math.round(0.4 * 1.5) / 1.5
Take the1.5
Not necessarily equal1
It could be greater than 1, it could be less than 1, of course, it could be equal to 1.
Confused?
Let me show you a common test:
0.1+0.2 === 0.3 // false
How’s that? Is that clear? Ha ha.
The physical pixel is the whole, greater than 1, will occupy two physical pixels, less than 1 May occupy one or not occupied, is equal to 1, normal display. This is pixel grid alignment, which causes the StyleSheet. HairlineWidth Settings to display three things:
- Display thicker than expected;
- Display normal;
- Don’t show;
Solution: In most cases, StyleSheet. HairlineWidth actually behaves fine. If this is a problem, you can try using a value between 0.4 and 1 to set the size:
wrapper:{
height:8..backgroundColor:'# 333'
}
Copy the code
Then look at the render and choose the one that fits best.
conclusion
In this article, I first introduced RN adaptation scheme, and summed up an adaptation formula for you. If you understand this, you have a pretty good idea of RN adaptation; Then, from the perspective of source code, take you to trace back to the meaning of the adaptation of core API — Dimensions and its value of the source; Finally, the phenomenon or problem of “full-screen mask cannot cover the whole screen” and “sometimes 1-pixel border cannot be displayed” is explained. I hope you have learned something from this article! If you feel good, welcome to like and favorites and recommend to friends around, thank you for your encouragement and recognition! Any questions are also welcome to leave a message or private letter I am not easy to original, reproduced need to obtain my consent.
FQA
- Bangs screen, special-shaped screen how adaptation?
It is recommended to enable “Immersion” drawing. This function is enabled by default on ios and required on Android<StatusBar translucent={true} />
. Then set the height of the top status bar + title bar according to the bangs and irregular screen. - How to adapt large screen tablet computer such as iPad?
It depends on the actual business. If the demand only needs to be consistent with the mobile terminal, then you can directly use my scheme. If you also require landscape adaptation, then you need to use itDimensions.addEventListener()
Listen and set RN port parameters, calculate the ratio, listen to the value as the standard, and then adapt. - Why to say fit is maximum reduction design? In the section “1 pixel borders sometimes don’t show”, I mentioned pixel mesh alignment and JS numeric accuracy. When doing adapter, we finally set of values are calculated according to the proportion, the calculation results will have error precision, coupled with the pixel grid alignment, after apply colours to a drawing, there are some special circumstances, such as within a certain area for rendering a large number of small element nodes, the cumulative error can lead to a subtle difference and design precision.