国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Android屏幕適配方案

Sourcelink / 3038人閱讀

摘要:下圖為圖標(biāo)的各個(gè)屏幕密度的對(duì)應(yīng)尺寸屏幕密度圖標(biāo)尺寸解析解析獲取屏幕分辨率信息的三種方法第一種第二種第三種屏幕適配出現(xiàn)的原因什么是像素點(diǎn)屏幕分辨率是指在橫縱向上的像素點(diǎn)數(shù),單位是,個(gè)像素點(diǎn)。

目錄介紹

1.屏幕適配定義

2.相關(guān)重要的概念

2.1 屏幕尺寸[物理尺寸]

2.2 屏幕分辨率[px]

2.3 屏幕像素密度[dpi]

2.4 dp、dip、dpi、sp、px

2.5 mdpi、hdpi、xdpi、xxdpi

2.6 獲取屏幕分辨率[寬高]

3.Android屏幕適配出現(xiàn)的原因

3.1 什么是像素點(diǎn)

3.2 dp與百分比

4.Android適配問(wèn)題及本質(zhì)

4.1 尺寸適配

4.2 代碼適配

4.3 布局適配

4.4 權(quán)重適配

4.5 圖片適配

4.6 百分比適配

5.存在問(wèn)題和困境

5.1 通配符適配困境

5.2 傳統(tǒng)dp適配困境

6.常用解決方案

6.1 今日頭條適配方案

6.2 鴻洋大神庫(kù)

6.3 AndroidAutoSize

1.屏幕適配定義

使得某一元素在Android不同尺寸、不同分辨率的手機(jī)上具備相同的顯示效果

2.相關(guān)重要的概念 2.1 屏幕尺寸[物理尺寸]

含義:手機(jī)對(duì)角線的物理尺寸

單位:英寸(inch),1英寸=2.54cm

Android手機(jī)常見(jiàn)的尺寸有5寸、5.5寸、6寸等等

2.2 屏幕分辨率[px]

含義:手機(jī)在橫向、縱向上的像素點(diǎn)數(shù)總和

一般描述成屏幕的"寬x高”=AxB

含義:屏幕在橫向方向(寬度)上有A個(gè)像素點(diǎn),在縱向方向 (高)有B個(gè)像素點(diǎn)

例子:1080x1920,即寬度方向上有1080個(gè)像素點(diǎn),在高度方向上有1920個(gè)像素點(diǎn)

單位:px(pixel),1px=1像素點(diǎn)

Android手機(jī)常見(jiàn)的分辨率:720x1280、1080x1920等等

2.3 屏幕像素密度[dpi]

含義:每英寸的像素點(diǎn)數(shù)

單位:dpi(dots per ich)

假設(shè)設(shè)備內(nèi)每英寸有160個(gè)像素,那么該設(shè)備的屏幕像素密度=160dpi

屏幕像素密度與屏幕尺寸和屏幕分辨率有關(guān),在單一變化條件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。

dpi計(jì)算公式:舉個(gè)例子:屏幕分辨率為:1920*1080,屏幕尺寸為5吋的話,那么dpi為440

注意:dpi是根據(jù)屏幕真實(shí)的分辨率和尺寸來(lái)計(jì)算的,每個(gè)設(shè)備都可能不一樣的

2.4 dp[dip]、dpi、sp、px

dp(dip):px = dp * 密度比,都是Density Independent Pixels的縮寫(xiě),即密度無(wú)關(guān)像素

dpi:開(kāi)方(寬度平方 + 高度平方) / 手機(jī)的尺寸;dpi是屏幕像素密度,假如一英寸里面有160個(gè)像素,這個(gè)屏幕的像素密度就是160dpi

sp: 可以根據(jù)文字大小首選項(xiàng)進(jìn)行放縮,是設(shè)置字體大小的御用單位。

px: 像素,px是比較熟悉,前面的分辨率就是用的像素為單位,大多數(shù)情況下,比如UI設(shè)計(jì)、Android原生API都會(huì)以px作為統(tǒng)一的計(jì)量單位,像素是獲取屏幕寬高等。

問(wèn)題: dp和px如何換算呢?

px = density * dp;
density = dpi / 160;
px = dp * (dpi / 160);
2.5 mdpi、hdpi、xdpi、xxdpi

2.5.1 作用: mdpi、hdpi、xdpi、xxdpi用來(lái)修飾Android中的drawable文件夾及values文件夾,用來(lái)區(qū)分不同像素密度下的圖片和dimen值。

