項目屏幕適配

一. 爲什麼要屏幕適配;
2012年到2014年支持Android設備的種類從3997增長到18796。同時各大廠商定製的屏幕尺寸也非常多。這將非常不利於我們進行屏幕適配。這要求我們必須掌握屏幕適配技能,以便使我們的app可以適用於不同屏幕尺寸的設備上。
二。屏幕尺寸
屏幕尺寸指屏幕的對角線的長度,單位是英寸,1英寸=2.54釐米
比如常見的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等
屏幕分辨率
屏幕分辨率是指在橫縱向上的像素點數,單位是px,1px=1個像素點。一般以縱向像素*橫向像素,如1960*1080。

以谷歌的標準,按安卓屏幕寬度爲例,一般來說480px對應的density是1.5(也就是hdpi)對應320dp,720px對應的density是2.0(也就是xhdpi)對應360dp,1080px對應的density是3.0(也就是xxhdpi)對應360dp;
如果非要拿屏幕ppi說事的話,就是這樣,以160ppi爲基準,160ppi對應的density是1.0,240ppi對應的density是1.5,320ppi對應的density是2.0…
這些術語都是指屏幕的分辨率。
VGA:Video Graphics Array,即:顯示繪圖矩陣,相當於640×480 像素;
HVGA:Half-size VGA,即:VGA的一半,分辨率爲480×320,像三星蓋世Ace S5830就是使用這分辨率;
QVGA:Quarter VGA,即:VGA的四分之一,分辨率爲320×240,一般用於小屏手機 像三星蓋世Mini S5570就是使用這分辨率;
WQVGA:Wide Quarter VGA,即:擴大的QVGA,分辨率比QVGA高,比VGA低,一般是:400×240,480×272;
WVGA:Wide Video Graphics Array,即:擴大的VGA,分辨率爲800×480像素,像三星i9000就是使用這分辨率;
FWVGA:Full Wide VGA ,數碼產品屏幕材質的一種,VGA的另一種形式,比WVGA分辨率高,別名 : Full Wide VGA, ,其分辨 率爲854×480象素(16:9)。


以下是一些常見的分辨率
標屏
分辨率
寬屏
分辨率
QVGA
320×240
WQVGA
400×240
VGA
640×480
WVGA
800×480
SVGA
800×600
WSVGA
1024×600
XGA
1024×768
WXGA
1280×768/1280×800/1280*960
SXGA
1280×1024
WXGA+
1440×900
SXGA+
1400×1050
WSXGA+
1680×1050
UXGA
1600×1200
WUXGA
1920×1200
QXGA
2048×1536
WQXGA
2560×1536


VGA
640*480 (Video Graphics Array)
-
QVGA
320*240 (Quarter VGA)
-
HVGA
480*320 (Half-size VGA)
mdpi
SVGA
800*600 (Super VGA)
-
5:3
尺寸
對應分辨率
WVGA
800*480 (Wide VGA)
hdpi
16:9
尺寸
對應分辨率
FWVGA
854*480 (Full Wide VGA)
hdpi
HD
1920*1080 High Definition
-
QHD
960*540
hdpi
720p
1280*720
xhdpi
1080p
1920*1080
xxhdpi
屏幕像素密度
屏幕像素密度是指每英寸上的像素點數,單位是dpi,即“dot per inch”的縮寫。屏幕像素密度與屏幕尺寸和屏幕分辨率有關,在單一變化條件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。
dp、dip、dpi、sp、px


1.px (pixels)像素 – 是像素,就是屏幕上實際的像素點單位。

 dip或dp (device independent pixels)設備獨立像素, 與設備屏幕有關(密度無關像素)。
理解一下密度無關像素:
480*320
160dpi (1px=1dp)
800*480
240dpi (1px=??dp)

dp = px * (dpi/160);

 sp (scaled pixels — best for text size):類似dp, 主要處理字體的大小。
dpi(dot per inch):屏幕像素密度,每英寸多少像素
density:density表示每英寸有多少個像素點(邏輯值),它的單位是dpi
DPI的計算: 對角屏幕像素點數/屏幕尺寸(4.95);
dpi=445
Nexus 5(1920*1080)

不同像素密度區分

1.2 分辨率對應DPI
"HVGA    mdpi"
"WVGA   hdpi "
"FWVGA hdpi "
"QHD      hdpi "
"720P     xhdpi"
"1080P   xxhdpi "
Android design

屏幕適配在麼寫:
1。wrap_content match-parent
weight (原有寬度+剩餘空間佔的百分比)
2/3L=L+(L-2L)*1/3L

2。使用相對佈局,禁止使用相對佈局或者寫死值
3。使用限定符 (large)
使用最小寬度限定符,
使用佈局別名,
使用屏幕方向限定符
4。使用自動拉伸圖片
百分比適配
Percent Support Lib



