Android屏幕適配基本概念

目錄

一、為什么要適配

由于Android系統的開放性,任何用戶、開發者、硬件廠商、運營商都可以對Android系統和硬件進行定制,修改成他們想要的樣子。 那么這種“碎片化”到達什么程度呢?

img

以上每一個矩形都代表一種機型,且它們屏幕尺寸、屏幕分辨率大相徑庭。隨著Android設備的增多,設備碎片化、系統碎片化、屏幕尺寸碎片化、屏幕碎片化的程度也在不斷加深。

備注:

  1. Android系統碎片化:基于Google原生系統,小米定制的MIUI、魅族定制的flyme、華為定制的EMUI等等;
  2. Android機型屏幕尺寸碎片化:5寸、5.5寸、6寸等等;
  3. Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920等;

當Android系統、屏幕尺寸、屏幕密度出現碎片化的時候,就很容易出現同一元素在不同手機上顯示不同的問題。試想一下這么一個場景: 為4.3寸屏幕準備的UI設計圖,運行在5.0寸的屏幕上,很可能在右側和下側存在大量的空白;而5.0寸的UI設計圖運行到4.3寸的設備上,很可能顯示不下。

為了保證用戶獲得一致的用戶體驗效果,使得某一元素在Android不同尺寸、不同分辨率的、不同系統的手機上具備相同的顯示效果,能夠保持界面上的效果一致,我們需要對各種手機屏幕進行適配!

二、基本概念

1、像素(px):

  • 含義:通常所說的像素,就是CCD/CMOS上光電感應元件的數量,一個感光元件經過感光,光電信號轉換,A/D轉換等步驟以后,在輸出的照片上就形成一個點,我們如果把影像放大數倍,會發現這些連續色調其實是由許多色彩相近的小方點所組成,這些小方點就是構成影像的最小單位“像素”(Pixel)。簡而言之,像素就是手機屏幕的最小構成單元

  • 單位:px(pixel),1px = 1像素點 一般情況下UI設計師的設計圖會以px/dp作為統一的計量單位。

2、分辨率:

  • 含義:手機在橫向、縱向上的像素點數總和 一般描述成 寬*高 ,即橫向像素點個數 * 縱向像素點個數(如1080 x 1920)。

  • 單位:px(pixel),1px = 1像素點

3、屏幕尺寸(inch):

  • 含義:手機對角線的物理尺寸

  • 單位 英寸(inch),一英寸大約2.54cm 常見的尺寸有4.7寸、5寸、5.5寸、6寸

4、屏幕像素密度(dpi):

  • 含義:每英寸長所占的像素點數。 例如每英寸內有160個像素點,則其像素密度為160dpi。

  • 單位:dpi(dots per inch)

  • 計算公式: 像素密度 = 像素 / 尺寸 (dpi = px / in)

  • 標準屏幕像素密度(mdpi): 每英寸長度上還有160個像素點(160dpi),即稱為標準屏幕像素密度(mdpi)。

至于為什么標準像素密度要設置為160?

簡單說就是為了可以讓像素取整。 下面是具體解釋

實際開發當中,我們經常需要對這幾個尺寸進行相互轉換(比如先在某個分辨率下完成設計,然后縮放到其他尺寸微調后輸出),一般按照 dpi 之間的比例即 2:1.5:1:0.75   來給界面中的元素來進行尺寸定義。

也就是說如果以 160 dpi 作為基準的話,只要尺寸的 DP 是 4 的公倍數,XHDPI 下乘以 2,HDPI 下乘以 1.5,LDPI 下乘以 0.75 即可滿足所有尺寸下都是整數 pixel 。

但假設以 240 dpi 作為標準,那需要 DP 是 3 的公倍數,XHDPI 下乘以 1.333,MDPI 下乘以 0.666 ,LDPI 下除以 2

而以 LDPI 和 XHDPI 為基準就更復雜了,所以選擇 160 dpi

密度類型 代表的分辨率(PX) 屏幕像素密度(DPI)
低密度(ldpi) 240 x 320 120
中密度(mdpi) 320 x 480 160
高密度(hdpi) 480 x 800 240
超高密度(xhdpi) 720 x 1280 320
超超高密度(xxhdpi) 1080 x 1920 480

屏幕尺寸、分辨率、像素密度三者關系

一部手機的分辨率是寬x高,屏幕大小是以寸為單位,那么三者的關系是:

img

