屏幕適配小記

最近在工作中遇到了屏幕適配的問題汹押,這里做個記錄,方便以后查看奏寨。

先貼出參考的文章:參考文章


場景是這樣的:做一個widget榛搔,他沒有activity application之類的,是由主應(yīng)用反射拿到對應(yīng)的view去做渲染说贝,我的工作是做皮膚應(yīng)用议惰,不涉及到主應(yīng)用的汹押。

那么問題來了形耗,這意味著有很多限制歹河,比如無法用那些UI適配框架去適配耍属。

先說一下分辨率相關(guān)的那幾個單位吧:

  1. 屏幕尺寸:即手機(jī)屏幕對角線的長度 單位是英寸 inch琳轿。

  2. 屏幕分辨率:手機(jī)屏幕的寬 高像素點(diǎn)數(shù) 單位是px蚯撩。一般設(shè)計給的設(shè)計稿也是以這個為單位的逗爹。

  3. dpi:屏幕像素密度 1英寸有多少像素绑蔫。Android上會以這個來區(qū)分 mdpi hdpi xdpi 等資源文件夾蛋哭。

  4. dp:密度無關(guān)像素 單位 dp县习,Android上推薦使用的單位

  5. desity:密度,表示 1dp等于多少px

上面那些單位的計算方式:

  1. dpi
    dpi 計算公式

tip:真實(shí)的dpi其實(shí)是拿的系統(tǒng)配置項(xiàng)里的 ro.sf.lcd_density,可以通過adb shell命令查看:

$ cd system
$ cat build.prop|grep density 
  1. desity

    desity 計算公式

  2. dp

    dp 計算公式

網(wǎng)上查閱了一些適配的方案躁愿,大概有以下幾種:

1. dp直接適配叛本,建 mdpi、hdpi彤钟、xdpi来候、xxdpi、xxxdpi 這幾個values文件 逸雹,分別去寫dimens营搅。這種方式太麻煩,要根據(jù)不同的手機(jī)一點(diǎn)點(diǎn)去調(diào)梆砸,而且適配效果也不好转质,對應(yīng)相同dpi,不同尺寸的手機(jī)也不能很好去適配帖世。

Google官方的區(qū)分標(biāo)準(zhǔn)

2. 寬高限定符適配休蟹,就是建不同手機(jī)寬高像素的values文件 如:values-480×320,然后找到一個基準(zhǔn)分辨率日矫,其他的分辨率都根據(jù)這個基準(zhǔn)去把寬高等分赂弓。這樣好處是我們只需要適配一個分辨率即可,缺點(diǎn)是命中率太低哪轿,如果沒有找到當(dāng)前運(yùn)行的手機(jī)分辨率的文件夾盈魁,就會去拿默認(rèn)dimens里的值,這樣UI就可能變形了缔逛。

比如以480x320為基準(zhǔn)分辨率

寬度為320备埃,將任何分辨率的寬度整分為320份,取值為x1到x320

高度為480褐奴,將任何分辨率的高度整分為480份按脚,取值為y1到y(tǒng)480

那么對于800480的分辨率的dimens文件來說,x1=(480/320)1=1.5px x2=(480/320)*2=3px

  1. UI適配框架敦冬,比如鴻洋的AutoLayout辅搬,這種使用簡單,前提是你有AndroidManifest和Activity脖旱,而且現(xiàn)在該項(xiàng)目已經(jīng)停止維護(hù)堪遂。(對于我來說并不適用??)

4. 今日頭條的適配方案,只要能拿到上下文環(huán)境context就行萌庆。他是修改當(dāng)前應(yīng)用獲取到的density值溶褪。主要方法是根據(jù)設(shè)計圖的寬度dp,重新計算出density践险,然后賦值給DisplayMetrics的density猿妈。不過我試了一下吹菱,效果不錯,就是導(dǎo)致在部分手機(jī)上主應(yīng)用的字體偏小彭则,可能是主應(yīng)用里有不同dpi的values文件導(dǎo)致的鳍刷。
感興趣的可以看看今日頭條適配方案,主要代碼如下:

DisplayMetrics appDisplayMetrics = mainPkgContext.getResources().getDisplayMetrics();
if (sNoncompatDensity == 0) {
    sNoncompatDensity = appDisplayMetrics.density;
    sNoncompatScaledDensity = appDisplayMetrics.scaledDensity;
    // 當(dāng)修改系統(tǒng)字體時俯抖,會回調(diào)此方法
    mainPkgContext.getApplicationContext().registerComponentCallbacks(new ComponentCallbacks() {
        @Override
        public void onConfigurationChanged(Configuration configuration) {
            if (configuration != null && configuration.fontScale > 0) {
                sNoncompatScaledDensity = mainPkgContext.getResources().getDisplayMetrics().scaledDensity;
            }
        }

        @Override
        public void onLowMemory() {
        }
    });
}

// 320是設(shè)計圖的寬度dp输瓜,可以根據(jù)自己的設(shè)計稿去修改
float targetDesity = appDisplayMetrics.widthPixels / 320;
float targetScaledDensity = targetDesity * (sNoncompatScaledDensity / sNoncompatDensity);
int targetDesityDpi = (int) (160 * targetDesity);

appDisplayMetrics.density = targetDesity;
appDisplayMetrics.scaledDensity = targetScaledDensity;
appDisplayMetrics.densityDpi = targetDesityDpi;

DisplayMetrics activityDisplayMetrics = context.getResources().getDisplayMetrics();
activityDisplayMetrics.density = targetDesity;
activityDisplayMetrics.scaledDensity = targetScaledDensity;
activityDisplayMetrics.densityDpi = targetDesityDpi;

5. 最小寬度限定符適配,和寬高限定符適配差不多芬萍,也是建不同手機(jī)寬度dp的values文件 如:values-sw320dp尤揣,系統(tǒng)會根據(jù)手機(jī)的寬度去拿不同文件夾下的值。
我們只需要根據(jù)設(shè)計稿的寬度計算出各個sw文件的px對應(yīng)多少dp柬祠,使用的時候直接根據(jù)設(shè)計稿去引用px就行芹缔。網(wǎng)上有很多自動生成這些文件的工具,貼出我使用的一個:自動生成sw工具 java項(xiàng)目
這種方式優(yōu)點(diǎn)是容錯性提高了瓶盛,如果沒有找到當(dāng)前運(yùn)行的手機(jī)寬度的文件夾,就會去拿與之相近的dimens里的值示罗,這樣UI就不會出現(xiàn)太大的差異惩猫。

各個手機(jī)的sw dp文件夾
計算px對應(yīng)的dp值
使用時直接引用


最終我還是選擇了最小寬度限定符的方式,因?yàn)檫@種侵入性小蚜点,不過就是太多的values文件會增加應(yīng)用的大小轧房。

如果有不對的地方還望大佬指出。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绍绘,一起剝皮案震驚了整個濱河市奶镶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌陪拘,老刑警劉巖厂镇,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異左刽,居然都是意外死亡捺信,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門欠痴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迄靠,“玉大人,你說我怎么就攤上這事喇辽≌浦浚” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵菩咨,是天一觀的道長吠式。 經(jīng)常有香客問我陡厘,道長,這世上最難降的妖魔是什么奇徒? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任雏亚,我火速辦了婚禮,結(jié)果婚禮上摩钙,老公的妹妹穿的比我還像新娘罢低。我一直安慰自己,他們只是感情好胖笛,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布网持。 她就那樣靜靜地躺著,像睡著了一般长踊。 火紅的嫁衣襯著肌膚如雪功舀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天身弊,我揣著相機(jī)與錄音辟汰,去河邊找鬼。 笑死阱佛,一個胖子當(dāng)著我的面吹牛帖汞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凑术,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼翩蘸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了淮逊?” 一聲冷哼從身側(cè)響起催首,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泄鹏,沒想到半個月后郎任,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡命满,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年涝滴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胶台。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡歼疮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诈唬,到底是詐尸還是另有隱情韩脏,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布铸磅,位于F島的核電站赡矢,受9級特大地震影響杭朱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吹散,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一弧械、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧空民,春花似錦刃唐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至浊猾,卻和暖如春抖甘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背葫慎。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工衔彻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人偷办。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓米奸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親爽篷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 夕陽下面慢睡,一條靜靜的小河逐工。河的這一邊是去往學(xué)校的路,而那一邊坐落著姥姥家的房子漂辐,是我童年的樂園泪喊。 我六歲那年,在姥...
    Q先生日記閱讀 307評論 0 0