Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of Android screen adaptation

2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the example analysis of Android screen adaptation, which has a certain reference value, and interested friends can refer to it. I hope you will gain a lot after reading this article.

Testing and thinking

I have to say that the ideas of the great gods of Jinri Toutiao are really very original, extremely low cost, but also very easy to use. The final plan they came up with was as follows:

Private static float sRoncompatDennsity; private static float sRoncompatScaledDensity; private void setCustomDensity (@ NonNull Activity activity, final @ NonNull Application application) {/ / application final DisplayMetrics appDisplayMetrics = application.getResources () .getDisplayMetrics (); if (sRoncompatDennsity = = 0) {sRoncompatDennsity = appDisplayMetrics.density; sRoncompatScaledDensity = appDisplayMetrics.scaledDensity Application.registerComponentCallbacks (new ComponentCallbacks () {@ Override public void onConfigurationChanged (Configuration newConfig) {if (newConfig! = null & & newConfig.fontScale > 0) {sRoncompatScaledDensity = application.getResources () .getDisplayMetrics () .scaledDensity } @ Override public void onLowMemory () {}});} / / the calculation width is 360dp and the height can be set to 640dp according to the actual situation final float targetDensity = appDisplayMetrics.widthPixels / 360; final float targetScaledDensity = targetDensity * (sRoncompatScaledDensity / sRoncompatDennsity); final int targetDensityDpi = (int) (targetDensity * 160) AppDisplayMetrics.density = targetDensity; appDisplayMetrics.densityDpi = targetDensityDpi; appDisplayMetrics.scaledDensity = targetScaledDensity; / / activity final DisplayMetrics activityDisplayMetrics = activity.getResources () .getDisplayMetrics (); activityDisplayMetrics.density = targetDensity; activityDisplayMetrics.densityDpi = targetDensityDpi; activityDisplayMetrics.scaledDensity = targetScaledDensity;}

After reading this article, I quickly wrote a demo test and found a small problem. The size of the design drawing given by our UI is 1334 to 720. If I take the width as the adaptation standard, according to the width of the design drawing 720px, the width of the screen should be 360dp, that is:

Final float targetDensity = appDisplayMetrics.widthPixels / 360

In this way, there is no question about the proportion of the width fit, but I wonder if it is OK to change it to this if it needs to be adapted at a height (that is, the content just fills the full screen longitudinally):

Final float targetDensity = appDisplayMetrics.heightPixels / 667

But after running, it is found that there is a great difference in height, running on mobile phones with different resolutions and sizes, the vertical proportion of each part of the page is different, and does not achieve a good adaptation effect. After thinking about it for a long time, I found a problem: the width of the test machine I have at hand is two 720s and two 1080, while the height is 1280, 1440, 1780 and 2160 of a full screen. The open nature of the Android leads to the fragmentation of the size of the Android device, and by looking at the size parameters of the phone, you will find that if you use these four phones to test, the width can be directly divisible, but the height can not (and the width of the test machine at hand can also be divisible, what if there is a phone whose width cannot be divisible? However, using the method given in Jinri Toutiao, the result will be rounded after division, could it be that the longitudinally calculated density rounding affects the accuracy, resulting in unsatisfactory results?

Problem repair

After discovering the above problems, I began to modify the calculation results and assigned them to targetDensity after taking the remainder of the calculation results. after repeated tests and experiments all afternoon, I revised the calculation method of targetDensity:

Float targetDensity = 0; try {Double division = Operation.division (appDisplayMetrics.heightPixels, 667); / / because the length and width of mobile phones are different, there must be cases of inaccuracy, so here we do an operation that preserves two decimal places: DecimalFormat df = new DecimalFormat ("0.00"); String s = df.format (division); targetDensity = Float.parseFloat (s) } catch (NumberFormatException e) {e.printStackTrace ();}

After testing, it is found that after taking two decimal places in this way, the adaptation result on the height is very satisfactory. However, there is another problem. Generally speaking, our adaptation is based on the width of the phone, but it is inevitable that one or two pages in an app are adapted according to height (that is, pages filled vertically with full screen content). However, the above method can only guarantee one direction, so I will allow it to switch freely to the reference direction of the adaptation.

Final plan

After continuing to modify, I got the final scheme, and everything in this class after modification is as follows:

Private static float appDensity; private static float appScaledDensity; private static DisplayMetrics appDisplayMetrics; / / this method calls Density.setDensity (this) in the onCreate method of Application; public static void setDensity (@ NonNull Application application) {/ / gets the DisplayMetrics appDisplayMetrics of application = application.getResources (). GetDisplayMetrics (); if (appDensity = = 0) {/ / assign a value on initialization (called only once in Application) appDensity = appDisplayMetrics.density AppScaledDensity = appDisplayMetrics.scaledDensity / / add listener application.registerComponentCallbacks for font change (new ComponentCallbacks () {@ Override public void onConfigurationChanged (Configuration newConfig) {/ / after font change, reassign appScaledDensity to if (newConfig! = null & & newConfig.fontScale > 0) {appScaledDensity = application.getResources () .getDisplayMetrics () .scaledDensity } @ Override public void onLowMemory () {}});} / / call the method to modify the density value (default is based on width) setAppOrientation (null, AppUtils.WIDTH) } / / this method is used to change the adaptation direction Density.setOrientation (mActivity, "width/height") in an Activity; public static void setOrientation (Activity activity, String orientation) {setAppOrientation (activity, orientation) } / * * targetDensity * targetScaledDensity * targetDensityDpi * these three parameters are uniformly modified values * * orientation: direction value, pass width or height * / private static void setAppOrientation (@ Nullable Activity activity, String orientation) {float targetDensity = 0; try {Double division / / choose different adaptation directions according to the input parameters: if (orientation.equals ("height")) {/ / appDisplayMetrics.heightPixels/667 division = Operation.division (appDisplayMetrics.heightPixels, 667);} else {division = Operation.division (appDisplayMetrics.widthPixels, 360) } / / because the length and width of mobile phones are different, there must be endless division and inaccuracy, so here we do an operation to preserve two decimal places DecimalFormat df = new DecimalFormat ("0.00"); String s = df.format (division); targetDensity = Float.parseFloat (s);} catch (NumberFormatException e) {e.printStackTrace () } float targetScaledDensity = targetDensity * (appScaledDensity / appDensity); int targetDensityDpi = (int) (160 * targetDensity) / * here assign the modified value to the system parameter * * (because at the beginning of initialization, activity is null, so just set the value of application. * so judge here, if there is an activity Then set the value of Activity) * / if (activity! = null) {DisplayMetrics activityDisplayMetrics = activity.getResources () .getDisplayMetrics () ActivityDisplayMetrics.density = targetDensity; activityDisplayMetrics.scaledDensity = targetScaledDensity; activityDisplayMetrics.densityDpi = targetDensityDpi;} else {appDisplayMetrics.density = targetDensity; appDisplayMetrics.scaledDensity = targetScaledDensity; appDisplayMetrics.densityDpi = targetDensityDpi;}}

This is all the content after the modification. If you don't understand, you can take a look at the comments inside, where I default to the width as the benchmark (this is the method set in Activity, and both fragment,dialog and PopupWindow under this Activity will be affected by this effect, that is to say, after setting it once in Activity, other sub-View under Activity do not need to be set again).

Usage

Create a class yourself, copy and paste the code in the final scheme and you can use it.

Usage: in the onCreate () method of Application

If you are only adapting to one direction, just set this sentence (I set the default adaptation to width in utils, and you can modify the default adaptation direction according to your own needs, as shown in the following figure)

If there is a page in app that needs to be adapted vertically:

Since it is a personal encapsulation, this method needs to be written in front of the setContentView () method in onCreate () before the effect of switching direction will take effect * / @ Override public void setOrientation () {Density.setOrientation (this, AppUtils.HEIGHT) } / * if you switch the adaptation direction in an Activity, you need to set the direction to the default direction in destroy, * because the switch direction changes the value of Activity, but application's will also be overwritten (the reason is not clear yet.) * reinitialize the direction during the onDestroy life cycle after weighing the pros and cons (because there are very few pages that use height as the adaptation benchmark *, so that the impact on program functionality can be reduced to a certain extent) * / @ Override protected void onDestroy () {super.onDestroy () Density.setOrientation (this, AppUtils.WIDTH);}

Because after switching directions in a certain Activity, I modified the value (activityDensity) in Activity, but after going back and clicking on other pages, I found that the adaptation direction of other pages had also been modified, so after weighing the pros and cons, I used this method with relatively minimal impact: in the onDetroy life cycle of the Activity that needs to modify the adaptation direction, change the direction to the default manually. After making trouble for a long time, I really can't think of a better way, if you have any other good way to leave a message for me.

* A vertical adaptation effect map is posted, and the TextView height of the blue background in the page is a fixed 150dp (it's just a simple page written by myself, don't be ugly.) :

Knock on the blackboard!

To write adaptation in this way, only one dimens file and one layout file are needed, and only dp is needed in the xml layout. (the bangs of Android P need to be adapted to layout separately, and the virtual buttons that can be hidden on full-screen phones also need to be adapted separately.) no, no, no.

Thank you for reading this article carefully. I hope the article "sample Analysis of Android screen adaptation" shared by the editor will be helpful to you. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report