假設一部手機的分辨率是1080x1920(px),屏幕大小是5寸

img

5、密度無關像素(dp):

  • 含義:density-independent pixel,叫dp或dip,與終端上的實際物理像素點無關

  • 單位:dp,可以保證在不同屏幕像素密度的設備上顯示相同的效果,是安卓特有的長度單位。

  • 場景例子:假如同樣都是畫一條長度是屏幕一半的線,如果使用px作為計量單位,那么在480x800分辨率手機上設置應為240px;在320x480的手機上應設置為160px,二者設置就不同了;如果使用dp為單位,在這兩種分辨率下,160dp都顯示為屏幕一半的長度。

  • dp與px的轉換:1dp = (dpi / 160 ) * 1px;

密度類型 代表的分辨率(PX) 屏幕密度(DPI) 換算
低密度(ldpi) 240 x 320 120 1dp = 0.75px
中密度(mdpi) 320 x 480 160 1dp=1px
高密度(hdpi) 480 x 800 240 1dp=1.5px
超高密度(xhdpi) 720 x 1280 320 1dp=2px
超超高密度(xxhdpi) 1080 x 1920 480 1dp=3px

6、獨立比例像素(sp):

含義:scale-independent pixel,叫sp或sip

單位:sp,字體大小專用單位 Android開發時用此單位設置文字大小,可根據字體大小首選項進行縮放; 推薦使用12sp、14sp、18sp、22sp作為字體大小,不推薦使用奇數和小數,容易造成精度丟失,12sp以下字體太小。

7、sp 與 dp 的區別:

dp只跟屏幕的像素密度有關;

sp和dp很類似但唯一的區別是,Android系統允許用戶自定義文字尺寸大小(小、正常、大、超大等等),當文字尺寸是“正常”時1sp=1dp=0.00625英寸,而當文字尺寸是“大”或“超大”時,1sp>1dp=0.00625英寸。類似我們在windows里調整字體尺寸以后的效果——窗口大小不變,只有文字大小改變。

追到android源碼,發現系統內部用applyDimension() (路徑:android.util.TypedValue.applyDimension())將所有單位都轉換成px 再處理:

/*
 *
 * @param unit The unit to convert from.
 * @param value The value to apply the unit to.
 * @param metrics Current display metrics to use in the conversion -- 
 *                supplies display density and scaling information.
 * 
 * @return The complex floating point value multiplied by the appropriate 
 * metrics depending on its unit. 
 */
 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;
 }
?
 可以發現dp和sp的區別在于density和scaledDensity兩個值上;
?
 /**
 * The logical density of the display.  This is a scaling factor for the
 * Density Independent Pixel unit, where one DIP is one pixel on an
 * approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen), 
 * providing the baseline of the system's display. Thus on a 160dpi screen 
 * this density value will be 1; on a 120 dpi screen it would be .75; etc.
 *
 * <p>This value does not exactly follow the real screen size (as given by 
 * {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of
 * the overall UI in steps based on gross changes in the display dpi.  For 
 * example, a 240x320 screen will have a density of 1 even if its width is 
 * 1.8", 1.3", etc. However, if the screen resolution is increased to 
 * 320x480 but the screen size remained 1.5"x2" then the density would be 
 * increased (probably to 1.5).
 *
 * @see #DENSITY_DEFAULT
 */
 public float density;
?
 /**
 * A scaling factor for fonts displayed on the display.  This is the same
 * as {@link #density}, except that it may be adjusted in smaller
 * increments at runtime based on a user preference for the font size.
 */
 public float scaledDensity;

8.區分dpi、dp、dip、px、density、分辨率

  • dpi:dots per inch , 直接來說就是一英寸多少個像素點。常見取值 120,160,240。我一般稱作像素密度,簡稱密度

  • density:可以理解為像素密度,手機屏幕dpi與標準mdpi(160dpi)的比值,比如160dpi的手機,density=1,440dpi的手機,density=2.75

  • dp/dip:density-independent pixels 密度無關像素,就是Google工程師們給android定義的一個長度單位,使用這種長度單位,可以使界面元素在不同密度(dpi)的屏幕上保持近似的物理尺寸大小

  • px:pixel 像素,屏幕上顯示元素的最小單位,比如屏幕分辨率1920*1080 px

  • 分辨率:屏幕寬高的像素 比如:1920*1080

9.px、dpi、density各單位的計算

Metrics

在android里面,獲取一個窗口的metrics,里面有這么幾個值

