Android屏幕適配方式--來自字節(jié)團隊的低成本適配方案

轉(zhuǎn)載請標(biāo)明出處http://www.reibang.com/p/71a68addb357

前言:現(xiàn)在的Android開發(fā)環(huán)境下笆环,手機適配是一直沒有消失,長存的問題躁劣。就連IOS環(huán)境下的屏幕也都變得多樣。反觀Android環(huán)境下的各個廠家的各種尺寸屏幕手機的適配账忘,是個難辦的問題。在這環(huán)境之下鳖擒,其實Android屏幕適配的解決,還是有幾套方案可以實行的蒋荚。包括常用的針對你所需要適配的手機屏幕的分辨率各自建立一個文件夾。hongyang大神文章里還有自動生成文件夾的工具圆裕,這里不贅述,這里說一種更低成本的吓妆,頭條團隊提供的方案。在此之下先說一下分辨率相關(guān)的幾個基礎(chǔ)知識點行拢。

1. 分辨率

分辨率就是手機屏幕的像素點數(shù),一般描述成屏幕的“寬×高”舟奠,720×1280表示此屏幕在寬度方向有720個像素,在高度方向有1280個像素沼瘫。在進行屏幕適配時,不要直接通過分辨率適配耿戚,應(yīng)該通過屏幕尺寸和屏幕密度來適配

2. 屏幕大小

屏幕尺寸是指屏幕的物理尺寸,是通過測量屏幕的對角線測量出來的坛猪。以英寸(inch)為單位。指對角線的尺寸墅茉,比如6寸×2.54厘米/寸=15.24厘米。

3. 屏幕密度(dpi)

屏幕物理區(qū)域中的像素量就斤,通常稱為dpi/ppi(每英寸的像素點數(shù),ios為ppi,anroid為dpi)。密度越高战转,成像的效果越好搜立,越細(xì)膩。有些廠家會推出2k,3k刁标,4k的屏幕,用戶體驗的確是很好的膀懈。

4. px (像素)

px 即 pixel,像素點启搂,電子屏幕上組成圖像的最基本單位,在上面描述屏幕分辨率時使用到該單位胳赌。

5. dp (也稱 dip,與dpi區(qū)別)

Density-independent pixel (dp)獨立像素密度疑苫。標(biāo)準(zhǔn)是160dip.即1dp對應(yīng)1個pixel,計算公式如:px = dp * (dpi / 160)捍掺,屏幕密度越大,1dp對應(yīng) 的像素點越多挺勿。

6. sp (可縮放獨立像素)

在安卓系統(tǒng)里,sp 與 dp 類似满钟,不同的是 sp 可以根據(jù)用戶的字體大小首選項進行縮放,而 dp 則不會湃番。 盡量使用 dp 作為空間大小單位,sp 作為文字相關(guān)大小單位吠撮,例如:新聞類和短信類等大篇幅文本讲竿,推薦使用 sp 為單位。

android中的dp在渲染前會將dp轉(zhuǎn)為px题禀。根據(jù)這個公式。

px = density * dp;

density = dpi / 160;

px = dp * (dpi / 160);

而dpi是這么計算出來的迈嘹。

image

即勾股定理出對角線全庸,除以屏幕尺寸融痛,就是dpi大小了。

這樣會出現(xiàn)一個問題雁刷,就是當(dāng)手機的dpi越大的時候,使用dp計算出來的px值是會越來越大的沛励。假設(shè)你UI設(shè)計圖是按360dp設(shè)計。

若實際手機是大于360dp的目派,那么顯示效果,px值就會偏大址貌。

所以為了解決這個問題,頭條團隊提供了一個方案练对,就是在設(shè)置系統(tǒng)density的值,通過獲得UI圖dpi和手機真實寬px計算,最終設(shè)置系統(tǒng)的density螟凭。

這個核心處理工具類


public class MyDensityUtil {

    //屏幕密度

    private static float sComponentDensity;

    //屏幕顯示的字體的密度

    private static float sComponentScaledDensity;