名稱像                     素密度范圍
ldpi                      0dpi~120dpi
mdpi                      120dpi~160dpi
hdpi                      120dpi~160dpi
xdpi                      160dpi~240dpi
xxdpi                     240dpi~320dpi
xxxdpi                    480dpi~640dpi

Android項(xiàng)目后應(yīng)該可以看到很多drawable文件夾,分別對(duì)應(yīng)不同的dpi
drawable-ldpi (dpi=120, density=0.75)
drawable-mdpi (dpi=160, density=1)
drawable-hdpi (dpi=240, density=1.5)
drawable-xhdpi (dpi=320, density=2)
drawable-xxhdpi (dpi=480, density=3)
對(duì)于五種主流的像素密度(MDPI、HDPI、XHDPI、XXHDPI 和 XXXHDPI)應(yīng)按照 2:3:4:6:8 的比例進(jìn)行縮放。

2.5.2 在進(jìn)行開(kāi)發(fā)的時(shí)候,我們需要把合適大小的圖片放在合適的文件夾里面。下面以圖標(biāo)設(shè)計(jì)為例進(jìn)行介紹

2.5.3 在設(shè)計(jì)圖標(biāo)時(shí),對(duì)于五種主流的像素密度(MDPI、HDPI、XHDPI、XXHDPI 和 XXXHDPI)應(yīng)按照 2:3:4:6:8 的比例進(jìn)行縮放。

例如,一個(gè)啟動(dòng)圖標(biāo)的尺寸為48x48 dp,這表示在 MDPI 的屏幕上其實(shí)際尺寸應(yīng)為 48x48 px,在 HDPI 的屏幕上其實(shí)際大小是 MDPI 的 1.5 倍 (72x72 px),在 XDPI 的屏幕上其實(shí)際大小是 MDPI 的 2 倍 (96x96 px),依此類推。

2.5.4 下圖為圖標(biāo)的各個(gè)屏幕密度的對(duì)應(yīng)尺寸:

屏幕密度                 圖標(biāo)尺寸
mdpi                     48X48px
hdpi                     72X72px
xdpi                     96X96px
xxdpi                    144X144px
xxxdpi                   192X192px
2.6 DisplayMetrics解析

DisplayMetrics解析

獲取屏幕分辨率信息的三種方法:

//第一種
DisplayMetrics metrics = new DisplayMetrics();
Display display = activity.getWindowManager().getDefaultDisplay();
display.getMetrics(metrics);

//第二種
DisplayMetrics metrics= activity.getResources().getDisplayMetrics();

//第三種
Resources.getSystem().getDisplayMetrics();
3.Android屏幕適配出現(xiàn)的原因 3.1 什么是像素點(diǎn)

屏幕分辨率是指在橫縱向上的像素點(diǎn)數(shù),單位是px,1px=1個(gè)像素點(diǎn)。

一般以縱向像素橫向像素,如19601080。 由于Android系統(tǒng)的開(kāi)放性,任何用戶、開(kāi)發(fā)者、OEM廠商、運(yùn)營(yíng)商都可以對(duì)Android進(jìn)行定制,修改成他們想要的樣子。 屏幕尺寸這么多,為了讓我們開(kāi)發(fā)的程序能夠比較美觀的顯示在不同尺寸、分辨率、像素密度(這些概念我會(huì)在下面詳細(xì)講解)的設(shè)備上,那就要在開(kāi)發(fā)的過(guò)程中進(jìn)行處理,至于如何去進(jìn)行處理,這就是我們今天的主題。

3.2 dp與百分比 (網(wǎng)頁(yè)前端提供百分比,所以無(wú)需適配)

只要記住一點(diǎn)dp是與像素?zé)o關(guān)的,在實(shí)際使用中1dp大約等于1/160inch

那么dp究竟解決了適配上的什么問(wèn)題?可以看出1dp = 1/160inch;那么它至少能解決一個(gè)問(wèn)題,就是你在布局文件寫(xiě)某個(gè)View的寬和高為160dp160dp,這個(gè)View在任何分辨率的屏幕中,顯示的尺寸大小是大約是一致的(可能不精確),大概是 1 inch 1 inch。

1.呈現(xiàn)效果仍舊會(huì)有差異,僅僅是相近而已

當(dāng)設(shè)備的物理尺寸存在差異的時(shí)候,dp就顯得無(wú)能為力了。為4.3寸屏幕準(zhǔn)備的UI,運(yùn)行在5.0寸的屏幕上,很可能在右側(cè)和下側(cè)存在大量的空白。而5.0寸的UI運(yùn)行到4.3寸的設(shè)備上,很可能顯示不下。

