preface
When it comes to Android screen adaptation, it is a commonplace topic, and the purpose of adaptation is nothing more than the UI performance of different devices should be proportional to the design drawing. In the actual adaptation process, in the face of different models, a variety of resolutions, have you adapted correctly? Do you apply OOM because the picture is not in the right position? This article introduces the width and height qualifiers and SW qualifiers of common screen adaptation schemes, with emphasis on SW qualifiers and image adaptation.
1. Screen adaptation solution
1. Width and height qualifier (resolution qualifier)
Take all the phone widths and heights in the market, generate res files such as values-1920 × 1080, Values-1280 × 720,values-1024 × 600, etc., write DIMens files using one of the resolutions (same as UI design) as a benchmark. Then, all other resolutions are calculated according to the benchmark resolution to generate dimens files with corresponding resolutions. When using, the corresponding DIMens values are directly used in XML according to the UI design drawing. Values under the corresponding DIMens will be used for different resolutions.
There are two big problems with this plan:
- Problem 1: Generating dimens files is troublesome, but it can be generated using tools, so it can be solved.
- For example, values-1920 × 1080 is configured. If the resolution of a weird phone is 1920 × 1070, the default DIMens will be used because there is no corresponding qualifier, and then the UI will be deformed. You need to generate dimens files for this weird resolution.
2. Sw qualifier
Also known as the minimum width qualifier, Android identifies the minimum dp of the available height and width of the screen (typically the dp of the phone width), then uses the corresponding resource file in the resource file based on the identified result, and if it does not find a corresponding resource file, it searches down, and finally uses the default. For example, if sw= 360DP, values-SW360DP will be preferred. If there is no values-360DP and only Values350DP, values350DP will be used. If there is no one smaller than 350DP and values350DP, the default configuration will be used (under values). This scheme is widely used because it is easier to hit a resource than the width and height qualifier, and even if there is no resource, close ones will be used. The UI effect is not much different, so this scheme is widely used.
2. Screen adaptation Directory meaning
By default, portrait screen will be introduced, if there is a difference between vertical screen adaptation will be specially explained
1. Layout fit (Layout directory)
Layout adaptation loads a specified layout based on one of the adaptation schemes
Layout Default directory layout-land Landscape layout-port Portrait Normally, the default directory is portrait. Add layout-land for landscape and vice versa
1.1 Width and height qualifiers
Before android3.0, name the layout folder as follows: layout-1024 × 768 layout-1024 × 600 layout-1280 × 768
After android3.0, subtract 48 pixels from the height of the bottom status bar: layout-976 × 768 layout-976 × 600 layout-1232 × 768
To distinguish between vertical and horizontal adaptation (android3.0 or later), add land or port to the directory name. Layout -land-1024 x 720 for vertical adaptation: layout-port-976 x 768 for vertical adaptation
1.2 SW qualifier
The name is layout-SW360DP layout-SW392DP layout-SW411DP
To differentiate between vertical and horizontal adaptation, add land or port to the directory name.
layout-sw360dp-land layout-sw360dp-port
1.3 W or H qualifier
In addition, there is a directory layout- w360DP, and layout- SW360DP difference, for example
1.3.1. The layout – sw360dp
When the absolute width of your screen is greater than 360DP, the screen will automatically call the layout in the folder layout-sw360DP.
Note: The absolute width here refers to the actual width of the phone, regardless of the horizontal or vertical screen. Sw minimum width refers to the small value of screen width and height. Each screen is fixed and does not change as the screen changes horizontally and vertically.
1.3.2. The layout – w360dp
When the relative width of your screen is greater than 360DP, the screen automatically calls the layout in the layout-w360DP folder.
Note: The relative width here refers to the relative width of the phone; That is, when the phone is portrait, the length of the smaller side; When the phone is landscape, it is the length of the longer side. When the screen is switched horizontally and vertically, the width of the screen is changed. Compare the changed width with the original width to see whether to use the resources under the resource file.
1.3.3. Layout – h360dp
The use of layout-W360DP is the same, but here refers to the relative height. This method is rarely used, however, because the screen can generally scroll vertically, resulting in varying lengths, rather than being as fixed as widths. Because this method is not very flexible, the Official Google documentation recommends using this method as little as possible.
Here, the DPI values of SW, W and H are calculated as follows
DisplayMetrics metrics = getResources().getDisplayMetrics();
int widthDpi = (int) (metrics.widthPixels / metrics.density);
int heightDpi = (int) (metrics.heightPixels / metrics.density);
Copy the code
Sw: Set widthDpi and heightDpi to smaller values w: widthDpi h: heightDpi
2. Dimen Adaptation (VALUES directory)
Values directory can put more resources, such as dimen, color,style, internationalization language. The values directory structure can be as complex as values-port-xhpdi-1280 × 768-4
The layout qualifier is described above. Normally, the length qualifier is used for multiple points, and the process is the same as above.
3. Sw Dimen adaptation process
Select one of the devices as the base fit, and then use the base device to generate the SW values of the other devices in proportion
Refer to the calculation formula:
px = density * dp;
density = dpi / 160;
px = dp * (dpi / 160);
Copy the code
The calculation formula of SW-XXXX-DP is as follows:
sw *160/dpi
Copy the code
Sw is the smaller side of the width and height
3.1. Dimen adaptation
- If the resolution of the benchmark device is 1080 × 1920, DPI =360, density=3 and picture directory xxhdPI are selected, thenvalues-sw360dp.
1dp=1dp
- It needs to be adapted to other devices (device 1 and 2), and the equal ratio treatment is as follows:
- Device 1: resolution 1080 × 1920, DPI =420, density= 2.625,values-sw411dp.
1 dp = 411/360 * 1 dp = 1.14 dp
- Device 2: resolution 1080 × 1920, DPI =360, density=2.25,values-sw480dp.
1 dp = 480/360 * 1 dp = 1.33 dp
- Device 3: resolution 720 × 1280, DPI =240, density=1.5,values-sw480dp.
1 dp = 480/360 * 1 dp = 1.33 dp
- Device 4: resolution 480 × 840, DPI =240, density=1.5,values-sw320dp.
1 dp = 320/360 * 1 dp = 0.88 dp
- Device 5: resolution 480 × 840, DPI =160, density=1,values-sw480dp.
1 dp = 480/360 * 1 dp = 1.33 dp
Note: Device parameters source simulator 3.
| | values directory dp value | — — — — — — — – | — — — — — — — — — — — — – | — — — — — — — — — — — — – | values (default directory and benchmark) 1 dp = 1 dp | | values – sw320dp dp | | 1 dp = 0.88 Benchmark values – sw360dp (sw) | 1 dp = 1 dp | values – sw411dp dp | | 1 dp = 1.14 values – sw480dp | 1 dp = 1.33 dp
- Then adjust the blue Lake resolution design width ** 360DP **
5. Select dp according to the number of DP marked in the design control.
6. Test verification: When you label the control as 250dp× 250DP, the width ratio is similar across different devices
- On the base device SW360DP, 250DP -> 250DP x 1DP = 250DP
- On the device SW320DP, 250DP -> 250DP × 0.88DP = 220DP
- On the SW411DP device, 250DP -> 250DP x 1.14DP = 285DP
- On sw480DP, 250DP -> 250DP x 1.33 DP =332.5 DP
The dp value of the device will eventually be converted to px value (according to the formulapx= dp * density
), so the final value of 250DP for the above reference device and the 5 devices is
- Values -SW360DP (density=3), 250DP * 3=750px, and width ratio: 750/1080=0.6944
- Device 1: Resolution 1080 × 1920, DPI =420, density= 2.625,values -SW411DP, 285DP * 2.625= 748.12px, and width ratio: 748.125/1080=0.6927
- Density =2.25 values sw480DP, 332.5DP *2.25= 748.12px, and width ratio: 748.125/1080=0.6927
- Dpi =240, density=1.5,values- SW480dp, 332.5dp*1.5=498.75px, and width ratio: 498.75px/720=0.6927
- Dpi =240, density=1.5,values- SW320DP, 220DP *1.5=330px, and width ratio: 330px/480=0.6875
- Dpi =160, density=1,values sw480DP, 332.5dp*1=332.5px, and width ratio: 332.5px/480=0.6927
It can be found from the above that the final ratio is about 0.6927, so the screen adaptation has completed equal scale scaling, and the error range is acceptable. If there is a big difference, it indicates that there is a problem with your adaptation. The difference between 0.6927 and 0.6875 above is because the decimal part is omitted when calculating SWDP. For example, device 1 was originally 411.4285714285714, and the value is 411DP. The values-SWDP whose value is less than or equal to 411.4285714285714 dp is matched by the system. The values-SWDP whose value is greater than 411.4285714285714 DP is not matched.
Add Sw code calculation method: Sw calculation method 1:
/** * get SmallestWidthDP *@param context
* @return* /
public static float getSmallestWidthDP(Context context) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
int heightPixels =getScreenHeight(context);
int widthPixels = getScreenWidth(context);
float density = dm.density;
float heightDP = heightPixels / density;
float widthDP = widthPixels / density;
float smallestWidthDP;
if (widthDP < heightDP) {
smallestWidthDP = widthDP;
} else {
smallestWidthDP = heightDP;
}
return smallestWidthDP;
}
/** * get the screen width **@param context Context
* @returnScreen width (px) */
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
wm.getDefaultDisplay().getRealSize(point);
} else {
wm.getDefaultDisplay().getSize(point);
}
return point.x;
}
/** * Get the screen height **@param context Context
* @returnScreen height (px) */
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
wm.getDefaultDisplay().getRealSize(point);
} else {
wm.getDefaultDisplay().getSize(point);
}
return point.y;
}
Copy the code
Sw Calculation Method 2:
int smallestWidthDP2 = (Math.min(heightPixels,widthPixels)) * 160 / dm.densityDpi;
Copy the code
Sw Calculation Method 3:
int smallestScreenWidthDp3 =context.getResources().getConfiguration().smallestScreenWidthDp;
Copy the code
Generate values-sw directories in batches
How to calculate the sw value is described above. In practice, there are two ways to generate the length of different SW values:
- Use ScreenMatch to batch generate values-sw directories
- Use the following utility classes:
package com.sjl.lib.screenadaptation;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** * sw Generate tool class **@author Kelly
* @version 1.0.0
* @filename MakeDpXml
* @timeBehold, 2020/11/30 *@copyright(C) 2020 song
*/
public class MakeDpXml {
/** * base value in dp */
private static int baseSw = 1080;
private static List<Integer> sw = Arrays.asList(360.392.411.1080.1440.2160);
private static int decimals = 4;
private static int scale = 1;
private static String filename = "dimens.xml";
public static void main(String[] args) {
// Customize parameters
baseSw = 1080;
decimals = 4;
scale = 1;
// Template file, file storage F:/layout, you can also define your own
filename = "dimens.xml";
create();
System.out.println("At the end of MakeDp");
}
public static void create(a) {
// The contents of dimens. XML file in this folder are the initial reference values
File file = new File("F:/layout",filename);
List<String> lines = new ArrayList<>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String tempString;
while((tempString = reader.readLine()) ! =null) { lines.add(tempString); }}catch (Exception e) {
e.printStackTrace();
} finally {
if(reader ! =null) {
try {
reader.close();
} catch (Exception ex) {
}
}
}
int lineSize = lines.size();
if (lineSize == 0) {
return;
}
Map<Integer, String> resultContent = new HashMap<>();
for (int j = 0; j < sw.size(); j++) {
Integer tempSw = sw.get(j);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < lineSize; i++) {
String xmlStrLine = lines.get(i);
if (xmlStrLine.contains("</dimen>")) {
String start = xmlStrLine.substring(0, xmlStrLine.indexOf(">") + 1);
String end = xmlStrLine.substring(xmlStrLine.lastIndexOf("<") - 2);
String text = xmlStrLine.substring(xmlStrLine.indexOf(">") + 1,
xmlStrLine.indexOf("</dimen>") - 2);
if (text.startsWith("@dimen")) {
sb.append(xmlStrLine).append("\r\n");
continue;
}
Float num = Float.parseFloat(text);
// Compute new values, concatenate new strings, and wrap new lines at the end according to different sizes.
float value = (float) tempSw / baseSw * num;
if(tempSw ! = baseSw){ value = value / scale; } sb.append(start).append(String.format("%."+decimals+"f", value)).append(end).append("\r\n");
} else {
sb.append(xmlStrLine).append("\r\n");
}
}
resultContent.put(tempSw, sb.toString());
}
// Write to the file
for (int i = 0; i < sw.size(); i++) {
Integer tempSw = sw.get(i);
String s = resultContent.get(tempSw);
File dir = new File("F:/layout/values-sw" + tempSw + "dp",filename);
if(! dir.getParentFile().exists()) { dir.getParentFile().mkdirs(); } MakeXmlUtils.writeFile(dir.getAbsolutePath(), s); }}}Copy the code
MakeXmlUtils:
/** * write file */
public static void writeFile(String file, String text) {
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
out.println(text);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(out ! =null) { out.close(); }}}Copy the code
3.2. Picture adaptation
If the control is a picture and the width and height of the control are specified according to the design drawing, how to choose which density of the picture?
Operation steps:
- Calculate device density DPI
DisplayMetrics dm = getResources().getDisplayMetrics();
int densityDpi = dm.densityDpi;
Copy the code
- Then refer to the figure below
directory | The density of the corresponding | Device density | Recommended size of LOGO | Density range |
---|---|---|---|---|
ldpi | 120dpi | 0.75 | 36 * 36 | 0-120. |
mdpi | 160dpi | 1 | 48 * 48 | 120dpi~160dpi |
hdpi | 240dpi | 1.5 | 72 * 72 | 160-240. |
xhdpi | 320dpi | 2 | 96 * 96 | 240-320. |
xxhdpi | 480dpi | 3 | 144 * 144 | 320-480. |
xxxhdpi | 640dpi | 4 | 192 * 192 | 480-640. |
-
According to the actual DPI of the device to choose pictures to download and store, generally choose a baseline density, such as 360Dpi, such as XXHDPI, and then run on different devices, control display length finally calculated width accounted for the same, the above has been explained.
-
However, when running to devices with different DPI, the memory occupied is not the same, has nothing to do with the control display size, do not attempt to modify the control display size to reduce the application memory. If and only when the device density range is 320DP to 480dpi, xxHDPI is the best match (the definition is the best, the memory occupation is appropriate). The memory of other device density images decreases or increases, and the images appear blurred to different degrees.
The diMEN adaption length is the same as the width ratio, but the memory occupied by the image is different. The memory occupied by the image is related to the image resolution, pixel storage format, the drawable folder where the image is located and the DEVICE DPI.
The memory footprint of pixels is affected by the storage mode of Bitmap colors:
- ARGB_8888: A->8bit-> one byte, R->8bit-> one byte, G->8bit-> one byte, B->8bit-> one byte, i.e. 8888, A pixel total of four bytes, 8+8+8+8=32bit=8byte
- ARGB_4444: A->4bit-> half A byte, R->4bit-> half A byte, G->4bit-> half A byte, B->4bit-> half A byte, that is, 4444, A pixel total of two bytes, 4+4+4+4=16bit=2byte
- RGB_565: R->5bit-> half a byte, G->6bit-> half a byte, B->5bit-> half a byte, i.e. 565, a pixel total of two bytes, 5+6+5=16bit=2byte ALPHA_8: R->5bit-> half a byte, G->6bit-> half a byte, B->5bit-> half a byte, i.e. A->8bit-> 1byte, i.e. 8, each pixel is A total of one byte, 8=8bit=1byte
Before giving examples, know the formula for calculating the actual width and height of an image
Width of the new figure = width of the original figure * (DPI of the device/dPI of the directory) Height of the new figure = Height of the original figure * (DPI of the device/DPI of the directory)Copy the code
Android :layout_width android:layout_height Android :layout_height
Image memory size = Width x height * memory bytes per pixelCopy the code
The actual width and height of the image are not directly calculated, strictly speaking, the actual size of the image in the form of bitmap in memory. So the above
Memory occupied by an image = Bitmap width xbitmap height x Memory bytes occupied by a pixel Bitmap width = Width of the original image x (DPI of the device/directory) Bitmap height = height of the original image x (DPI of the device/directory Dpi)Copy the code
or
Image memory size = original image width * (inTargetDensity/inDensity) * Original image height * (inTargetDensity/inDensity) * Number of bytes occupied by each pixelCopy the code
InDensity: indicates the DPI of the target image (under which resource folder), i.e., the dPI of the directory inTargetDensity: So you can see that inDensity and inTargetDensity stretch the width and height of the Bitmap to change how much memory the Bitmap occupies
For example:
Suppose the dPI of your device is 360DP, the density is 3, the corresponding image directory is XXhdPI, the resolution is 1080 × 1920, the SW is SW360, there is a picture with the width and height of 250px ×250px, suppose you put the wrong picture directory (not MDPI, normally put in xxhdPI directory), Images take up different amounts of memory.
- The picture in the wrong directory leads to the picture width and height change, which leads to the picture memory change analysis. Now let’s calculate the memory changes of images in different directories
Storage directory | Width calculation | Memory changes |
---|---|---|
ldpi | 360/120 * 250 | bigger |
mdpi | 360/160 * 250 | bigger |
xxdpi | 360/360 * 250 | normal |
xxdpi | 360/640 * 250 | smaller |
The same goes for height. As can be seen from the above,** The same picture on the same device occupies different memory in different picture directories **.
- Assuming your image is properly placed in xxHDPI, the memory changes when you run it on a different DPI device:
Calculation reference:
Width of new image = width of original image * (DPI of device/DPI of directory)Copy the code
- Device 1: Resolution 1080 × 1920, DPI =420, density= 2.625, VALUES – SW411DP, 420/360*250, increased
- Device 2: Resolution 1080 × 1920, DPI =360, DENSITY =2.25, VALUES – SW480DP, 360/360*250, normal
- Device 3: Resolution 720 × 1280, DPI =240, density=1.5, VALUES – SW480DP, 240/360*250, smaller
- Device 4: Resolution 480 × 840, DPI =240, density=1.5, VALUES -SW320DP, 240/360*250, smaller
- Device 5: Resolution 480 × 840, DPI =160, density=1, VALUES sw480DP, 160/360*250, smaller
As can be seen from the above, ** The same picture on different devices is in the same directory, and the dPI of different devices occupies different memory **.
In short, usually we are a set of image adaptation, but if a set of image adaptation, there are slight differences, need to be adapted separately for different devices DPI. Note that the image directory storage location should not be too different, otherwise it is prone to OOM, blurred pictures and other problems.
4. Example of sw adaptation benchmark device
The following data is the SW value of each device. You can select one device as the reference value for adaptation, and then use the reference device to generate the SW value of other devices. The adaptation process is the same as the preceding SW DImen adaptation process terminal device example:
size | The screen | The resolution of the | The density of | Relationship between dp and PX | sw | Blue Lake preview resolution custom |
---|---|---|---|---|---|---|
8 | Vertical screen | 800 × 1280 | 1 | mdpi | 1:1 | sw800 |
10.1 | landscape | 1280 × 800 | 1 | mdpi | 1:1 | sw800 |
55 | Vertical screen | 1080 × 1920 | 1 | mdpi | 1:1 | sw1080 |
21 | Vertical screen | 1080 x 1920 | 1 | mdpi | 1:1 | sw1080 |
17 | landscape | 1280 × 1024 | 1 | mdpi | 1:1 | sw1024 |
Mobile phone:
size | The screen | The resolution of the | The density of | Relationship between dp and PX | sw | Blue Lake preview resolution custom | describe |
---|---|---|---|---|---|---|---|
5.2 | Vertical screen | 800 × 1280 | 3 | xxhdpi | 1:3 | sw360 | 360 * 640 |
6.4 | Vertical screen | 2340 × 1080 | 3 | xxhdpi | 1:3 | sw360 | 360 * 780 |
Screen direction judgment:
If (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
/ / vertical screen
System.out.println("Portrait");
} else {
/ / landscape
System.out.println("Landscape");
}
Copy the code
5. Get dimen from code
There are three main ways to reference dimen. XML dp values in Java or Kotlin code:
getDimension
Returns a float valuegetDimensionPixelOffset
Strongly converting float to an int is returnedgetDimensionPixelSize
Returns a float value rounded to an int value
The value returned by the above three methods is based on the length unit of the SW XML file:
- When the given value is px, the given value is returned directly
- When the given value is dp, multiply the screen density and return
- When the given value is sp, the scaling factor is multiplied and returned
If you use the dp value as a font size, you need to pay attention to magnification.
XML set font 20dp
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="@dimen/dp_20"
/>
Copy the code
Set 20DP in Java code
float size = context.getResources().getDimension(R.dimen.dp_20);
TextView textView = new TextView(context);
textView.setTextSize(size);
Copy the code
The font result value above will be larger than the XML value (device density is not 160dpi, i.e. 1px does not equal 1DP), resulting in an unsatisfactory display. The reason is that as stated above, when the given value is dp, the screen density is multiplied and returned
To be compatible with other devices, the correct dp value is as follows:
float size = context.getResources().getDimension(R.dimen.dp_20)/ context.getResources().getDisplayMetrics().density;
TextView textView = new TextView(context);
textView.setTextSize(size);
Copy the code
This setting is the correct value, display as expected.
6. Expansion (Toutiao adaptation)
Toutiao adaptation scheme achieves adaptation purpose by modifying system density. In Android, no matter what unit is used, the system will eventually convert the size to PX, and
px = dp * density
Copy the code
The density used by the system is a member variable in DisplayMetrics, and the DisplayMetrics instance is available via Resources#getDisplayMetrics, Resouces are obtained from the Activity or Application Context. In other words, all dp and PX conversions are calculated by the relevant values in DisplayMetrics. Therefore, dp adaptation can be completed only by modifying the density value in DisplayMetrics. Sp ADAPTS similarly, but with a scaling factor that allows users to change font sizes
public class ScreenAdpt {
/** the width of the design is dp */
private static final float width = 360;
private static float textDensity = 0;
private static float textScaledDensity = 0;
/ * * *@param activity
*/
public static void setCustomDensity(@NonNull final Activity activity) {
final Application application = activity.getApplication();
final DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();
if (textDensity == 0) {
textDensity = displayMetrics.density;
textScaledDensity = displayMetrics.scaledDensity;
application.registerComponentCallbacks(new ComponentCallbacks() {
@Override
public void onConfigurationChanged(Configuration configuration) {
if(configuration ! =null && configuration.fontScale > 0) { textScaledDensity = application.getResources().getDisplayMetrics().scaledDensity; }}@Override
public void onLowMemory(a) {}}); }final float targetDensity = displayMetrics.widthPixels / width;
final float targetScaledDensity = targetDensity * (textScaledDensity / textDensity);
final int targetDpi = (int) (160 * targetDensity);
displayMetrics.density = targetDensity;
displayMetrics.scaledDensity = targetScaledDensity;
displayMetrics.densityDpi = targetDpi;
finalDisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics(); activityDisplayMetrics.density = targetDensity; activityDisplayMetrics.scaledDensity = targetScaledDensity; activityDisplayMetrics.densityDpi = targetDpi; }}Copy the code
7. Summary
In summary, the smallestWidth qualifier screen ADAPTS scenarios in which the ratio of View to screen width on different devices is the same as in the design drawing. The adaptation needs to be noted is to choose one of the devices as the reference, and then use the reference device (minimum width reference value) to generate the SW value of other devices in equal proportion, otherwise it is easy to cause problems, UI designers generally do not have this awareness, most of the map based on a certain resolution, when you choose the SW qualifier adaptation, Most need to customize the resolution preview (blue Lake, Mouk, etc.), otherwise it is easy to choose the wrong length and image size, leading to a series of problems. Please correct any mistakes above.