Android屏幕適配的示例分析

這篇文章主要介紹了Android屏幕適配的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)公司是一家專業(yè)的成都網(wǎng)站建設(shè)公司,我們專注網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、網(wǎng)絡(luò)營銷、企業(yè)網(wǎng)站建設(shè),買鏈接1元廣告為企業(yè)客戶提供一站式建站解決方案,能帶給客戶新的互聯(lián)網(wǎng)理念。從網(wǎng)站結(jié)構(gòu)的規(guī)劃UI設(shè)計(jì)到用戶體驗(yàn)提高,創(chuàng)新互聯(lián)力求做到盡善盡美。

測(cè)試與思考

不得不說今日頭條的大神們的想法真的非常獨(dú)到,成本極其低廉,還特別好用。他們給出的最終方案是這樣的:

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() {              }         });     }      //計(jì)算寬為360dp 同理可以設(shè)置高為640dp的根據(jù)實(shí)際情況     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; }

看到這篇文章之后我趕緊就寫了一個(gè)demo測(cè)試了一下,發(fā)現(xiàn)了一點(diǎn)小問題。我們UI給出的設(shè)計(jì)圖尺寸為1334*720,如果我按照寬度作為適配標(biāo)準(zhǔn)的話,按照設(shè)計(jì)圖720px的寬度,屏幕的寬度應(yīng)為360dp,也就是這樣:

final float targetDensity = appDisplayMetrics.widthPixels / 360;

這樣做的話寬度適配的比例是沒有任何問的,但是我在想,如果需要以高度來做適配(也就是內(nèi)容剛好縱向填充全屏)的話,是不是改成這樣就可以了:

final float targetDensity = appDisplayMetrics.heightPixels / 667;

但是運(yùn)行之后發(fā)現(xiàn),高度上的差異很大,運(yùn)行在不同分辨率和尺寸的手機(jī)上,頁面中的每一部分內(nèi)容在縱向上的比例不盡相同,沒有達(dá)到很好的適配的效果。思考了許久過后我發(fā)現(xiàn)一個(gè)問題:我手邊的測(cè)試機(jī)的寬度是兩個(gè)720和兩個(gè)1080,而高度有1280,1440,1780和一個(gè)全面屏的2160。Android的開原性導(dǎo)致了Android設(shè)備的尺寸的碎片化太嚴(yán)重,而通過查看手機(jī)的尺寸參數(shù)會(huì)發(fā)現(xiàn),如果用這四個(gè)手機(jī)來測(cè)試的話,寬度可以直接整除,而高度不可以(并且我手邊的測(cè)試機(jī)的寬度也可以整除,如果有寬度沒法整除的手機(jī)呢?)。但是用今日頭條給出的方法,做除法后結(jié)果會(huì)取整,那會(huì)不會(huì)是由于用縱向計(jì)算出來的density取整影響了精度,從而導(dǎo)致了效果不盡人意呢?

問題修復(fù)

發(fā)現(xiàn)上述問題之后我就著手去修改,將計(jì)算結(jié)果取余后在賦值給targetDensity,經(jīng)過一下午的反復(fù)測(cè)試與實(shí)驗(yàn),我重新修改了targetDensity的計(jì)算方法:

float targetDensity = 0; try {     Double division = Operation.division(appDisplayMetrics.heightPixels, 667);     //由于手機(jī)的長寬不盡相同,肯定會(huì)有除不盡的情況,有失精度,所以在這里把所得結(jié)果做了一個(gè)保留兩位小數(shù)的操作     DecimalFormat df = new DecimalFormat("0.00");     String s = df.format(division);     targetDensity = Float.parseFloat(s); } catch (NumberFormatException e) {     e.printStackTrace(); }

經(jīng)測(cè)試后發(fā)現(xiàn),這樣取兩位小數(shù)計(jì)算過后,高度上的適配結(jié)果讓人非常滿意??墒沁€有一個(gè)問題,我們一般來說做適配都是以手機(jī)的寬度為基準(zhǔn),但是一個(gè)app里面避免不了偶爾一兩個(gè)頁面是按照高度為基準(zhǔn)(就是內(nèi)容縱向填充全屏的頁面)做適配的。但是上述方法只能保證一個(gè)方向,那我就讓它可以自由的切換適配的基準(zhǔn)方向不就好了。

最終方案

繼續(xù)修改之后我得到了最終的方案,修改過后這個(gè)類中的所有內(nèi)容如下:

private static float appDensity; private static float appScaledDensity; private static DisplayMetrics appDisplayMetrics;  //此方法在Application的onCreate方法中調(diào)用    Density.setDensity(this); public static void setDensity(@NonNull Application application) {     //獲取application的DisplayMetrics     appDisplayMetrics = application.getResources().getDisplayMetrics();      if (appDensity == 0) {         //初始化的時(shí)候賦值(只在Application里面初始化的時(shí)候會(huì)調(diào)用一次)         appDensity = appDisplayMetrics.density;         appScaledDensity = appDisplayMetrics.scaledDensity;          //添加字體變化的監(jiān)聽         application.registerComponentCallbacks(new ComponentCallbacks() {             @Override             public void onConfigurationChanged(Configuration newConfig) {                 //字體改變后,將appScaledDensity重新賦值                 if (newConfig != null && newConfig.fontScale > 0) {                     appScaledDensity = application.getResources().getDisplayMetrics().scaledDensity;                 }             }              @Override             public void onLowMemory() {             }         });     }          //調(diào)用修改density值的方法(默認(rèn)以寬度作為基準(zhǔn))     setAppOrientation(null, AppUtils.WIDTH); }  //此方法用于在某一個(gè)Activity里面更改適配的方向    Density.setOrientation(mActivity, "width/height"); public static void setOrientation(Activity activity, String orientation) {     setAppOrientation(activity, orientation); }  /**  * targetDensity  * targetScaledDensity  * targetDensityDpi  * 這三個(gè)參數(shù)是統(tǒng)一修改過后的值  *  * orientation:方向值,傳入width或height  */ private static void setAppOrientation(@Nullable Activity activity, String orientation) {      float targetDensity = 0;     try {         Double division;         //根據(jù)帶入?yún)?shù)選擇不同的適配方向         if (orientation.equals("height")) {             //appDisplayMetrics.heightPixels/667             division = Operation.division(appDisplayMetrics.heightPixels, 667);         } else {             division = Operation.division(appDisplayMetrics.widthPixels, 360);         }         //由于手機(jī)的長寬不盡相同,肯定會(huì)有除不盡的情況,有失精度,所以在這里把所得結(jié)果做了一個(gè)保留兩位小數(shù)的操作         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);      /**      *      * ***在這里將修改過后的值賦給系統(tǒng)參數(shù)      *      * (因?yàn)樽铋_始初始化的時(shí)候,activity為null,所以只設(shè)置application的值就可以了...      * 所以在這里判斷了一下,如果傳有activity的話,再設(shè)置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;     } }

這是修改之后的所有內(nèi)容,不懂的地方可以看一下里面的注釋,在里面我是默認(rèn)的以寬度來作為基準(zhǔn)(這是在Activity中設(shè)置的方法,存在于此Activity下的fragment,dialog和PopupWindow都會(huì)受到此效果的影響,也就是說,在Activity中設(shè)置一次之后,Activity下的其他子View都無需再設(shè)置一次)。

使用方法

自己創(chuàng)建一個(gè)類,將最終方案里面的代碼復(fù)制粘貼就可以使用了

使用方法:在Application的onCreate()方法中

Android屏幕適配的示例分析

如果只是適配一個(gè)方向的話,只設(shè)置這一句就可以了(我在utils里面設(shè)置了默認(rèn)按照寬度適配,可以根據(jù)自己的需求修改默認(rèn)的適配方向,見下圖)

Android屏幕適配的示例分析

若app中有某一個(gè)頁面需要縱向適配的話:

/**  *  * 由于是個(gè)人封裝,此方法需要寫在onCreate()中的setContentView()方法前面,切換方向的效果才會(huì)生效  */ @Override public void setOrientation() {     Density.setOrientation(this, AppUtils.HEIGHT); }  /**  *  * 如果在一個(gè)Activity里面切換了適配方向的話,需要在destroy里面將方向設(shè)置為默認(rèn)的方向,  * 因?yàn)榍袚Q方向修改的是Activity的值,但是application的也會(huì)覆蓋掉(原因還沒有搞清楚...),  * 權(quán)衡利弊之后就在onDestroy這個(gè)生命周期里面重新初始化了一下方向(因?yàn)橛酶叨茸鳛檫m配基準(zhǔn)的頁面  * 少之又少,這樣可以***程度的減少對(duì)程序功能性的影響)  */ @Override protected void onDestroy() {     super.onDestroy();     Density.setOrientation(this, AppUtils.WIDTH); }

由于在某一個(gè)Activity里面切換方向之后,我修改掉的是Activity中的值(activityDensity),但是返回再點(diǎn)擊其他頁面之后發(fā)現(xiàn)其他頁面的適配方向也被修改掉了,于是乎權(quán)衡利弊之后我就用了這個(gè)相對(duì)來說影響最小的辦法:在需要修改適配方向的Activity中的onDetroy生命周期里面,再手動(dòng)將方向改成默認(rèn)。。。(搗鼓了很久實(shí)在是想不到更好的辦法了,如果各位看官有其他的好辦法可以給我留言)。

Android屏幕適配的示例分析

***貼出縱向適配的效果圖,頁面中藍(lán)色背景的TextView高度是固定的150dp(只是我自己寫的一個(gè)很簡(jiǎn)單的頁面,不要嫌丑。。。):

Android屏幕適配的示例分析

敲黑板!!!

用此方法寫適配,只需要一個(gè)dimens文件,一個(gè)layout文件就足矣,在xml布局中直接只用dp就可以了(Android  P的劉海屏需要單獨(dú)適配layout,全面屏手機(jī)可以隱藏的虛擬按鍵似乎也需要單獨(dú)適配。。。)

Android屏幕適配的示例分析

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Android屏幕適配的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!

新聞名稱:Android屏幕適配的示例分析
分享路徑:http://muchs.cn/article30/jsojso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、品牌網(wǎng)站設(shè)計(jì)營銷型網(wǎng)站建設(shè)、網(wǎng)站策劃網(wǎng)頁設(shè)計(jì)公司、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營