    /**

    * 設(shè)置自定義的屏幕密度

    * 在BaseActivity中的onCreate()方法中調(diào)用

    */

    static void setCustomDensity(Activity activity, final Application application) {

        //顯示器的一般信息類

        final DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();

        if (sComponentDensity ==0) {

            //屏幕密度

            sComponentDensity = appDisplayMetrics.density;

            //屏幕顯示的字體的密度

            sComponentScaledDensity = appDisplayMetrics.scaledDensity;

            //字體切換監(jiān)聽,防止切換字體再返回應(yīng)用字體并沒有變化

            application.registerComponentCallbacks(new ComponentCallbacks() {

@Override

                public void onConfigurationChanged(Configuration newConfig) {

if (newConfig !=null && newConfig.fontScale >0) {

sComponentScaledDensity =application.getResources().getDisplayMetrics().scaledDensity;

                    }

}

@Override

                public void onLowMemory() {

}

});

        }

        //實際顯示器的絕對寬度與UI寬度比例

        final float targetDensity = appDisplayMetrics.widthPixels /1080F;//以1080dp和寬維度來適配的

        //通過原本的ScaledDensity和density獲取比例從而得出現(xiàn)在的實際顯示器字體密度

        final float targetScaledDensity = targetDensity * (sComponentScaledDensity /sComponentDensity);

        //DENSITY_DEFAULT棒厘,默認(rèn)參考密度

        final int targetDensityDpi = (int) (DENSITY_DEFAULT * targetDensity);

        //賦值到application中的density中

        appDisplayMetrics.density = targetDensity;

        appDisplayMetrics.scaledDensity = targetScaledDensity;

        appDisplayMetrics.densityDpi = targetDensityDpi;

        //下面賦值到activity中的density中

        final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();

        activityDisplayMetrics.density = targetDensity;

        activityDisplayMetrics.scaledDensity = targetScaledDensity;

        activityDisplayMetrics.densityDpi = targetDensityDpi;

    }

使用如下:

public class BaseDensityActivity extends Activity {
    /**
     * px = density * dp;
     * density = dpi / 160;
     * px = dp * (dpi / 160);
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyDensityUtil.setCustomDensity(this,getApplication());
        setContentView(R.layout.activity_main);
    }
}

代碼比較簡單下隧,而且最重要的,這些都是公開的可操作的api淆院,而并非是通過反射,hook去操作了系統(tǒng)非公開的私有api土辩,是穩(wěn)定,低入侵的方案拷淘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者启涯。
  • 序言:七十年代末恃轩,一起剝皮案震驚了整個濱河市扁瓢,隨后出現(xiàn)的幾起案子补君,更是在濱河造成了極大的恐慌引几,老刑警劉巖挽铁,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異楣铁,居然都是意外死亡,警方通過查閱死者的電腦和手機盖腕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門浓镜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人膛薛,你說我怎么就攤上這事听隐⊙湃危” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵沪么,是天一觀的道長。 經(jīng)常有香客問我成玫,道長,這世上最難降的妖魔是什么哭当? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任冗澈,我火速辦了婚禮,結(jié)果婚禮上亚亲,老公的妹妹穿的比我還像新娘彻采。我一直安慰自己,他們只是感情好肛响,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著特笋,像睡著了一般剃浇。 火紅的嫁衣襯著肌膚如雪猎物。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天蔫磨,我揣著相機與錄音,去河邊找鬼堤如。 笑死,一個胖子當(dāng)著我的面吹牛搀罢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播魄揉,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼洛退!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起兵怯,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎媒区,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袜漩,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年宙攻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片座掘。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡柔滔,死狀恐怖萍虽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杉编,我是刑警寧澤超全,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布卵迂,位于F島的核電站裕便,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏偿衰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一下翎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧视事,春花似錦胆萧、人聲如沸俐东。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至砌庄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娄昆,已是汗流浹背佩微。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工哺眯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人杆怕。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓壳贪,卻偏偏與公主長得像寝杖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瑟幕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344