一句話,總結(jié)下,dp能夠讓同一數(shù)值在不同的分辨率展示出大致相同的尺寸大小。但是當(dāng)設(shè)備的尺寸差異較大的時(shí)候,就無(wú)能為力了。

4.Android屏幕適配常見(jiàn)方法 4.1 適配常見(jiàn)方法

尺寸適配

dimen適配

布局適配

代碼適配

圖片適配

4.2 尺寸適配 4.2.1 布局文件設(shè)置寬高

寬高設(shè)置參數(shù):有的時(shí)候用dp,有的時(shí)候用px,大多數(shù)用dp

dp:dp(dip):px = dp * 密度比,與屏幕像素有對(duì)應(yīng)關(guān)系,設(shè)置成dp后,在不同分辨率的手機(jī)上有可能尺寸會(huì)不一樣

px:像素,比如小分辨率手機(jī)上一像素和大分辨率手機(jī)上一像素,所顯示的圖像是不一樣的
理解dp和px之間對(duì)應(yīng)的關(guān)系,不同分辨率的手機(jī)用不同的dp值來(lái)適配

4.2.2 密度比

密度比是固定的,可以查詢文檔Develop—>API Guides—>Best Practices—>Supporting Multiple

mdpi手機(jī):160dpi 是基準(zhǔn)線,1px = 1dp * 1,其他手機(jī)的密度比 = 自己的dpi/160

代碼獲取密度比:getResources().getDisplayMetrics().density

ldip:120px = 160dp * 0.75
mdpi:160px = 160dp * 1
hdpi:240px = 160dp * 1.5
xhdpi:360px = 180dp * 2

4.2.3 dimen適配

1.在默認(rèn)的values中的dimens文件下聲明(類似于Strings.xml)

    16dp
    16dp
    160dp



    
    120dip     



    
    220dip     





    
    80dip     

2.在布局文件中引用

3.新建需要適配的values-XXX(比如values-1280x720,注意規(guī)范大值在前)

4.在新建values-1280x720中的dimens.xml文件中

* 180dp

5.所有手機(jī)適配找對(duì)應(yīng)的默認(rèn)的dimens

    * 思考:如何計(jì)算dpi?如何計(jì)算手機(jī)密度比?能夠用dp適配所有手機(jī)嗎?
    * dp不能適配所有手機(jī);
    * 舉個(gè)例子:按鈕占屏幕寬度一半,把寬度設(shè)置成160dp,120px和160px和240px可以占屏幕一半,但是360px則小于屏幕一半;
    * 如果把寬度設(shè)置成180dp,那么360dp可以占屏幕一半,但其他幾個(gè)又不行。
    * 如果要適配所有手機(jī)的控件寬度為屏幕寬度的一半,該怎么做呢?用dimen
4.2 代碼適配 4.3 布局適配,有可能在不同的手機(jī)布局中,控件排列的位置不一樣

1.位置不一樣

不同的手機(jī)在運(yùn)行的時(shí)候選擇不同的布局(布局名稱一樣,類似于dimens),比如:

2.控件不一樣

不能用布局適配了;為什么?

布局能夠?qū)崿F(xiàn)界面效果,但是完成布局后在代碼中,由于控件都不一樣,所以會(huì)找這兩套布局的id,還要做判斷,根據(jù)不同的布局做兩套代碼(如果頁(yè)面復(fù)雜,給控件設(shè)置參數(shù)等十分繁瑣)

3.適用場(chǎng)景

不同的手機(jī)的控件的位置不一樣,發(fā)生了位置變化才會(huì)用到布局適配,實(shí)際開(kāi)發(fā)中用的很少

4.4 權(quán)重適配 4.5 圖片適配

1.圖片的查找順序

注意:一般手機(jī) ldpi

注意:mdpi手機(jī) ldpi

適配主流手機(jī),1920 1080 1080 720 800 * 480,高清圖、背景圖(全屏展示)準(zhǔn)備多套 。小圖片 準(zhǔn)備一套高分辨率的;比如按鈕,圖標(biāo)等

為了是apk瘦身,有些圖片不要準(zhǔn)備多套,Android分辨率種類太多了;即使適配主流手機(jī),展示比較清楚的背景圖(比如:歡迎界面),可以準(zhǔn)備多套

2.在小分辨率展示高清圖,放到大分辨率會(huì)出現(xiàn)什么情況呢?

