Android屏幕適配,Android屏幕兼容劝枣,Android不同大小屏幕汤踏,字節(jié)跳動(dòng)屏幕適配方案

需要的基本知識(shí):

px:

一個(gè)像素點(diǎn)

dpi:

用于印刷行業(yè),表示一英寸內(nèi)的墨點(diǎn)數(shù)

ppi:

表示一英寸內(nèi)的像素點(diǎn)舔腾,對(duì)于Android,dpi=ppi

ppi和px的關(guān)系

dp:

1dp在不同大小溪胶,分辨率的屏幕上是同長的(前提是系統(tǒng)要把px,dp比例算對(duì)稳诚,下面的方案二哗脖,正是使用了非標(biāo)準(zhǔn)px,dp比例)

三者轉(zhuǎn)換關(guān)系:

px = dp * (dpi / 160)

舉個(gè)例子:

若一個(gè)屏幕的分辨率為640*480,大小為5寸扳还,那這個(gè)屏幕的ppi(dpi)為160才避,那么根據(jù)以上公式,在這個(gè)屏幕上正好1dp=1px

若一個(gè)屏幕的分辨率為1280*960,大小為5寸氨距,那這個(gè)屏幕的ppi(dpi)為320桑逝,那么根據(jù)以上公式,在這個(gè)屏幕上1dp=2px

對(duì)于一個(gè)640dp*360dp的設(shè)計(jì)圖俏让。我們有各種各樣dp屏幕的適配楞遏,

如果對(duì)view設(shè)定固定的dp茬暇,會(huì)導(dǎo)致這個(gè)view在各個(gè)屏幕的大小一樣,而不是占據(jù)屏幕的比例一樣寡喝,這顯然與設(shè)計(jì)圖不符

屏幕適配方案一:

針對(duì)不同大小的屏幕設(shè)置不同的dp而钞,

通過Android限定符來實(shí)現(xiàn),創(chuàng)建多個(gè)dimen文件拘荡,分別放在xh臼节,xxh這些文件夾下,

這個(gè)方案不能完美適配珊皿,因?yàn)檫@些限定符無法指代所有Android手機(jī)网缝,有很大局限性,不推薦蟋定。

屏幕適配方案二(字節(jié)跳動(dòng)的方案粉臊,推薦):

更改1dp所指代的px數(shù),使得不同大小屏幕的寬度的dp數(shù)驶兜,總是和設(shè)計(jì)圖寬度的dp數(shù)一致扼仲,

比如說,設(shè)計(jì)師給到我們的設(shè)計(jì)圖寬度為360dp抄淑,

實(shí)際上因?yàn)槭謾C(jī)屏幕大小不一屠凶,手機(jī)屏幕寬度可能有360dp,420dp肆资,480dp的矗愧,

此時(shí)一張?jiān)O(shè)計(jì)圖去適配這些屏幕,就會(huì)出現(xiàn)效果差異郑原,

而方案二就是通過改變手機(jī)的dp/px比唉韭,來實(shí)現(xiàn)各個(gè)手機(jī)寬度都是360dp,

這樣一個(gè)View展示在不同的屏幕上時(shí)犯犁,其和ui的差距只是等比變大或者縮小了属愤,

但是這個(gè)View的寬度和屏幕寬度比,不會(huì)因?yàn)槠聊淮笮〔町惏l(fā)生變化酸役,

顯然這是可接受的住诸,下面我們來看下怎么實(shí)現(xiàn)吧。

Android中簇捍,DisplayMetrics.density 這個(gè)字段表示1dp對(duì)應(yīng)的px數(shù)

app中所有dp轉(zhuǎn)px都是通過這個(gè)字段來計(jì)算的只壳,我們可以設(shè)置這個(gè)字段,以我們?cè)O(shè)計(jì)圖寬度為360dp為例

在setContentView()方法前調(diào)用:

private static void setCustomDensity(@NonNull Activity activity, @NonNull Application application){

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

    //360表示這個(gè)項(xiàng)目設(shè)計(jì)圖的寬度為360dp
    final float targetDensity=appDisplayMetrics.widthPixels/360;//每dp等于targetDensity px

    final int targetDensityDpi=(int)(160*targetDensity);//重新計(jì)算設(shè)備的dpi

    appDisplayMetrics.density=appDisplayMetrics.scaledDensity=targetDensity;

    appDisplayMetrics.densityDpi=targetDensityDpi;

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

    activityDisplayMetrics.density=activityDisplayMetrics.scaledDensity=targetDensity;

    activityDisplayMetrics.densityDpi=targetDensityDpi;

}

驗(yàn)證:

新建一個(gè)activity暑塑,使用以下布局

<LinearLayout xmlns:android="[http://schemas.android.com/apk/res/android](http://schemas.android.com/apk/res/android)"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

<TextView

android:layout_width="180dp"

android:layout_height="match_parent"

android:text="我的寬度正好是屏幕一半"

android:textSize="50dp"

android:textColor="#ff0000"

android:background="#000000"/>

</LinearLayout>

運(yùn)行在不同手機(jī)上吼句,可以看到,即使手機(jī)屏幕的大小不同事格,TextView寬度總是屏幕寬度的一半

上述代碼存在缺陷惕艳,因?yàn)橛脩艨赡芡ㄟ^系統(tǒng)設(shè)置設(shè)置了默認(rèn)字體大小搞隐,

這會(huì)改變 DisplayMetrics.scaledDensity的值,這個(gè)值和DisplayMetrics.density的比例應(yīng)當(dāng)保持不變

所以正確的計(jì)算方法為:

final float targetScaledDensity=targetDensity*(appDisplayMetrics.scaledDensity/appDisplayMetrics.density);

同時(shí)我們還要監(jiān)聽字體改變事件远搪,在字體改變時(shí)重新計(jì)算這個(gè)值劣纲,最終代碼參考:

private static float sNoncompatDensity=0;

private static float sNoncompatScaldeDensity=0;

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

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

if (sNoncompatDensity==0){

sNoncompatDensity=appDisplayMetrics.density;

sNoncompatScaldeDensity=appDisplayMetrics.scaledDensity;

application.registerComponentCallbacks(new ComponentCallbacks() {

@Override

public void onConfigurationChanged(Configuration newConfig) {

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

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

}

}

@Override

public void onLowMemory() {

}

});

}

//360表示這個(gè)項(xiàng)目設(shè)計(jì)圖的寬度為360dp
final float targetDensity=appDisplayMetrics.widthPixels/360;//每dp等于targetDensity px

final float targetScaledDensity=(sNoncompatScaldeDensity/sNoncompatDensity)*targetDensity;

final int targetDensityDpi=(int)(160*targetDensity);//重新計(jì)算設(shè)備的dpi

appDisplayMetrics.density=targetDensity;

appDisplayMetrics.scaledDensity=targetScaledDensity;

appDisplayMetrics.densityDpi=targetDensityDpi;

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

activityDisplayMetrics.density=targetDensity;

activityDisplayMetrics.scaledDensity=targetScaledDensity;

activityDisplayMetrics.densityDpi=targetDensityDpi;

}

參考:

https://99designs.com/blog/tips/ppi-vs-dpi-whats-the-difference/

https://www.csdn.net/gather_20/MtTakg4sNzIxNS1ibG9n.html

https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA?tdsourcetag=s_pctim_aiomsg

end

如果你覺得這篇文章對(duì)你有所幫助,不妨點(diǎn)一個(gè)贊谁鳍,作者會(huì)非常高興的癞季。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市倘潜,隨后出現(xiàn)的幾起案子绷柒,更是在濱河造成了極大的恐慌,老刑警劉巖涮因,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件废睦,死亡現(xiàn)場離奇詭異,居然都是意外死亡养泡,警方通過查閱死者的電腦和手機(jī)嗜湃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澜掩,“玉大人购披,你說我怎么就攤上這事∈湎酰” “怎么了今瀑?”我有些...
    開封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵程梦,是天一觀的道長点把。 經(jīng)常有香客問我,道長屿附,這世上最難降的妖魔是什么郎逃? 我笑而不...
    開封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮挺份,結(jié)果婚禮上褒翰,老公的妹妹穿的比我還像新娘。我一直安慰自己匀泊,他們只是感情好优训,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著各聘,像睡著了一般揣非。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上躲因,一...
    開封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天早敬,我揣著相機(jī)與錄音忌傻,去河邊找鬼。 笑死搞监,一個(gè)胖子當(dāng)著我的面吹牛水孩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播琐驴,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼俘种,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了绝淡?” 一聲冷哼從身側(cè)響起安疗,我...
    開封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎够委,沒想到半個(gè)月后荐类,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茁帽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年玉罐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潘拨。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吊输,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铁追,到底是詐尸還是另有隱情季蚂,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布琅束,位于F島的核電站扭屁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏涩禀。R本人自食惡果不足惜料滥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望艾船。 院中可真熱鬧葵腹,春花似錦、人聲如沸屿岂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爷怀。三九已至阻肩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霉撵,已是汗流浹背磺浙。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來泰國打工洪囤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撕氧。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓瘤缩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伦泥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子剥啤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350