有條理的整理
1. 什麼是屏幕尺寸、屏幕分辨率、屏幕像素密度?
屏幕尺寸是指屏幕對角線的長度。單位是英寸,1英寸=2.54釐米
屏幕分辨率是指在橫縱向上的像素點數,單位是px,1px=1像素點,一般是縱向像素橫向像素,如1280×720
屏幕像素密度(dpi)是指每英寸上的像素點數,單位是dpi,即“dot per inch”的縮寫,像素密度和屏幕尺寸和屏幕分辨率有關

屏幕像素密度計算公式

例如:計算Nexus5的屏幕像素密度:
屏幕尺寸:4.95inch、分辨率:1920×1080,屏幕像素密度:445


和官方給出的一樣,說明我們計算正確。
2. 什麼是dp、dip、dpi、sp、px?之間的關係是什麼?
dip:Density Independent Pixels(密度無關像素)的縮寫。以160dpi爲基準,1dp=1px
dp:dip
dpi:屏幕像素密度的單位,“dot per inch”的縮寫
px:像素,物理上的絕對單位
sp:Scale-Independent Pixels的縮寫,可以根據文字大小首選項自動進行縮放。Google推薦我們使用12sp以上的大小,通常可以使用12sp,14sp,18sp,22sp,最好不要使用奇數和小數。

dp的特點

說明:如果A設備的參數爲480×320,160dpi,B設置的參數爲800×480,240dpi。我們要畫出一條和屏幕寬度一樣長的直線,如果使用px作爲單位,必須在A設備上設置爲320px,在B設備上設置480px。但是如果我們使用dp作爲單位,由於以160dpi爲基準,1dp=1px,所以A設備上設置爲320dp就等於屏幕寬度(320px),在B設備上設置爲320dp就等於320×(240/160)=480px,即B設備的屏幕寬度。這樣,使用dp作爲單位就可以實現簡單的屏幕適配。這知識一種巧合,也有B設備的像素密度不是這樣剛剛好的,就需要我們運用別的屏幕適配技術。
3. 什麼是mdpi、hdpi、xdpi、xxdpi、xxxdpi?如何計算和區分?
用於區分不同的像素密度。
名稱
像素密度範圍
圖片大小
mdpi
120dp~160dp
48×48px
hdpi
160dp~240dp
72×72px
xhdpi
240dp~320dp
96×96px
xxhdpi
320dp~480dp
144×144px
xxxhdpi
480dp~640dp
192×192px


在Google官方開發文檔中,說明了 mdpi:hdpi:xhdpi:xxhdpi:xxxhdpi=2:3:4:6:8 的尺寸比例進行縮放。例如,一個圖標的大小爲48×48dp,表示在mdpi上,實際大小爲48×48px,在hdpi像素密度上,實際尺寸爲mdpi上的1.5倍,即72×72px,以此類推。
二. 解決方案-支持各種屏幕尺寸
我們可以通過以下幾種方式來支持各種屏幕尺寸:
1. 使用wrap_content、math_parent、weight
wrap_content:根據控件的內容設置控件的尺寸
math_parent:根據父控件的尺寸大小設置控件的尺寸
weight:權重,在線性佈局中可以使用weight屬性設置控件所佔的比例
例如,我們要實現下圖所顯示的效果:當屏幕尺寸改變時,new reader控件兩邊的控件大小不變,new reader控件會佔完剩餘的空間。


實現:通過給new reader控件設置屬性:android:layout_width="wrap_content"android:layout_weight="1",兩邊兩個控件爲固定大小,android:layout_weight="0"
具體佈局文件如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:layout_width="80dp" android:layout_height="80dp" android:layout_weight="0" android:background="#028330"/> <TextView android:layout_width="wrap_content" android:layout_height="80dp" android:text="newreader" android:textSize="22sp" android:layout_weight="1"/> <TextView android:layout_width="160dp" android:layout_height="80dp" android:text="Politics" android:textSize="18sp" android:layout_weight="0" android:background="#028330"/></LinearLayout>
小插曲:關於android:layout_weight屬性
公式:所佔寬度=原來寬度+剩餘空間所佔百分比的寬度
一般情況,我們都是設置要進行比例分配的方向的寬度爲0dp,然後再用權重進行分配。如下:
<Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button1" /><Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="Button2" />
效果爲:

寬度爲0dp時,所佔比例

設屏幕寬度爲L,
根據公式,
button1寬度=0+L×1/(1+2)=1/3L
button2寬度=0+L×2/(1+2)=2/3L
但如果設置爲match_parent
<Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button1" /><Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="2" android:text="Button2" />
效果爲:

寬度爲match_parent時,所佔比例
button1寬度=L+(L-2L)×1/3=2/3L
button2寬度=L+(L-2L)×2/3=1/3L
當然,還有其他的方式,都可以運用此公式進行計算。
在實際開發中,我們一般使用0dp的方式,而不使用其他方式。
2. 使用相對佈局,禁用絕對佈局
簡單的佈局一般都使用線性佈局,而略微複雜點的佈局,我們使用相對佈局,大多數時候,我們都是使用這兩種佈局的嵌套。
我們使用相對佈局的原因是,相對佈局能在各種尺寸的屏幕上保持控件間的相對位置。
3. 使用限定符
  • 使用尺寸限定符
當我們要在大屏幕上顯示不同的佈局,就要使用large限定符。例如,在寬的屏幕左邊顯示列表右邊顯示列表項的詳細信息,在一般寬度的屏幕只顯示列表,不顯示列表項的詳細信息,我們就可以使用large限定符。
res/layout/main.xml 單面板:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 列表 --> <fragment android:id="@+id/headlines" android:layout_height="fill_parent" android:name="com.example.android.newsreader.HeadlinesFragment" android:layout_width="match_parent" /></LinearLayout>
res/layout-large/main.xml 雙面板:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> <!-- 列表 --> <fragment android:id="@+id/headlines" android:layout_height="fill_parent" android:name="com.example.android.newsreader.HeadlinesFragment" android:layout_width="400dp" android:layout_marginRight="10dp"/> <!-- 列表項的詳細信息 --> <fragment android:id="@+id/article" android:layout_height="fill_parent" android:name="com.example.android.newsreader.ArticleFragment" android:layout_width="fill_parent" /></LinearLayout>
如果這個程序運行在屏幕尺寸大於7inch的設備上,系統就會加載res/layout-large/main.xml 而不是res/layout/main.xml,在小於7inch的設備上就會加載res/layout/main.xml
需要注意的是,這種通過large限定符分辨屏幕尺寸的方法,適用於android3.2之前。在android3.2之後,爲了更精確地分辨屏幕尺寸大小,Google推出了最小寬度限定符。
  • 使用最小寬度限定符
最小寬度限定符的使用和large基本一致,只是使用了具體的寬度限定。
res/layout/main.xml,單面板(默認)佈局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/headlines" android:layout_height="fill_parent" android:name="com.example.android.newsreader.HeadlinesFragment" android:layout_width="match_parent" /></LinearLayout>
res/layout-sw600dp/main.xml,雙面板佈局: Small Width 最小寬度
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> <fragment android:id="@+id/headlines" android:layout_height="fill_parent" android:name="com.example.android.newsreader.HeadlinesFragment" android:layout_width="400dp" android:layout_marginRight="10dp"/> <fragment android:id="@+id/article" android:layout_height="fill_parent" android:name="com.example.android.newsreader.ArticleFragment" android:layout_width="fill_parent" /></LinearLayout>
這種方式是不區分屏幕方向的。這種最小寬度限定符適用於android3.2之後,所以如果要適配android全部的版本,就要使用large限定符和sw600dp文件同時存在於項目res目錄下。
這就要求我們維護兩個相同功能的文件。爲了避免繁瑣操作,我們就要使用佈局別名。
  • 使用佈局別名
res/layout/main.xml: 單面板佈局
res/layout-large/main.xml: 多面板佈局
res/layout-sw600dp/main.xml: 多面板佈局
由於後兩個文具文件一樣,我們可以用以下兩個文件代替上面三個佈局文件:
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:
<resources> <item name="main" type="layout">@layout/main</item></resources>
Android3.2之前的平板佈局
res/values-large/layout.xml:
<resources> <item name="main" type="layout">@layout/main_twopanes</item></resources>
Android3.2之後的平板佈局
res/values-sw600dp/layout.xml:
<resources> <item name="main" type="layout">@layout/main_twopanes</item></resources>
這樣就有了main爲別名的佈局。
在activity中setContentView(R.layout.main);
這樣,程序在運行時,就會檢測手機的屏幕大小,如果是平板設備就會加載res/layout/main_twopanes.xml,如果是手機設備,就會加載res/layout/main.xml 。我們就解決了只使用一個佈局文件來適配android3.2前後的所有平板設備。
  • 使用屏幕方向限定符
如果我們要求給橫屏、豎屏顯示的佈局不一樣。就可以使用屏幕方向限定符來實現。
例如,要在平板上實現橫豎屏顯示不用的佈局,可以用以下方式實現。
res/values-sw600dp-land/layouts.xml:橫屏
<resources> <item name="main" type="layout">@layout/main_twopanes</item></resources>
res/values-sw600dp-port/layouts.xml:豎屏
<resources> <item name="main" type="layout">@layout/main</item></resources>
4. 使用自動拉伸位圖
自動拉伸位圖,即android下特有的.9.png圖片格式。
當我們需要使圖片在拉伸後還能保持一定的顯示效果,比如,不能使圖片中的重要像素拉伸,不能使內容區域受到拉伸的影響,我們就可以使用.9.png圖來實現。

AutoLayout 屏幕適配:







發佈了38 篇原創文章 · 獲贊 6 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章