比如:你針對(duì)800480分辨率手機(jī)做了背景圖圖片,正好完全展示;如果把它放到大分辨率1280720上,會(huì)對(duì)圖片進(jìn)行拉伸,會(huì)使像素點(diǎn)變大,可能會(huì)看到鋸齒或者模糊的東西

5.存在問(wèn)題和困境 5.1 通配符適配困境 5.2 傳統(tǒng)dp適配困境

[摘自頭條]一般我們?cè)O(shè)計(jì)圖都是以固定的尺寸來(lái)設(shè)計(jì)的。比如以分辨率750px 1334px來(lái)設(shè)計(jì),以density為3來(lái)標(biāo)注,也就是屏幕其實(shí)是350dp 667dp。如果想在所有設(shè)備上顯示完全一致,其實(shí)是不現(xiàn)實(shí)的,因?yàn)槠聊桓邔挶炔皇枪潭ǖ模鞣N寬高比層出不窮,寬高比不同,顯示完全一致就不可能了。但是通常下,我們只需要以寬或高一個(gè)維度去適配,比如我們Feed是上下滑動(dòng)的,只需要保證在所有設(shè)備中寬的維度上顯示一致即可,再比如一個(gè)不支持上下滑動(dòng)的頁(yè)面,那么需要保證在高這個(gè)維度上都顯示一致,尤其不能存在某些設(shè)備上顯示不全的情況。同時(shí)考慮到現(xiàn)在基本都是以dp為單位去做的適配,如果新的方案不支持dp,那么遷移成本也非常高。

因此,總結(jié)下大致需求如下:

支持以寬或者高一個(gè)維度去適配,保持該維度上和設(shè)計(jì)圖一致;注意是某一個(gè)維度

支持dp和sp單位,控制遷移成本到最小。

6.常用適配框架 6.1 今日頭條適配方案 6.1.1 兼容突破口

從dp和px的轉(zhuǎn)換公式 :px = dp * density

可以看出,如果設(shè)計(jì)圖寬為360dp,想要保證在所有設(shè)備計(jì)算得出的px值都正好是屏幕寬度的話,我們只能修改 density 的值。

//在xml中使用何種尺寸單位(dp、sp、pt、in、mm),最后在繪制時(shí)都會(huì)給我們轉(zhuǎn)成px!
public static float applyDimension(int unit, float value, DisplayMetrics metrics) {
    switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
    return 0;
}
6.1.2 頭條適配方案核心代碼
public static void setCustomDensity(Activity activity, Application application) {
    DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();
    if (sNoncompatDensity == 0) {
        // 系統(tǒng)的Density
        sNoncompatDensity = displayMetrics.density;
        // 系統(tǒng)的ScaledDensity
        sNoncompatScaledDensity = displayMetrics.scaledDensity;
        // 監(jiān)聽(tīng)在系統(tǒng)設(shè)置中切換字體
        application.registerComponentCallbacks(new ComponentCallbacks() {
            @Override
            public void onConfigurationChanged(Configuration newConfig) {
                if (newConfig != null && newConfig.fontScale > 0) {
                    sNoncompatScaledDensity=application.getResources().getDisplayMetrics().scaledDensity;
                }
            }

            @Override
            public void onLowMemory() {

            }
        });
    }
    // 公司UI尺寸是750px-1334px,此處以375dp的設(shè)計(jì)圖作為例子
    float targetDensity=displayMetrics.widthPixels/375;
    float targetScaledDensity=targetDensity*(sNoncompatScaledDensity/sNoncompatDensity);
    int targetDensityDpi= (int) (160 * targetDensity);
    displayMetrics.density = targetDensity;
    displayMetrics.scaledDensity = targetScaledDensity;
    displayMetrics.densityDpi = targetDensityDpi;

    DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
    activityDisplayMetrics.density = targetDensity;
    activityDisplayMetrics.scaledDensity = targetScaledDensity;
    activityDisplayMetrics.densityDpi = targetDensityDpi;
}
6.1.3 頭條適配方案注意事項(xiàng)

寬度適配就已經(jīng)完成啦,只需要在Activity中調(diào)用就行了,必須在setContentView()之前!

如果需要適配高度,頭條指出只要按照同樣的方法做高度適配就可以了!

實(shí)現(xiàn)思路:假設(shè)設(shè)計(jì)圖寬度是360dp,以寬維度來(lái)適配,那么適配后的 density = 設(shè)備真實(shí)寬(單位px) / 360,接下來(lái)只需要把我們計(jì)算好的 density 在系統(tǒng)中修改下即可