metrics.densityDpi;
metrics.density; 

densityDpi : 就是我們常說的dpi,一英寸占多數像素。

density:密度(density=dpi/160) 常見取值1.0 1.5 。

計算dpi

假設一部手機屏幕為4英寸,分辨率為800*480,計算dpi

dpi是指每英寸長所占的像素數量

4英寸是指屏幕對角線長度為4寸

分辨率高800px、寬480px

那么根據勾股定理可以求得對角線的像素數量

(800平方+480平方)開根號 = 屏幕對角線像素數量

屏幕對角線像素數量 / 4 = dpi

800平方 + 480平方 = 870400

870400開方 = 932.952

932.952 / 4 = 233 (dpi)

也就是說這部手機的dpi是233,接近hdpi

dp與px換算

為什么要知道這個呢? 因為針對不同的手機dp與px的換算大小是不一樣的,我們有必要知道是什么決定了他們的大小

換算公式如下:

1 = dpi/160

(dp) (px)

1是指1dp

160是標準密度,也就是mdpi

所以我們能看出來,當dpi為160的時候 1dp=1px,dpi為240(hdpi)時,1dp=1.5px

我們再將這個公式變一下,我們知道density=(dpi/160),是不是和上邊的公式很像,這個公式就可以變為

density*dp = px

可以理解為dp乘上密度就是px

三、適配方案

屏幕適配問題的本質是使得布局、布局組件在Android不同尺寸、不同分辨率的手機上具備相同的顯示效果,下面我將分幾個方面來談談如何去適配。

3.1 關于布局組件的適配:

3.1.1 避免使用像素(px)指定尺寸

由于各種屏幕的像素密度都有所不同,因此相同數量的像素在不同設備上的實際大小也會有所差異,這樣使用像素(px)定義布局尺寸就會產生問題。 因此,請務必使用密度無關像素 dp 或獨立比例像素 sp 單位指定尺寸。

備注:在生產過程中,廠家不會完全按照屏幕密度標準去生產Android設備,會在Google的標準周圍浮動變化,或是偏離Google的屏幕密度標準比較大,再加上理論計算(開方)造成的誤差,實際上使用dp作為單位是不能完完全全的完成適配操作。

3.1.2 使用相對布局或線性布局,不要使用絕對布局

對于線性布局(Linearlayout)、相對布局(RelativeLayout)、幀布局(FrameLayout)、絕對布局(AbsoluteLayout)以及新增的加強版幀布局(CoordinatorLayout)需要根據需求進行選擇,沒有絕對而言。 ? 但因為RelativeLayout講究的是相對位置,即使屏幕的大小改變,視圖之前的相對位置都不會變化,與屏幕大小無關,靈活性很強,而LinearLayout法準確地控制子視圖之間的位置關系,只能簡單的一個挨著一個地排列,所以,對于屏幕適配來說,使用相對布局(RelativeLayout)將會是更好的解決方案,至于絕對布局由于適配性極差,所以極少使用。

3.1.3 使用wrap_content、match_parent、權重

使用 “wrap_content” 和 “match_parent” 尺寸值而不是硬編碼的尺寸,系統會自動計算相應的數值,視圖就會相應地使用自身所需的空間或填滿可用空間,讓布局正確適應各種屏幕尺寸和屏幕方向,組件的權重比同理。

3.1.4 使用minWidth、minHeight、lines等屬性

很多時候我們顯示的數據都是由后臺返回的,再由我們加工處理后去適配我們的組件,這些數據的長度我們是無法確定的,而正常情況下我們構思的布局都僅是適用于理想的情況下,為了保證界面的對齊、數據顯示完整等等的原因,我們需要在構思布局時增加對組件最小寬高度、行數等屬性的設置,確保在特殊的數據下不會破壞我們的整體布局。

3.1.5 使用dimens

組件的長寬我們可以通過dimens來定義,不同的屏幕尺寸可以定義不同的數值,或者是不同的語言顯示我們也可以定義不同的數值,因為翻譯后的長度一般都不會跟中文的一致。

3.2 成熟的適配框架

3.2.1 生成多套Dimens適配

最常用效果最好的適配方案

3.2.2 針對density轉換px適配(今日頭條的適配方案)

最便捷的適配方案

AndroidAutoSize

https://github.com/JessYanCoding/AndroidAutoSize

http://www.lxweimin.com/p/4aa23d69d481

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容