十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
Android屏幕適配-基礎篇
創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站制作、網(wǎng)站建設與策劃設計,房山網(wǎng)站建設哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設十余年,網(wǎng)設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:房山等地區(qū)。房山做網(wǎng)站價格咨詢:18982081108
Android屏幕適配-應用篇
從兩個大方面闡述一下Android的屏幕適配:
? Android推薦使用dp作為尺寸單位來適配UI ,通過dp加上自適應布局和weight比例布局可以基本解決不同手機上適配的問題,這基本是最原始的Android適配方案。
缺點 :
(1)這種方案只能保證我們寫出來的界面適配絕大部分手機,部分手機仍然需要單獨適配,但dpi的不同,還是會存在差異。
(2)一般的設計稿都是以px為單位的,所以我們在寫layout文件的時候需要將px轉為dp,影響開發(fā)效率。
?為了高效的實現(xiàn)UI開發(fā),出現(xiàn)了新的適配方案,我把它稱作寬高限定符適配。簡單說,就是窮舉市面上所有的Android手機的寬高像素值,設定一個基準的分辨率,其他分辨率都根據(jù)這個基準分辨率來計算,在不同的尺寸文件夾內(nèi)部,根據(jù)該尺寸編寫對應的dimens文件:
鴻洋大神的作品 ,使用也超級簡單,核心功能就是在繪制的時候在onMeasure里面做變換,重新計算px。
缺點 :我們自定義的控件可能會被影響或限制,可能有些特定的控件(框架沒有做適配的控件),需要單獨適配。
??小結:上述幾種適配方案都是實際開發(fā)中用過的方案,但隨著技術不斷的更新,出現(xiàn)了更好的適配方案。
?? 實現(xiàn)原理 :Android會識別屏幕可用高度和寬度的最小尺寸的dp值( 其實就是手機的寬度值 ),然后根據(jù)識別到的結果去資源文件中尋找對應限定符的文件夾下的資源文件。
?? sw限定符適配 和 寬高限定符適配 類似,區(qū)別在于,前者有很好的容錯機制,如果沒有value-sw360dp文件夾,系統(tǒng)會向下尋找,比如離360dp最近的只有value-sw350dp,那么Android就會選擇value-sw350dp文件夾下面的資源文件。這個特性就完美的解決了上文提到的寬高限定符的容錯問題。
?? 優(yōu)點: 1.非常穩(wěn)定,極低概率出現(xiàn)意外
????2.不會有任何性能的損耗
????3.適配范圍可自由控制,不會影響其他三方庫
?? 缺點 :就是多個dimens文件可能導致apk變大,幾百k。
?? 附件: 生成sw文件的工具
?? 實現(xiàn)原理 : 修改系統(tǒng)的density值 (核心)
??今日頭條適配是以設計圖的寬或高進行適配的,適配最終是改變系統(tǒng)density實現(xiàn)的。
?? 過程:
??AndroidAutoSize 是基于今日頭條適配方案,該開源庫已經(jīng)很大程度上解決了今日頭條適配方案的兩個缺點,可以對activity,fragment進行取消適配。也是目前我的項目中所使用的適配方案。
使用也非常簡單只需兩步:
(1)引入:
(2)在 AndroidManifest 中填寫全局設計圖尺寸 (單位 dp),如果使用副單位,則可以直接填寫像素尺寸,不需要再將像素轉化為 dp,詳情請查看 demo-subunits
@[TOC](文章目錄)
hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1"
# 前言
font color=#999AAA 使用工具Android studio,利用values文件下dimens.xml界面適配安卓屏幕/font
hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1"
font color=#999AAA 提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
# 一、概念
1.屏幕分辨率單位是px,例如Android手機常見的分辨率:320x480px、480x800px、720x1280px、1080x1920px。
2.手機屏幕的密度:每英寸的像素點數(shù),單位是dpi。
| 密度類型 |代表的分辨率(px)| 屏幕像素密度(dpi) | 1dp轉換為px |
|:--------|:--------|:--------|:--------|
| 低密度(ldpi) |240x320|120|0.75|
| 中密度(mdpi) |320x480|160|1|
| 高密度(hdpi)|480x800|240| 1.5|
| 超高密度(xhdpi)|720x1280|320|2|
| 超超高密度(xxhdpi) |1080x1920|480|3|
3.由于android的機型屏幕大小品類太多了,有一些是不標準的,這時我們就需要單獨去獲取屏幕的分辨率和密度了。
# 二、獲取屏幕的分辨率和密度
```java
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
float density = displayMetrics.density;
int densityDpi = displayMetrics.densityDpi;
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
Log.e("123","密度:"+density+"---"+densityDpi);
Log.e("123","屏幕分辨率:"+width+"x"+height);
Log.e("123","安卓系統(tǒng):"+android.os.Build.VERSION.RELEASE);
Log.e("123","手表型號:"+android.os.Build.PRODUCT);
```
# 三、SmallestWidth適配
**smallestWidth適配,或者叫sw限定符適配。指的是Android會識別屏幕可用高度和寬度的最小尺寸的dp值(其實就是手機的寬度值),然后根據(jù)識別到的結果去資源文件中尋找對應限定符的文件夾下的資源文件。**
**sw計算公式:sw = 屏幕寬度 / (dpi/160)? 注:160是默認的**
**例如:屏幕寬度為1080px、480dpi 的sw = 1080/(480/160)**
# 四、生成 dimens 文件
1、 首先在 res 目錄下新建各種尺寸的 values 文件 。文件名為:values-sw(你要適配屏幕的sw值)dp。
例如:
![code23]()
注意:values文件下也生成 dimens文件
**生成dimens值工具類**
1、先生成標準的值。//value = (i + 1) * 1;
2、再用生成其他的值。 //value = (i + 1) * 需要生成的sw值/標準的sw值;
例如:value = (i + 1) * 160 / 320;
```java
public static void genDimen() {
? ? StringBuilder stringBuilder = new StringBuilder();
? ? try {
? ? ? ? double value;
? ? ? ? for (int i = 0; i 500; i++) {
? ? ? ? ? //value = (i + 1) * 1; //這里控制對應轉換的值,如果是標準尺寸就一對一轉換
? ? ? ? ? ? //value = (i + 1) * 需要生成的sw值/標準的sw值; //這里控制對應轉換的值
value = (i + 1) * 1
? ? ? ? ? ? //value = (i + 1) * 160 / 320;
? ? ? ? ? ? value = Math.round(value * 100) / 100;
//dp可改成sp
? ? ? ? ? ? stringBuilder.append("dimen name=\"size_" + (i + 1) + "\"" + value + "dp/dimen\r\n");
? ? ? ? }
? ? ? ? if (stringBuilder.length() 4000) {
? ? ? ? ? ? for (int i = 0; i stringBuilder.length(); i += 4000) {
? ? ? ? ? ? ? ? if (i + 4000 stringBuilder.length())
? ? ? ? ? ? ? ? ? ? Log.e("123", stringBuilder.substring(i, i + 4000));
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? Log.e("123", stringBuilder.substring(i, stringBuilder.length()));
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? Log.e("123", stringBuilder.toString());
? ? ? ? }
? ? } catch (Exception e) {
? ? ? ? e.printStackTrace();
? ? } finally {
? ? }
}
```
示例:(我這是以sw320為適配的標準的,你們可改自己的標準)
1、sw320的樣例
```java
resources
dimen name="dimen_1"1.0dp/dimen
dimen name="dimen_2"2.0dp/dimen
dimen name="dimen_3"3.0dp/dimen
dimen name="dimen_4"4.0dp/dimen
dimen name="dimen_5"5.0dp/dimen
dimen name="dimen_6"6.0dp/dimen
dimen name="dimen_7"7.0dp/dimen
dimen name="dimen_8"8.0dp/dimen
dimen name="dimen_9"9.0dp/dimen
dimen name="dimen_10"10.0dp/dimen
dimen name="size_1"1.0sp/dimen
dimen name="size_2"2.0sp/dimen
dimen name="size_3"3.0sp/dimen
dimen name="size_4"4.0sp/dimen
dimen name="size_5"5.0sp/dimen
dimen name="size_6"6.0sp/dimen
dimen name="size_7"7.0sp/dimen
dimen name="size_8"8.0sp/dimen
dimen name="size_9"9.0sp/dimen
dimen name="size_10"10.0sp/dimen
/resources
```
2、sw160的樣例
```java
resources
dimen name="dimen_1"0.0dp/dimen
dimen name="dimen_2"1.0dp/dimen
dimen name="dimen_3"1.0dp/dimen
dimen name="dimen_4"2.0dp/dimen
dimen name="dimen_5"2.0dp/dimen
dimen name="dimen_6"3.0dp/dimen
dimen name="dimen_7"3.0dp/dimen
dimen name="dimen_8"4.0dp/dimen
dimen name="dimen_9"4.0dp/dimen
dimen name="dimen_10"5.0dp/dimen
dimen name="size_1"0.0sp/dimen
dimen name="size_2"1.0sp/dimen
dimen name="size_3"1.0sp/dimen
dimen name="size_4"2.0sp/dimen
dimen name="size_5"2.0sp/dimen
dimen name="size_6"3.0sp/dimen
dimen name="size_7"3.0sp/dimen
dimen name="size_8"4.0sp/dimen
dimen name="size_9"4.0sp/dimen
dimen name="size_10"5.0sp/dimen
/resources
```
3、xml界面控件使用樣例
```java
TextView
? ? android:layout_width="@dimen/dimen_30"
? ? android:layout_height="@dimen/dimen_30"
? ? android:textSize="@dimen/size_20"
? ? android:layout_margin="@dimen/dimen_10"
? ? android:padding="@dimen/dimen_10"
```
hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1"
# 總結
font color=#999999 提示:這里對文章進行總結:
如果你的app需要適配dpi較低的屏幕,最好以最小dpi的sw為適配的標準。
從2017年開始,全面屏之戰(zhàn)逐漸如火如荼的展開了,那么我們Android程序員又多了一個小事情,就是解決全面屏適配的問題。
全面屏和以前的屏幕相比,有以下幾點改變
聲明方式
ratio_float這個值怎么取呢?
其實就是高寬比。
傳統(tǒng)的手機高寬比是:16 : 9 即 16 / 9 ≈ 1.78
那么全面屏的手機寬高比:18 :9 即 18 / 9 = 2
但是這個時候,我們需要注意一下,現(xiàn)在很多手機都在追求更大的高寬比,即讓屏幕頂部和底部邊框越小越好,比如現(xiàn)在的「小米 mix 3 」
即他的高寬比是
19.5 / 9 ≈ 2.17
所以保險起見,設置成為 2.2, 當然這個值也不是固定的,如果有更新的手機上市,沒準我們還得改。
即這樣設定就好了
Android 7.0 google 默認支持了分屏模式,即 Manifest 文件中配置 Activity 的
那么這個時候就不需要再配置上面的 「最大屏幕高寬比」,就可以適配全面屏了。
但是如果通過自定義控件將“分屏模式”禁止的話,就會出現(xiàn)屏幕 上下黑邊的效果,非常丑。
修改AndroidManifest.xml文件,設置targetSdkVersion=26,就是應用升級到O版本。
不需要設置其他任何屬性,默認在任何縱橫比的屏幕都能全屏顯示。
(備注:有一種例外情況需要注意,應用如果已經(jīng)適配到O版本,并且通過meta-data屬性android.max_aspect或者是android:MaxAspectRatio屬性設置了頁面支持的最大縱橫比,同時又通過android:resizeableActivity=“false”設置了頁面不支持分屏,這個時候系統(tǒng)會按照應用自己設置的最大縱橫比決定該頁面是否能全屏顯示,如果應用設置的最大縱橫比比手機屏幕比例小,那應用還是無法全屏顯示。)
默認 UI 為我們切的啟動頁面的圖是固定的,比如 1920*1080
這個能適配以前一般的分辨率的手機,但是全面屏的出現(xiàn),我們會發(fā)現(xiàn),這個啟動頁的圖片會被拉伸,一般是縱向拉伸,因為 “高” 變大了。
那么這種情況的解決方法其實有這么幾種思路:
本人還是覺得虛擬導航按鍵不是一個好東西,但是全面屏的出現(xiàn),真的把我以前喜歡的"實體按鍵" 給舍棄掉了。
我倒是覺得替代以前的"實體按鍵"的最好的方法,還是手勢操作。起碼我覺得小米8 的手勢操作很 6 有沒有。再看看蘋果,壓根就不同虛擬按鍵考慮好不。。。
不過,這是我自己的拙見,請各位虛擬按鍵愛好者,不要噴我,先行謝過。
原則,虛擬按鈕的顯示樣式,其實根據(jù)當前具體的頁面情況進行調整,調整策略其實和status bar 的類似。
可以通過
來定義顏色。
或者通過設置當前activity 主題 或者設置application主題
在主題的樣式中設置:
即可。
頻繁的手機更新迭代,雖然讓我們程序員多了一些事情可做,但是卻也是我們喜聞樂見的事,手機在發(fā)展,說明我們的行業(yè)也在發(fā)展呀,況且,解決這些問題也不是難事。你說是不是呢?
如果沒看懂我的文章,請觀看小米官網(wǎng)提供的方案(其實是一致的):
全面屏及虛擬鍵適配說明
1: dp: android 尺寸的基本單位。 在不同的分辨率的手機里面,1dp對應著不同數(shù)量的px, 這樣就實現(xiàn)了dp定義一個控件大小的時候,在不同分辨率手機里表現(xiàn)出相應大小的像素值。
2: 屏幕分辨率: 1080下160, 表示寬度有1080個像素點而高度有2160個像素點。常見的分辨率有320x480, 480x800, 720x1280, 1080x1920等。
3: 屏幕尺寸: 以寸為單位, Android設備對角線的長度
4: 像素密度: 每英寸的像素點
5: 屏幕尺寸, 分辨率,像素密度 三者之間的關系:
密度(dpi)= √(寬2 + 高2)/屏幕尺寸
6: px:像素,是屏幕上顯示數(shù)據(jù)的最基本的點
7: dpi:屏幕像素密度,每英寸上的像素點數(shù)
8: sp:與dp類似,通常用于指定字體的大小,當用戶修改手機顯示的字體時,字體大小會隨之改變。
1: dp適配方案: Android自帶的原始的適配方案, 在不同的分辨率手機里面表現(xiàn)出相應大小的像素點。
缺點: Android的碎片化嚴重, 如果生產(chǎn)廠家沒有根據(jù)屏幕尺寸、分辨率和像素密度的關系來規(guī)則定義, 或者出一些亂七八糟的屏幕大小,這樣的適配方案就不在適合了。
2: 寬高限定符:枚舉所有的屏幕寬高像素值,根據(jù)等比縮放去適配。如果沒有找到對應的屏幕, 則取默認的。 目前這種方案已經(jīng)被棄用。
缺點:
1: 占用資源大,會增加APK的體積。
2: 容錯機制大需要精準命中資源文件才能適配,比如1920x1080的手機就一定要找到1920x1080的限定符,否則就只能用統(tǒng)一的默認的dimens文件了。而使用默認的尺寸的話,UI就很可能變形。
3:AndroidAutoLayout適配方案(停止維護)
4: SW限定符適配方案:(smallestWidth最小寬度適配)
Android 會去識別屏幕可用高度或者寬度的最小尺寸的dp值。然后根據(jù)識別到的結果去對應的資源文件里面去找尋相應的結果。
如何生成:ScreenMatch插件
此方案跟寬高限定的適配方案相比,有很好的容錯機制, 如果沒有找到對應的適配寬度, 那么會在vlues文件里面去找跟他最接近的寬度。
5:今日頭條適配方案:
1: px 轉 dp 的公式 dp = px / density.不管我們設定的單位是什么, 最終我們都會將這些單位長度轉化為px的。density就是他們的轉化比, 所以,動態(tài)改變這個轉化比也是可以達到我們適配屏幕的目的的。
2: 通過修改density值,強行把所有不同尺寸分辨率的手機的寬度dp值改成一個統(tǒng)一的值(在清單文件中定義),這樣就解決了所有的適配問題。
3: Density = 當前設備屏幕總寬度(單位為像素)/ 設計圖總寬度(單位為 dp) ;
4:引入了AndroidAutoSize屏幕適配框架:
最后, 最重要的................
點贊 點贊 點贊, 不重要的事情也就說3遍......
關鍵字: 屏幕適配 px dp dpi sp large限定符 .9.png
前言: 這篇文章依然是我在 [慕課網(wǎng) ][h]學習 凱子哥 的同名視頻 Android-屏幕適配全攻略 ,所記錄下來的筆記---凱子哥講得真的超詳細。
[h]: "MOOC"
從上圖可以看出,主流的分辨率是前六種:1280×720、1920×1080、800×480、854×480、960×540、1184×720,不過我們有解決方案??赐赀@篇文章,想必你就可以解決常見的屏幕適配問題。
接下來正式進入正題。
介紹幾個在Android屏幕適配上非常重要的名詞:
屏幕尺寸 是指屏幕對角線的長度。單位是英寸,1英寸=2.54厘米
屏幕分辨率 是指在橫縱向上的像素點數(shù),單位是px,1px=1像素點,一般是縱向像素橫向像素,如1280×720
屏幕像素密度 是指每英寸上的像素點數(shù),單位是dpi,即“dot per inch”的縮寫,像素密度和屏幕尺寸和屏幕分辨率有關
dip: Density Independent Pixels(密度無關像素)的縮寫。以 160dpi 為基準,1dp=1px
dp: 同 dip
dpi: 屏幕像素密度的單位,“dot per inch”的縮寫
px: 像素,物理上的絕對單位
sp: Scale-Independent Pixels的縮寫,可以根據(jù)文字大小首選項自動進行縮放。Google推薦我們使用12sp以上的大小,通??梢允褂?2sp,14sp,18sp,22sp,最好不要使用奇數(shù)和小數(shù)。
用于區(qū)分不同的像素密度。
在Google官方開發(fā)文檔中,說明了 ** mdpi:hdpi:xhdpi:xxhdpi:xxxhdpi=2:3:4:6:8 ** 的尺寸比例進行縮放。例如,一個圖標的大小為48×48dp,表示在mdpi上,實際大小為48×48px,在hdpi像素密度上,實際尺寸為mdpi上的1.5倍,即72×72px,以此類推。
我們可以通過以下幾種方式來支持各種屏幕尺寸:
wrap_content: 根據(jù)控件的內(nèi)容設置控件的尺寸
math_parent: 根據(jù)父控件的尺寸大小設置控件的尺寸
weight: 權重,在線性布局中可以使用weight屬性設置控件所占的比例
例如,我們要實現(xiàn)下圖所顯示的效果:當屏幕尺寸改變時,new reader控件兩邊的控件大小不變,new reader控件會占完剩余的空間。
具體布局文件如下:
小插曲: 關于 android:layout_weight 屬性
一般情況,我們都是設置要進行比例分配的方向的寬度為0dp,然后再用權重進行分配。如下:
效果為:
效果為:
button1寬度=L+(L-2L)×1/3=2/3L
button2寬度=L+(L-2L)×2/3=1/3L
當然,還有其他的方式,都可以運用此公式進行計算。
在實際開發(fā)中,我們一般使用0dp的方式,而不使用其他方式。
簡單的布局一般都使用 線性布局 ,而略微復雜點的布局,我們使用 相對布局 ,大多數(shù)時候,我們都是使用這兩種布局的嵌套。
我們使用 相對布局 的原因是, 相對布局 能在各種尺寸的屏幕上保持控件間的相對位置。
res/layout/main.xml 單面板:
res/layout-large/main.xml 雙面板:
如果這個程序運行在屏幕尺寸大于7inch的設備上,系統(tǒng)就會加載 res/layout-large/main.xml 而不是 res/layout/main.xml ,在小于7inch的設備上就會加載 res/layout/main.xml 。
需要注意的是,這種通過 large 限定符分辨屏幕尺寸的方法,適用于android3.2之前。在android3.2之后,為了更精確地分辨屏幕尺寸大小,Google推出了最小寬度限定符。
res/layout-sw600dp/main.xml ,雙面板布局: Small Width 最小寬度
這種方式是不區(qū)分屏幕方向的。這種最小寬度限定符適用于android3.2之后,所以如果要適配android全部的版本,就要使用 large 限定符和 sw600dp 文件同時存在于項目 res 目錄下。
這就要求我們維護兩個相同功能的文件。為了避免繁瑣操作,我們就要使用布局別名。
由于后兩個文具文件一樣,我們可以用以下兩個文件代替上面三個布局文件:
res/layout/main.xml 單面板布局
res/layout/main_twopanes.xml 雙面板布局
然后在 res 下建立
res/values/layout.xml 、
res/values-large/layout.xml 、
res/values-sw600dp/layout.xml 三個文件。
默認布局
res/values/layout.xml :
Android3.2之前的平板布局
res/values-large/layout.xml :
Android3.2之后的平板布局
res/values-sw600dp/layout.xml :
這樣就有了 main 為別名的布局。
在activity中 setContentView(R.layout.main);
這樣,程序在運行時,就會檢測手機的屏幕大小,如果是平板設備就會加載 res/layout/main_twopanes.xml ,如果是手機設備,就會加載 res/layout/main.xml 。我們就解決了只使用一個布局文件來適配android3.2前后的所有平板設備。
如果我們要求給橫屏、豎屏顯示的布局不一樣。就可以使用 屏幕方向限定符 來實現(xiàn)。
例如,要在平板上實現(xiàn)橫豎屏顯示不用的布局,可以用以下方式實現(xiàn)。
res/values-sw600dp-land/layouts.xml :橫屏
res/values-sw600dp-port/layouts.xml :豎屏
自動拉伸位圖,即android下特有的 .9.png 圖片格式。
當我們需要使圖片在拉伸后還能保持一定的顯示效果,比如,不能使圖片中的重要像素拉伸,不能使內(nèi)容區(qū)域受到拉伸的影響,我們就可以使用 .9.png 圖來實現(xiàn)。
要使用 .9.png ,必須先得創(chuàng)建 .9.png 圖片,androidSDK給我們提供了的工具就包含 .9.png 文件的創(chuàng)建和修改工具。雙擊 SDK安裝目錄 oolsdraw9patch.bat ,就會打開下圖所示的窗口。
下面是一個例子:
Button屬性設置:
如果我們選擇的內(nèi)容區(qū)域偏差太大,可能就不會顯示出text值 BUTTON 。
好了,這篇文章寫的有點多了,剩下的內(nèi)容放在 下篇文章 記錄吧。
內(nèi)容提要:
解決方案-支持各種屏幕密度
解決方案-實施自適應用戶界面流程
未完待續(xù)