遇到的問(wèn)題:

1.如果某個(gè)頁(yè)面不想適配該方案,該如何處理

2.滾動(dòng)頁(yè)面以寬為維度適配,而某些頁(yè)面則是以高為維度適配,這種情況怎么辦?

3.針對(duì)第三方庫(kù)有何更好的方案,比如支付寶支付彈窗,或者第三方客服聊天頁(yè)面如何處理適配

6.1.4 頭條適配工具類,暫時(shí)只是用作測(cè)試項(xiàng)目

關(guān)于該工具類,已經(jīng)用于測(cè)試項(xiàng)目中,逐步完善,項(xiàng)目可以參考:https://github.com/yangchong2...

public class ScreenDensityUtils {


    /*
     * 1.先在application中使用setup()方法初始化一下
     * 2.手動(dòng)在Activity中調(diào)用match()方法做適配,必須在setContentView()之前
     * 3.建議使用dp做寬度適配,大多數(shù)時(shí)候?qū)挾冗m配才是主流需要
     * 4.個(gè)人覺(jué)得在寫(xiě)布局的時(shí)候,可以多用dp,如果是使用px,建議轉(zhuǎn)化成dp
     * 5.入侵性很低,不需要改動(dòng)原來(lái)的代碼
     */


    /**
     * 屏幕適配的基準(zhǔn)
     */
    private static final int MATCH_BASE_WIDTH = 0;
    private static final int MATCH_BASE_HEIGHT = 1;
    /**
     * 適配單位
     */
    private static final int MATCH_UNIT_DP = 0;
    private static final int MATCH_UNIT_PT = 1;

    // 適配信息
    private static MatchInfo sMatchInfo;
    // Activity 的生命周期監(jiān)測(cè)
    private static Application.ActivityLifecycleCallbacks mActivityLifecycleCallback;

