Basic Screen Concepts
Hardware concept
Physical properties | ||
---|---|---|
The name of the | define | unit |
size | The length of the diagonal | Inch is about 2.54 centimeters |
The resolution of the | The number of pixels in the screen direction | A pixel, |
Pixel density | Number of pixels per inch | ppi,point per inch |
In daily life, we usually hear or use the screen size (XX mobile phone 6.5-inch blabla), which refers to the diagonal length of the mobile phone screen
The second is resolution, common are 1080P (1920×1080), 2K (2560×1440), 4K (4096 x 2160), where the number refers to the number of pixels in two directions of the screen (why not say vertical and horizontal two directions? Because you can see it portrait, you can see it landscape 🙂
Software concept
Software concept | |
---|---|
The name of the | define |
px | pixel |
dp | Dip, pixel density |
sp | Font unit, same as DP, but can be changed according to system Settings |
dpi | The number of pixels per unit inch, also called screen density |
density | Density qualifier that represents the density level of the current screen |
The relationship is as follows:
For example: the phone has a 1920×1080 resolution and a 5-inch screen
(1920^2 + 1080^2)^ 1/2) / 5 = 440
So dpi is 440
Other relationships are as follows:
Why does the screen not fit
Android screen coding, control width and height properties are usually used in dp units
Assuming that our UI design is designed with a screen width of 360DP, the screen width of dPI440 is actually 1080/(440/160)=392.7 DP, which means that the screen is wider than the design. In this case, even using DP will not display the same effect on different devices. At the same time, the screen width of some devices is less than 360DP, which will lead to the actual display of incomplete development based on 360DP width.
Moreover, the above relationship between screen size, resolution and pixel density is not realized by many devices according to this rule, so the VALUE of DPI is very disorderly and there is no rule to follow, resulting in unsatisfactory adaptation effect of DP.
However, screen adaptation is generally unified with the width or height of different models, because now mobile phones are uneven in the screen height, so the common screen adaptation scheme is for the width of adaptation.
Toutiao’s screen adaptation scheme
Toutiao technology team provides a relatively complete solution:
Because dp in Android turns DP to PX before rendering,
So start with the conversion formula dp and PX:
Density is derived from dPI
Px is the final display, dp is the unit we layout according to the design drawing, so we take Density and DPI to start
We can learn by reading the source code, and density were members of the DisplayMetrics variables, and DisplayMetrics instance through Resources. GetDisplayMetrics can get, Resouces are obtained from the Activity or Application Context.
Let’s get familiar with a few variables related to DisplayMetrics neutralization and adaptation:
DisplayMetrics.density
This is density aboveDisplayMetrics.densityDpi
That’s dPIDisplayMetrics.scaledDensity
The size factor of a typeface is normally the same as density, but adjusting the system font size will change this value
hands-on
Get the current DisplayMetrics
DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
Copy the code
Compute the target Denisty
// Density = px/DP
final float targetDensity = (float) (appDisplayMetrics.widthPixels / 360.0);
// Calculate the font size of the corresponding scale size. Generally, scaledDensity is the same as density to prevent users from adjusting the font size in system Settings
final float targetScaledDensity = targetDensity * (appDisplayMetrics.scaledDensity / appDisplayMetrics.density);
//dpi = density * 160
final int targetDensityDpi = (int)(targetDensity * 160);
Copy the code
Add Settings to make all
private static void setCustomDensity(Application application, Activity activity) {
final DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
// If DP = 360, the Density can be calculated
final float targetDensity = (float) (appDisplayMetrics.widthPixels / 360.0);
final float targetScaledDensity = targetDensity * (appDisplayMetrics.scaledDensity / appDisplayMetrics.density);
final int targetDensityDpi = (int)(targetDensity * 160);
// Set the application Density
appDisplayMetrics.density = targetDensity;
appDisplayMetrics.scaledDensity = targetScaledDensity;
appDisplayMetrics.densityDpi = targetDensityDpi;
// Set the Density of the activity
final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
activityDisplayMetrics.density = targetDensity;
activityDisplayMetrics.scaledDensity = targetScaledDensity;
activityDisplayMetrics.densityDpi = targetDensityDpi;
}
Copy the code
A common application scenario is to call setCustomDensity() in the onCreate method of BaseActivity to achieve global adaptation
At present, it seems that there is no problem, but there is another scenario: if the user modifies the font in the system setting example during the run and then returns the APP, the APP will not be aware of the font change, so the font does not change, so we should also monitor the font change and adjust ScaledDensity at the same time
Evolved into a polar body
private static float aNoncompatDensity;
private static float aNoncompatScaledDensity;
private static void setCustomDensity(Application application, Activity activity) {
final DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
if (aNoncompatDensity == 0) {
aNoncompatDensity = appDisplayMetrics.density;
aNoncompatScaledDensity = appDisplayMetrics.scaledDensity;
application.registerComponentCallbacks(new ComponentCallbacks() {
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
if (newConfig.fontScale > 0) { aNoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity; }}@Override
public void onLowMemory(a) {}}); }final float targetDensity = (float) (appDisplayMetrics.widthPixels / 360.0);
final float targetScaledDensity = targetDensity * (aNoncompatScaledDensity/ aNoncompatDensity);
final int targetDensityDpi = (int)(targetDensity * 160);
// Set the application Density
appDisplayMetrics.density = targetDensity;
appDisplayMetrics.scaledDensity = targetScaledDensity;
appDisplayMetrics.densityDpi = targetDensityDpi;
// Set the Density of the activity
final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
activityDisplayMetrics.density = targetDensity;
activityDisplayMetrics.scaledDensity = targetScaledDensity;
activityDisplayMetrics.densityDpi = targetDensityDpi;
}
Copy the code
Poor me, I do not have many devices to test the adaptation effect, so I quote the test screenshots of today’s technical team:
This adaptation method is very low invasion, the effect is stable, just dozens of lines of code can complete the adaptation problem, it is not too simple
The above article briefly explains the principle of adaptation, there are many open source projects based on this principle to adopt a more brief implementation, I will not expand on the next, you can explore what more convenient implementation scheme
Dig a hole and talk about several other screen adaptations and how they compare
Reference: Toutiao: A Very low-cost Way to adapt Android screens