    private ScreenDensityUtils() {
        throw new UnsupportedOperationException("u can"t instantiate me...");
    }

    /**
     * 初始化
     * @param application                   需要在application中初始化
     */
    public static void setup(@NonNull final Application application) {

        /*
        //獲取屏幕分辨率信息的三種方法
        //第一種
        DisplayMetrics metrics = new DisplayMetrics();
        Display display = activity.getWindowManager().getDefaultDisplay();
        display.getMetrics(metrics);
        //第二種
        DisplayMetrics metrics= activity.getResources().getDisplayMetrics();
        //第三種
        Resources.getSystem().getDisplayMetrics();
        */

        //注意這個(gè)是獲取系統(tǒng)的displayMetrics
        final DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();
        if (sMatchInfo == null) {
            // 記錄系統(tǒng)的原始值
            sMatchInfo = new MatchInfo();
            sMatchInfo.setScreenWidth(displayMetrics.widthPixels);
            sMatchInfo.setScreenHeight(displayMetrics.heightPixels);
            sMatchInfo.setAppDensity(displayMetrics.density);
            sMatchInfo.setAppDensityDpi(displayMetrics.densityDpi);
            sMatchInfo.setAppScaledDensity(displayMetrics.scaledDensity);
            sMatchInfo.setAppXdpi(displayMetrics.xdpi);
        }
        // 添加字體變化的監(jiān)聽(tīng)
        // 調(diào)用 Application#registerComponentCallbacks 注冊(cè)下 onConfigurationChanged 監(jiān)聽(tīng)即可。
        application.registerComponentCallbacks(new ComponentCallbacks() {
            @Override
            public void onConfigurationChanged(Configuration newConfig) {
                // 字體改變后,將 appScaledDensity 重新賦值
                if (newConfig != null && newConfig.fontScale > 0) {
                    float scaledDensity = displayMetrics.scaledDensity;
                    sMatchInfo.setAppScaledDensity(scaledDensity);
                }
            }

            @Override
            public void onLowMemory() {

            }
        });
    }

    /**
     * 在 application 中全局激活適配(也可多帶帶使用 match() 方法在指定頁(yè)面中配置適配)
     */
    @RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public static void register(@NonNull final Application application, final float designSize, final int matchBase, final int matchUnit) {
        if (mActivityLifecycleCallback == null) {
            mActivityLifecycleCallback = new Application.ActivityLifecycleCallbacks() {
                @Override
                public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                    if (activity != null) {
                        match(activity, designSize, matchBase, matchUnit);
                    }
                }

                @Override
                public void onActivityStarted(Activity activity) {

                }

                @Override
                public void onActivityResumed(Activity activity) {

                }

                @Override
                public void onActivityPaused(Activity activity) {

                }

                @Override
                public void onActivityStopped(Activity activity) {

                }

                @Override
                public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

                }

                @Override
                public void onActivityDestroyed(Activity activity) {

                }
            };
            application.registerActivityLifecycleCallbacks(mActivityLifecycleCallback);
        }
    }

    /**
     * 全局取消所有的適配
     */
    @RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public static void unregister(@NonNull final Application application, @NonNull int... matchUnit) {
        if (mActivityLifecycleCallback != null) {
            application.unregisterActivityLifecycleCallbacks(mActivityLifecycleCallback);
            mActivityLifecycleCallback = null;
        }
        for (int unit : matchUnit) {
            cancelMatch(application, unit);
        }
    }


    /**
     * 適配屏幕(放在 Activity 的 setContentView() 之前執(zhí)行)
     *
     * @param context                               上下文
     * @param designSize                            設(shè)計(jì)圖的尺寸
     */
    public static void match(@NonNull final Context context, final float designSize) {
        match(context, designSize, MATCH_BASE_WIDTH, MATCH_UNIT_DP);
    }


    /**
     * 適配屏幕(放在 Activity 的 setContentView() 之前執(zhí)行)
     *
     * @param context                               上下文
     * @param designSize                            設(shè)計(jì)圖的尺寸
     * @param matchBase                             適配基準(zhǔn)
     */
    public static void match(@NonNull final Context context, final float designSize, int matchBase) {
        match(context, designSize, matchBase, MATCH_UNIT_DP);
    }

    /**
     * 適配屏幕(放在 Activity 的 setContentView() 之前執(zhí)行)
     *
     * @param context                               上下文
     * @param designSize                            設(shè)計(jì)圖的尺寸
     * @param matchBase                             適配基準(zhǔn)
     * @param matchUnit                             使用的適配單位
     */
    private static void match(@NonNull final Context context, final float designSize, int matchBase, int matchUnit) {
        if (designSize == 0) {
            throw new UnsupportedOperationException("The designSize cannot be equal to 0");
        }
        if (matchUnit == MATCH_UNIT_DP) {
            matchByDP(context, designSize, matchBase);
        } else if (matchUnit == MATCH_UNIT_PT) {
            matchByPT(context, designSize, matchBase);
        }
    }

    /**
     * 重置適配信息,取消適配
     */
    public static void cancelMatch(@NonNull final Context context) {
        cancelMatch(context, MATCH_UNIT_DP);
        cancelMatch(context, MATCH_UNIT_PT);
    }

    /**
     * 重置適配信息,取消適配
     *
     * @param context                       上下文
     * @param matchUnit                     需要取消適配的單位
     */
    private static void cancelMatch(@NonNull final Context context, int matchUnit) {
        if (sMatchInfo != null) {
            final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
            if (matchUnit == MATCH_UNIT_DP) {
                if (displayMetrics.density != sMatchInfo.getAppDensity()) {
                    displayMetrics.density = sMatchInfo.getAppDensity();
                }
                if (displayMetrics.densityDpi != sMatchInfo.getAppDensityDpi()) {
                    displayMetrics.densityDpi = (int) sMatchInfo.getAppDensityDpi();
                }
                if (displayMetrics.scaledDensity != sMatchInfo.getAppScaledDensity()) {
                    displayMetrics.scaledDensity = sMatchInfo.getAppScaledDensity();
                }
            } else if (matchUnit == MATCH_UNIT_PT) {
                if (displayMetrics.xdpi != sMatchInfo.getAppXdpi()) {
                    displayMetrics.xdpi = sMatchInfo.getAppXdpi();
                }
            }
        }
    }


    public static MatchInfo getMatchInfo() {
        return sMatchInfo;
    }


    /**
     * 使用 dp 作為適配單位(適合在新項(xiàng)目中使用,在老項(xiàng)目中使用會(huì)對(duì)原來(lái)既有的 dp 值產(chǎn)生影響)
     * 
*
    * dp 與 px 之間的換算: *
  • px = density * dp
  • *
  • density = dpi / 160
  • *
  • px = dp * (dpi / 160)
  • *
* * @param context 上下文 * @param designSize 設(shè)計(jì)圖的寬/高(單位: dp) * @param base 適配基準(zhǔn) */ private static void matchByDP(@NonNull final Context context, final float designSize, int base) { final float targetDensity; if (base == MATCH_BASE_WIDTH) { targetDensity = sMatchInfo.getScreenWidth() * 1f / designSize; } else if (base == MATCH_BASE_HEIGHT) { targetDensity = sMatchInfo.getScreenHeight() * 1f / designSize; } else { targetDensity = sMatchInfo.getScreenWidth() * 1f / designSize; } final int targetDensityDpi = (int) (targetDensity * 160); final float targetScaledDensity = targetDensity * (sMatchInfo.getAppScaledDensity() / sMatchInfo.getAppDensity()); final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); displayMetrics.density = targetDensity; displayMetrics.densityDpi = targetDensityDpi; displayMetrics.scaledDensity = targetScaledDensity; } /** * 使用 pt 作為適配單位(因?yàn)?pt 比較冷門(mén),新老項(xiàng)目皆適合使用;也可作為 dp 適配的補(bǔ)充, * 在需要同時(shí)適配寬度和高度時(shí),使用 pt 來(lái)適配 dp 未適配的寬度或高度) *
*

pt 轉(zhuǎn) px 算法: pt * metrics.xdpi * (1.0f/72)

* * @param context 上下文 * @param designSize 設(shè)計(jì)圖的寬/高(單位: pt) * @param base 適配基準(zhǔn) */ private static void matchByPT(@NonNull final Context context, final float designSize, int base) { final float targetXdpi; if (base == MATCH_BASE_WIDTH) { targetXdpi = sMatchInfo.getScreenWidth() * 72f / designSize; } else if (base == MATCH_BASE_HEIGHT) { targetXdpi = sMatchInfo.getScreenHeight() * 72f / designSize; } else { targetXdpi = sMatchInfo.getScreenWidth() * 72f / designSize; } final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); displayMetrics.xdpi = targetXdpi; } /** * 適配信息 */ private static class MatchInfo { private int screenWidth; private int screenHeight; private float appDensity; private float appDensityDpi; private float appScaledDensity; private float appXdpi; int getScreenWidth() { return screenWidth; } void setScreenWidth(int screenWidth) { this.screenWidth = screenWidth; } int getScreenHeight() { return screenHeight; } void setScreenHeight(int screenHeight) { this.screenHeight = screenHeight; } float getAppDensity() { return appDensity; } void setAppDensity(float appDensity) { this.appDensity = appDensity; } float getAppDensityDpi() { return appDensityDpi; } void setAppDensityDpi(float appDensityDpi) { this.appDensityDpi = appDensityDpi; } float getAppScaledDensity() { return appScaledDensity; } void setAppScaledDensity(float appScaledDensity) { this.appScaledDensity = appScaledDensity; } float getAppXdpi() { return appXdpi; } void setAppXdpi(float appXdpi) { this.appXdpi = appXdpi; } } }
6.2 鴻洋大AutoLayout框架

我記得上上一個(gè)公司的項(xiàng)目投資界就是用的這個(gè)屏幕適配庫(kù)……哈哈

該庫(kù)的想法非常好:對(duì)照設(shè)計(jì)圖,使用px編寫(xiě)布局,不影響預(yù)覽;繪制階段將對(duì)應(yīng)設(shè)計(jì)圖的px數(shù)值計(jì)算轉(zhuǎn)換為當(dāng)前屏幕下適配的大小;為簡(jiǎn)化接入,inflate時(shí)自動(dòng)將各Layout轉(zhuǎn)換為對(duì)應(yīng)的AutoLayout,從而不需要在所有的xml中更改。但是同時(shí)該庫(kù)也存在以下等問(wèn)題:

擴(kuò)展性較差。對(duì)于每一種ViewGroup都要對(duì)應(yīng)編寫(xiě)對(duì)應(yīng)的AutoLayout進(jìn)行擴(kuò)展,對(duì)于各View的每個(gè)需要適配的屬性都要編寫(xiě)代碼進(jìn)行適配擴(kuò)展;

在onMeasure階段進(jìn)行數(shù)值計(jì)算。消耗性能,并且這對(duì)于非LayoutParams中的屬性存在較多不合理之處。比如在onMeasure時(shí)對(duì)TextView的textSize進(jìn)行換算并setTextSize,那么玩家在代碼中動(dòng)態(tài)設(shè)置的textSize都會(huì)失效,因?yàn)樵诿看蝟nMesasure時(shí)都會(huì)重新被AutoLayout重新設(shè)置覆蓋。

issue較多并且作者已不再維護(hù)。

個(gè)人覺(jué)得AutoLayout的設(shè)計(jì)思想非常優(yōu)秀,但是將LayoutParams與屬性作為切入口在mesure過(guò)程中進(jìn)行轉(zhuǎn)換計(jì)算的方案存在效率與擴(kuò)展性等方面的問(wèn)題。那么Android計(jì)算長(zhǎng)度的收口在哪里,能不能在Android計(jì)算長(zhǎng)度時(shí)進(jìn)行換算呢?如果能在Android計(jì)算長(zhǎng)度時(shí)進(jìn)行換算,那么就不需要一系列多余的計(jì)算以及適配,一切問(wèn)題就都迎刃而解了

6.3 AndroidAutoSize

已經(jīng)用于現(xiàn)在正式庫(kù),代碼量多,且注釋也比較項(xiàng)目,作者更新很頻繁,極力維護(hù)并解決bug,非常不錯(cuò)!

關(guān)于其他內(nèi)容介紹 01.關(guān)于博客匯總鏈接

1.技術(shù)博客匯總

2.開(kāi)源項(xiàng)目匯總

3.生活博客匯總

4.喜馬拉雅音頻匯總

5.其他匯總

02.關(guān)于我的博客

我的個(gè)人站點(diǎn):www.yczbj.org,www.ycbjie.cn

github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/...

簡(jiǎn)書(shū):http://www.jianshu.com/u/b7b2...

csdn:http://my.csdn.net/m0_37700275

喜馬拉雅聽(tīng)書(shū):http://www.ximalaya.com/zhubo...

開(kāi)源中國(guó):https://my.oschina.net/zbj161...

泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...

郵箱:yangchong211@163.com

阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV

segmentfault頭條:https://segmentfault.com/u/xi...

03.參考博客

一種極低成本的Android屏幕適配方式:https://mp.weixin.qq.com/s/d9...

Android 屏幕適配從未如斯簡(jiǎn)單:https://juejin.im/post/5b6250...

今日頭條適配方案:https://www.jianshu.com/p/55e...

Android 目前最穩(wěn)定和高效的UI適配方案:https://www.jianshu.com/p/a4b...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/97789.html

相關(guān)文章

  • Android屏幕適配方案分析

    摘要:下面來(lái)看看常見(jiàn)的三種比較成熟的屏幕適配方案,并分析這幾種方案的優(yōu)劣。屏幕適配方案寬高限定符適配設(shè)定一個(gè)基準(zhǔn)的分辨率,也就是設(shè)計(jì)圖對(duì)應(yīng)的分辨率,其他分辨率都根據(jù)這個(gè)基準(zhǔn)分辨率來(lái)計(jì)算,在不同的尺寸文件夾內(nèi)部,根據(jù)該尺寸編寫(xiě)對(duì)應(yīng)的文件。 為什么要屏幕適配 Android開(kāi)發(fā)過(guò)程中我們常用的尺寸單位有px、dp,還有一種sp一般是用于字體的大小。但是由于px是像素單位,比如我們通常說(shuō)的手機(jī)分辨...

    Achilles 評(píng)論0 收藏0
  • Android屏幕適配方案

    摘要:下圖為圖標(biāo)的各個(gè)屏幕密度的對(duì)應(yīng)尺寸屏幕密度圖標(biāo)尺寸解析解析獲取屏幕分辨率信息的三種方法第一種第二種第三種屏幕適配出現(xiàn)的原因什么是像素點(diǎn)屏幕分辨率是指在橫縱向上的像素點(diǎn)數(shù),單位是,個(gè)像素點(diǎn)。 目錄介紹 1.屏幕適配定義 2.相關(guān)重要的概念 2.1 屏幕尺寸[物理尺寸] 2.2 屏幕分辨率[px] 2.3 屏幕像素密度[dpi] 2.4 dp、dip、dpi、sp、px 2.5 md...

    XboxYan 評(píng)論0 收藏0
  • 屏幕適配全方位解析

    摘要:需要注意的是,這種通過(guò)限定符分辨屏幕尺寸的方法,適用于之前。這種最小寬度限定符適用于之后,所以如果要適配全部的版本,就要使用限定符和文件同時(shí)存在于項(xiàng)目目錄下。 1.屏幕適配概念 而隨著支持Android系統(tǒng)的設(shè)備(手機(jī)、平板、電視、手表)的增多,設(shè)備碎片化、品牌碎片化、系統(tǒng)碎片化、傳感器碎片化和屏幕碎片化的程度也在不斷地加深。而我們今天要探討的,則是對(duì)我們開(kāi)發(fā)影響比較大的——屏幕的碎片...

    mochixuan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<