前言
Android的屏幕適配一直以來都在折磨著我們Android開發(fā)者,本文將結(jié)合:
- Google的官方權(quán)威適配文檔
- 郭霖: Android官方提供的支持不同屏幕大小的全部方法
- Stormzhang:Android 屏幕適配
- 鴻洋:Android 屏幕適配方案
- 凱子: Android屏幕適配全攻略(最權(quán)威的官方適配指導(dǎo))
- 自身的思考&實(shí)踐
給你帶來一種全新杜窄、全面而邏輯清晰的Android屏幕適配思路肠骆,只要你認(rèn)真閱讀,保證你能解決Android的屏幕適配問題塞耕!
目錄
定義
使得某一元素在Android不同尺寸蚀腿、不同分辨率的手機(jī)上具備相同的顯示效果
相關(guān)重要概念
屏幕尺寸
- 含義:手機(jī)對(duì)角線的物理尺寸
- 單位:英寸(inch),1英寸=2.54cm
Android手機(jī)常見的尺寸有5寸扫外、5.5寸莉钙、6寸等等
屏幕分辨率
- 含義:手機(jī)在橫向、縱向上的像素點(diǎn)數(shù)總和
- 一般描述成屏幕的"寬x高”=AxB
- 含義:屏幕在橫向方向(寬度)上有A個(gè)像素點(diǎn)筛谚,在縱向方向
(高)有B個(gè)像素點(diǎn)- 例子:1080x1920磁玉,即寬度方向上有1080個(gè)像素點(diǎn),在高度方向上有1920個(gè)像素點(diǎn)
- 單位:px(pixel)刻获,1px=1像素點(diǎn)
UI設(shè)計(jì)師的設(shè)計(jì)圖會(huì)以px作為統(tǒng)一的計(jì)量單位
- Android手機(jī)常見的分辨率:320x480蜀涨、480x800瞎嬉、720x1280、1080x1920
屏幕像素密度
- 含義:每英寸的像素點(diǎn)數(shù)
- 單位:dpi(dots per ich)
假設(shè)設(shè)備內(nèi)每英寸有160個(gè)像素厚柳,那么該設(shè)備的屏幕像素密度=160dpi
- 安卓手機(jī)對(duì)于每類手機(jī)屏幕大小都有一個(gè)相應(yīng)的屏幕像素密度:
密度類型 | 代表的分辨率(px) | 屏幕像素密度(dpi) |
---|---|---|
低密度(ldpi) | 240x320 | 120 |
中密度(mdpi) | 320x480 | 160 |
高密度(hdpi) | 480x800 | 240 |
超高密度(xhdpi) | 720x1280 | 320 |
超超高密度(xxhdpi) | 1080x1920 | 480 |
屏幕尺寸氧枣、分辨率、像素密度三者關(guān)系
一部手機(jī)的分辨率是寬x高别垮,屏幕大小是以寸為單位便监,那么三者的關(guān)系是:
數(shù)學(xué)不太差的人應(yīng)該能懂.....吧?
不懂沒關(guān)系碳想,在這里舉個(gè)例子
假設(shè)一部手機(jī)的分辨率是1080x1920(px)烧董,屏幕大小是5寸,問密度是多少胧奔?
解:請(qǐng)直接套公式
密度無關(guān)像素
- 含義:density-independent pixel逊移,叫dp或dip,與終端上的實(shí)際物理像素點(diǎn)無關(guān)龙填。
- 單位:dp胳泉,可以保證在不同屏幕像素密度的設(shè)備上顯示相同的效果
- Android開發(fā)時(shí)用dp而不是px單位設(shè)置圖片大小袜匿,是Android特有的單位
- 場(chǎng)景:假如同樣都是畫一條長(zhǎng)度是屏幕一半的線帖旨,如果使用px作為計(jì)量單位,那么在480x800分辨率手機(jī)上設(shè)置應(yīng)為240px冤竹;在320x480的手機(jī)上應(yīng)設(shè)置為160px宿礁,二者設(shè)置就不同了案铺;如果使用dp為單位,在這兩種分辨率下梆靖,160dp都顯示為屏幕一半的長(zhǎng)度控汉。
- dp與px的轉(zhuǎn)換
因?yàn)閡i設(shè)計(jì)師給你的設(shè)計(jì)圖是以px為單位的,Android開發(fā)則是使用dp作為單位的涤姊,那么我們需要進(jìn)行轉(zhuǎn)換:
密度類型 | 代表的分辨率(px) | 屏幕密度(dpi) | 換算(px/dp) | 比例 |
---|---|---|---|---|
低密度(ldpi) | 240x320 | 120 | 1dp=0.75px | 3 |
中密度(mdpi) | 320x480 | 160 | 1dp=1px | 4 |
高密度(hdpi) | 480x800 | 240 | 1dp=1.5px | 6 |
超高密度(xhdpi) | 720x1280 | 320 | 1dp=2px | 8 |
超超高密度(xxhdpi) | 1080x1920 | 480 | 1dp=3px | 12 |
在Android中暇番,規(guī)定以160dpi(即屏幕分辨率為320x480)為基準(zhǔn):1dp=1px
獨(dú)立比例像素
- 含義:scale-independent pixel嗤放,叫sp或sip
- 單位:sp
- Android開發(fā)時(shí)用此單位設(shè)置文字大小思喊,可根據(jù)字體大小首選項(xiàng)進(jìn)行縮放
- 推薦使用12sp、14sp次酌、18sp恨课、22sp作為字體設(shè)置的大小,不推薦使用奇數(shù)和小數(shù)岳服,容易造成精度的丟失問題剂公;小于12sp的字體會(huì)太小導(dǎo)致用戶看不清
請(qǐng)把上面的概念記住,因?yàn)橄旅嬷v解都會(huì)用到吊宋!
為什么要進(jìn)行Android屏幕適配
由于Android系統(tǒng)的開放性纲辽,任何用戶、開發(fā)者、OEM廠商拖吼、運(yùn)營(yíng)商都可以對(duì)Android進(jìn)行定制鳞上,于是導(dǎo)致:
- Android系統(tǒng)碎片化:小米定制的MIUI、魅族定制的flyme吊档、華為定制的EMUI等等
當(dāng)然都是基于Google原生系統(tǒng)定制的
- Android機(jī)型屏幕尺寸碎片化:5寸篙议、5.5寸、6寸等等
- Android屏幕分辨率碎片化:320x480怠硼、480x800鬼贱、720x1280、1080x1920
據(jù)友盟指數(shù)顯示香璃,統(tǒng)計(jì)至2015年12月这难,支持Android的設(shè)備共有27796種
當(dāng)Android系統(tǒng)、屏幕尺寸葡秒、屏幕密度出現(xiàn)碎片化的時(shí)候雁佳,就很容易出現(xiàn)同一元素在不同手機(jī)上顯示不同的問題。
試想一下這么一個(gè)場(chǎng)景:
為4.3寸屏幕準(zhǔn)備的UI設(shè)計(jì)圖同云,運(yùn)行在5.0寸的屏幕上糖权,很可能在右側(cè)和下側(cè)存在大量的空白;而5.0寸的UI設(shè)計(jì)圖運(yùn)行到4.3寸的設(shè)備上炸站,很可能顯示不下星澳。
為了保證用戶獲得一致的用戶體驗(yàn)效果:
使得某一元素在Android不同尺寸、不同分辨率的手機(jī)上具備相同的顯示效果
于是旱易,我們便需要對(duì)Android屏幕進(jìn)行適配禁偎。
屏幕適配問題的本質(zhì)
- 使得“布局”、“布局組件”阀坏、“圖片資源”如暖、“用戶界面流程”匹配不同的屏幕尺寸
使得布局、布局組件自適應(yīng)屏幕尺寸忌堂;
根據(jù)屏幕的配置來加載相應(yīng)的UI布局盒至、用戶界面流程
- 使得“圖片資源”匹配不同的屏幕密度
解決方案
- 問題:如何進(jìn)行屏幕尺寸匹配?
- 答:
“布局”匹配
本質(zhì)1:使得布局元素自適應(yīng)屏幕尺寸
- 做法
使用相對(duì)布局(RelativeLayout)士修,禁用絕對(duì)布局(AbsoluteLayout)
開發(fā)中枷遂,我們使用的布局一般有:
- 線性布局(Linearlayout)
- 相對(duì)布局(RelativeLayout)
- 幀布局(FrameLayout)
- 絕對(duì)布局(AbsoluteLayout)
由于絕對(duì)布局(AbsoluteLayout)適配性極差,所以極少使用棋嘲。
對(duì)于線性布局(Linearlayout)酒唉、相對(duì)布局(RelativeLayout)和幀布局(FrameLayout)需要根據(jù)需求進(jìn)行選擇,但要記追幸啤:
- RelativeLayout
布局的子控件之間使用相對(duì)位置的方式排列痪伦,因?yàn)镽elativeLayout講究的是相對(duì)位置侄榴,即使屏幕的大小改變,視圖之前的相對(duì)位置都不會(huì)變化网沾,與屏幕大小無關(guān)牲蜀,靈活性很強(qiáng) - LinearLayout
通過多層嵌套LinearLayout和組合使
用"wrap_content"和"match_parent"已經(jīng)可以構(gòu)建出足夠復(fù)雜的布局。但是LinearLayout無法準(zhǔn)確地控制子視圖之間的位置關(guān)系绅这,只能簡(jiǎn)單的一個(gè)挨著一個(gè)地排列
所以涣达,對(duì)于屏幕適配來說,使用相對(duì)布局(RelativeLayout)將會(huì)是更好的解決方案
本質(zhì)2:根據(jù)屏幕的配置來加載相應(yīng)的UI布局
應(yīng)用場(chǎng)景:需要為不同屏幕尺寸的設(shè)備設(shè)計(jì)不同的布局
- 做法:使用限定符
- 作用:通過配置限定符使得程序在運(yùn)行時(shí)根據(jù)當(dāng)前設(shè)備的配置(屏幕尺寸)自動(dòng)加載合適的布局資源
- 限定符類型:
- 尺寸(size)限定符
- 最小寬度(Smallest-width)限定符
- 布局別名
- 屏幕方向(Orientation)限定符
尺寸(size)限定符
- 使用場(chǎng)景:當(dāng)一款應(yīng)用顯示的內(nèi)容較多证薇,希望進(jìn)行以下設(shè)置:
- 在平板電腦和電視的屏幕(>7英寸)上:實(shí)施“雙面板”模式以同時(shí)顯示更多內(nèi)容
- 在手機(jī)較小的屏幕上:使用單面板分別顯示內(nèi)容
因此度苔,我們可以使用尺寸限定符(layout-large)通過創(chuàng)建一個(gè)文件
res/layout-large/main.xml
來完成上述設(shè)定:
- 讓系統(tǒng)在屏幕尺寸>7英寸時(shí)采用適配平板的雙面板布局
- 反之(默認(rèn)情況下)采用適配手機(jī)的單面板布局
文件配置如下:
- 適配手機(jī)的單面板(默認(rèn))布局: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>
- 適配尺寸>7寸平板的雙面板布局::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>
請(qǐng)注意:
- 兩個(gè)布局名稱均為main.xml,只有布局的目錄名不同:第一個(gè)布局的目錄名為:layout浑度,第二個(gè)布局的目錄名為:layout-large寇窑,包含了尺寸限定符(large)
- 被定義為大屏的設(shè)備(7寸以上的平板)會(huì)自動(dòng)加載包含了large限定符目錄的布局,而小屏設(shè)備會(huì)加載另一個(gè)默認(rèn)的布局
但要注意的是箩张,這種方式只適合Android 3.2版本之前甩骏。
最小寬度(Smallest-width)限定符
- 背景:上述提到的限定符“l(fā)arge”具體是指多大呢?似乎沒有一個(gè)定量的指標(biāo)先慷,這便意味著可能沒辦法準(zhǔn)確地根據(jù)當(dāng)前設(shè)備的配置(屏幕尺寸)自動(dòng)加載合適的布局資源
- 例子:比如說large同時(shí)包含著5寸和7寸饮笛,這意味著使用“l(fā)arge”限定符的話我沒辦法實(shí)現(xiàn)為5寸和7寸的平板電腦分別加載不同的布局
于是,在Android 3.2及之后版本论熙,引入了最小寬度(Smallest-width)限定符
定義:通過指定某個(gè)最小寬度(以 dp 為單位)來精確定位屏幕從而加載不同的UI資源
- 使用場(chǎng)景
你需要為標(biāo)準(zhǔn) 7 英寸平板電腦匹配雙面板布局(其最小寬度為 600 dp)福青,在手機(jī)(較小的屏幕上)匹配單面板布局
解決方案:您可以使用上文中所述的單面板和雙面板這兩種布局,但您應(yīng)使用 sw600dp 指明雙面板布局僅適用于最小寬度為 600 dp 的屏幕脓诡,而不是使用 large 尺寸限定符无午。
- sw xxxdp,即small width的縮寫祝谚,其不區(qū)分方向宪迟,即無論是寬度還是高度,只要大于 xxxdp交惯,就采用次此布局
- 例子:使用了layout-sw 600dp的最小寬度限定符次泽,即無論是寬度還是高度,只要大于600dp商玫,就采用layout-sw 600dp目錄下的布局
代碼展示:
- 適配手機(jī)的單面板(默認(rèn))布局: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>
- 適配尺寸>7寸平板的雙面板布局:res/layout-sw600dp/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>
- 對(duì)于最小寬度≥ 600 dp 的設(shè)備
系統(tǒng)會(huì)自動(dòng)加載 layout-sw600dp/main.xml(雙面板)布局箕憾,否則系統(tǒng)就會(huì)選擇 layout/main.xml(單面板)布局
(這個(gè)選擇過程是Android系統(tǒng)自動(dòng)選擇的)
使用布局別名
設(shè)想這么一個(gè)場(chǎng)景
當(dāng)你需要同時(shí)為Android 3.2版本前和Android 3.2版本后的手機(jī)進(jìn)行屏幕尺寸適配的時(shí)候,由于尺寸限定符僅用于Android 3.2版本前拳昌,最小寬度限定符僅用于Android 3.2版本后,所以這會(huì)帶來一個(gè)問題钠龙,為了很好地進(jìn)行屏幕尺寸的適配炬藤,你需要同時(shí)維護(hù)layout-sw600dp和layout-large的兩套main.xml平板布局御铃,如下:
- 適配手機(jī)的單面板(默認(rèn))布局:res/layout/main.xml
- 適配尺寸>7寸平板的雙面板布局(Android 3.2前):res/layout-large/main.xml
- 適配尺寸>7寸平板的雙面板布局(Android 3.2后)res/layout-sw600dp/main.xml
最后的兩個(gè)文件的xml內(nèi)容是完全相同的,這會(huì)帶來:文件名的重復(fù)從而帶來一些列后期維護(hù)的問題
于是為了要解決這種重復(fù)問題沈矿,我們引入了“布局別名”
還是上面的例子上真,你可以定義以下布局:
- 適配手機(jī)的單面板(默認(rèn))布局:res/layout/main.xml
- 適配尺寸>7寸平板的雙面板布局:res/layout/main_twopanes.xml
然后加入以下兩個(gè)文件,以便進(jìn)行Android 3.2前和Android 3.2后的版本雙面板布局適配:
- res/values-large/layout.xml(Android 3.2之前的雙面板布局)
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
- res/values-sw600dp/layout.xml(Android 3.2及之后的雙面板布局)
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
注:
- 最后兩個(gè)文件有著相同的內(nèi)容羹膳,但是它們并沒有真正去定義布局睡互,它們僅僅只是將main設(shè)置成了@layout/main_twopanes的別名
- 由于這些文件包含 large 和 sw600dp 選擇器,因此陵像,系統(tǒng)會(huì)將此文件匹配到不同版本的>7寸平板上:
a. 版本低于 3.2 的平板會(huì)匹配 large的文件
b. 版本高于 3.2 的平板會(huì)匹配 sw600dp的文件
這樣兩個(gè)layout.xml都只是引用了@layout/main_twopanes就珠,就避免了重復(fù)定義布局文件的情況
屏幕方向(Orientation)限定符
- 使用場(chǎng)景:根據(jù)屏幕方向進(jìn)行布局的調(diào)整
取以下為例子:
- 小屏幕, 豎屏: 單面板
- 小屏幕, 橫屏: 單面板
- 7 英寸平板電腦,縱向:?jiǎn)蚊姘逍延保瑤Р僮鳈?/li>
- 7 英寸平板電腦妻怎,橫向:雙面板,寬泞歉,帶操作欄
- 10 英寸平板電腦逼侦,縱向:雙面板,窄腰耙,帶操作欄
- 10 英寸平板電腦榛丢,橫向:雙面板,寬挺庞,帶操作欄
- 電視涕滋,橫向:雙面板,寬挠阁,帶操作欄
方法是:
- 先定義類別:?jiǎn)?雙面板宾肺、是否帶操作欄、寬/窄
定義在 res/layout/ 目錄下的某個(gè) XML 文件中
- 再進(jìn)行相應(yīng)的匹配:屏幕尺寸(小屏侵俗、7寸锨用、10寸)、方向(橫隘谣、縱)
使用布局別名進(jìn)行匹配
- 在 res/layout/ 目錄下的某個(gè) XML 文件中定義所需要的布局類別
(單/雙面板增拥、是否帶操作欄、寬/窄)
res/layout/onepane.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/onepane_with_bar.xml:(單面板帶操作欄)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:id="@+id/linearLayout1"
android:gravity="center"
android:layout_height="50dp">
<ImageView android:id="@+id/imageView1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/logo"
android:paddingRight="30dp"
android:layout_gravity="left"
android:layout_weight="0" />
<View android:layout_height="wrap_content"
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_weight="1" />
<Button android:id="@+id/categorybutton"
android:background="@drawable/button_bg"
android:layout_height="match_parent"
android:layout_weight="0"
android:layout_width="120dp"
style="@style/CategoryButtonStyle"/>
</LinearLayout>
<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/twopanes.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>
res/layout/twopanes_narrow.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="200dp"
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>
2.使用布局別名進(jìn)行相應(yīng)的匹配
(屏幕尺寸(小屏、7寸码泛、10寸)猾封、方向(橫、縱))
res/values/layouts.xml:(默認(rèn)布局)
<resources>
<item name="main_layout" type="layout">@layout/onepane_with_bar</item>
<bool name="has_two_panes">false</bool>
</resources>
可為resources設(shè)置bool噪珊,通過獲取其值來動(dòng)態(tài)判斷目前已處在哪個(gè)適配布局
res/values-sw600dp-land/layouts.xml
(大屏晌缘、橫向齐莲、雙面板、寬-Andorid 3.2版本后)
<resources>
<item name="main_layout" type="layout">@layout/twopanes</item>
<bool name="has_two_panes">true</bool>
</resources>
res/values-sw600dp-port/layouts.xml
(大屏磷箕、縱向选酗、單面板帶操作欄-Andorid 3.2版本后)
<resources>
<item name="main_layout" type="layout">@layout/onepane</item>
<bool name="has_two_panes">false</bool>
</resources>
res/values-large-land/layouts.xml
(大屏、橫向岳枷、雙面板芒填、寬-Andorid 3.2版本前)
<resources>
<item name="main_layout" type="layout">@layout/twopanes</item>
<bool name="has_two_panes">true</bool>
</resources>
res/values-large-port/layouts.xml
(大屏、縱向空繁、單面板帶操作欄-Andorid 3.2版本前)
<resources>
<item name="main_layout" type="layout">@layout/onepane</item>
<bool name="has_two_panes">false</bool>
</resources>
這里沒有完全把全部尺寸匹配類型的代碼貼出來殿衰,大家可以自己去嘗試把其補(bǔ)充完整
“布局組件”匹配
本質(zhì):使得布局組件自適應(yīng)屏幕尺寸
- 做法
使用"wrap_content"、"match_parent"和"weight“來控制視圖組件的寬度和高度
- "wrap_content"
相應(yīng)視圖的寬和高就會(huì)被設(shè)定成所需的最小尺寸以適應(yīng)視圖中的內(nèi)容- "match_parent"(在Android API 8之前叫作"fill_parent")
視圖的寬和高延伸至充滿整個(gè)父布局- "weight"
1.定義:是線性布局(Linelayout)的一個(gè)獨(dú)特比例分配屬性
2.作用:使用此屬性設(shè)置權(quán)重家厌,然后按照比例對(duì)界面進(jìn)行空間的分配播玖,公式計(jì)算是:控件寬度=控件設(shè)置寬度+剩余空間所占百分比寬幅
具體可以參考這篇文章,講解得非常詳細(xì)
通過使用"wrap_content"饭于、"match_parent"和"weight"來替代硬編碼的方式定義視圖大小&位置蜀踏,你的視圖要么僅僅使用了需要的那邊一點(diǎn)空間,要么就會(huì)充滿所有可用的空間掰吕,即按需占據(jù)空間大小果覆,能讓你的布局元素充分適應(yīng)你的屏幕尺寸
“圖片資源”匹配
本質(zhì):使得圖片資源在不同屏幕密度上顯示相同的像素效果
- 做法:使用自動(dòng)拉伸位圖:Nine-Patch的圖片類型
假設(shè)需要匹配不同屏幕大小,你的圖片資源也必須自動(dòng)適應(yīng)各種屏幕尺寸
使用場(chǎng)景:一個(gè)按鈕的背景圖片必須能夠隨著按鈕大小的改變而改變殖熟。
使用普通的圖片將無法實(shí)現(xiàn)上述功能,因?yàn)檫\(yùn)行時(shí)會(huì)均勻地拉伸或壓縮你的圖片
- 解決方案:使用自動(dòng)拉伸位圖(nine-patch圖片)局待,后綴名是.9.png,它是一種被特殊處理過的PNG圖片菱属,設(shè)計(jì)時(shí)可以指定圖片的拉伸區(qū)域和非拉伸區(qū)域钳榨;使用時(shí),系統(tǒng)就會(huì)根據(jù)控件的大小自動(dòng)地拉伸你想要拉伸的部分
1.必須要使用.9.png后綴名纽门,因?yàn)橄到y(tǒng)就是根據(jù)這個(gè)來區(qū)別nine-patch圖片和普通的PNG圖片的薛耻;
2.當(dāng)你需要在一個(gè)控件中使用nine-patch圖片時(shí),如
android:background="@drawable/button"
系統(tǒng)就會(huì)根據(jù)控件的大小自動(dòng)地拉伸你想要拉伸的部分
”用戶界面流程“匹配
- 使用場(chǎng)景:我們會(huì)根據(jù)設(shè)備特點(diǎn)顯示恰當(dāng)?shù)牟季郑沁@樣做赏陵,會(huì)使得用戶界面流程可能會(huì)有所不同饼齿。
- 例如,如果應(yīng)用處于雙面板模式下蝙搔,點(diǎn)擊左側(cè)面板上的項(xiàng)即可直接在右側(cè)面板上顯示相關(guān)內(nèi)容缕溉;而如果該應(yīng)用處于單面板模式下,點(diǎn)擊相關(guān)的內(nèi)容應(yīng)該跳轉(zhuǎn)到另外一個(gè)Activity進(jìn)行后續(xù)的處理吃型。
本質(zhì):根據(jù)屏幕的配置來加載相應(yīng)的用戶界面流程
- 做法
進(jìn)行用戶界面流程的自適應(yīng)配置:
- 確定當(dāng)前布局
- 根據(jù)當(dāng)前布局做出響應(yīng)
- 重復(fù)使用其他活動(dòng)中的片段
- 處理屏幕配置變化
- 步驟1:確定當(dāng)前布局
由于每種布局的實(shí)施都會(huì)稍有不同证鸥,因此我們需要先確定當(dāng)前向用戶顯示的布局。例如,我們可以先了解用戶所處的是“單面板”模式還是“雙面板”模式敌土。要做到這一點(diǎn)镜硕,可以通過查詢指定視圖是否存在以及是否已顯示出來运翼。
public class NewsReaderActivity extends FragmentActivity {
boolean mIsDualPane;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
View articleView = findViewById(R.id.article);
mIsDualPane = articleView != null &&
articleView.getVisibility() == View.VISIBLE;
}
}
這段代碼用于查詢“報(bào)道”面板是否可用返干,與針對(duì)具體布局的硬編碼查詢相比,這段代碼的靈活性要大得多血淌。
- 步驟2:根據(jù)當(dāng)前布局做出響應(yīng)
有些操作可能會(huì)因當(dāng)前的具體布局而產(chǎn)生不同的結(jié)果矩欠。
例如,在新聞閱讀器示例中悠夯,如果用戶界面處于雙面板模式下癌淮,那么點(diǎn)擊標(biāo)題列表中的標(biāo)題就會(huì)在右側(cè)面板中打開相應(yīng)報(bào)道;但如果用戶界面處于單面板模式下沦补,那么上述操作就會(huì)啟動(dòng)一個(gè)獨(dú)立活動(dòng):
@Override
public void onHeadlineSelected(int index) {
mArtIndex = index;
if (mIsDualPane) {
/* display article on the right pane */
mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
} else {
/* start a separate activity */
Intent intent = new Intent(this, ArticleActivity.class);
intent.putExtra("catIndex", mCatIndex);
intent.putExtra("artIndex", index);
startActivity(intent);
}
}
- 步驟3:重復(fù)使用其他活動(dòng)中的片段
多屏幕設(shè)計(jì)中的重復(fù)模式是指乳蓄,對(duì)于某些屏幕配置,已實(shí)施界面的一部分會(huì)用作面板夕膀;但對(duì)于其他配置虚倒,這部分就會(huì)以獨(dú)立活動(dòng)的形式存在。
例如产舞,在新聞閱讀器示例中魂奥,對(duì)于較大的屏幕,新聞報(bào)道文本會(huì)顯示在右側(cè)面板中易猫;但對(duì)于較小的屏幕耻煤,這些文本就會(huì)以獨(dú)立活動(dòng)的形式存在。
在類似情況下准颓,通彻可以在多個(gè)活動(dòng)中重復(fù)使用相同的 Fragment 子類以避免代碼重復(fù)。例如攘已,在雙面板布局中使用了 ArticleFragment:
<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>
然后又在小屏幕的Activity布局中重復(fù)使用了它 :
ArticleFragment frag = new ArticleFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
- 步驟3:處理屏幕配置變化
如果我們使用獨(dú)立Activity實(shí)施界面的獨(dú)立部分炮赦,那么請(qǐng)注意,我們可能需要對(duì)特定配置變化(例如屏幕方向的變化)做出響應(yīng)贯被,以便保持界面的一致性眼五。
例如,在運(yùn)行 Android 3.0 或更高版本的標(biāo)準(zhǔn) 7 英寸平板電腦上彤灶,如果新聞閱讀器示例應(yīng)用運(yùn)行在縱向模式下看幼,就會(huì)在使用獨(dú)立活動(dòng)顯示新聞報(bào)道;但如果該應(yīng)用運(yùn)行在橫向模式下幌陕,就會(huì)使用雙面板布局诵姜。
也就是說,如果用戶處于縱向模式下且屏幕上顯示的是用于閱讀報(bào)道的活動(dòng)搏熄,那么就需要在檢測(cè)到屏幕方向變化(變成橫向模式)后執(zhí)行相應(yīng)操作棚唆,即停止上述活動(dòng)并返回主活動(dòng)暇赤,以便在雙面板布局中顯示相關(guān)內(nèi)容:
public class ArticleActivity extends FragmentActivity {
int mCatIndex, mArtIndex;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
// If should be in two-pane mode, finish to return to main activity
if (getResources().getBoolean(R.bool.has_two_panes)) {
finish();
return;
}
...
}
通過上面一系列步驟,我們就完全可以建立一個(gè)可以根據(jù)用戶界面配置進(jìn)行自適應(yīng)的應(yīng)用程序App了宵凌。
總結(jié)
經(jīng)過上面的介紹鞋囊,對(duì)于屏幕尺寸大小適配問題應(yīng)該是不成問題了。
解決方案
- 問題:如何進(jìn)行屏幕密度匹配瞎惫?
- 答:
“布局控件”匹配
本質(zhì):使得布局組件在不同屏幕密度上顯示相同的像素效果
- 做法1:使用密度無關(guān)像素
由于各種屏幕的像素密度都有所不同溜腐,因此相同數(shù)量的像素在不同設(shè)備上的實(shí)際大小也有所差異,這樣使用像素(px)定義布局尺寸就會(huì)產(chǎn)生問題瓜喇。
因此挺益,請(qǐng)務(wù)必使用密度無關(guān)像素 dp 或**獨(dú)立比例像素 sp **單位指定尺寸。 - 相關(guān)概念介紹
密度無關(guān)像素 - 含義:density-independent pixel乘寒,叫dp或dip望众,與終端上的實(shí)際物理像素點(diǎn)無關(guān)。
- 單位:dp伞辛,可以保證在不同屏幕像素密度的設(shè)備上顯示相同的效果
- Android開發(fā)時(shí)用dp而不是px單位設(shè)置圖片大小烂翰,是Android特有的單位
- 場(chǎng)景:假如同樣都是畫一條長(zhǎng)度是屏幕一半的線,如果使用px作為計(jì)量單位始锚,那么在480x800分辨率手機(jī)上設(shè)置應(yīng)為240px刽酱;在320x480的手機(jī)上應(yīng)設(shè)置為160px,二者設(shè)置就不同了瞧捌;如果使用dp為單位棵里,在這兩種分辨率下,160dp都顯示為屏幕一半的長(zhǎng)度姐呐。
- dp與px的轉(zhuǎn)換
因?yàn)閡i給你的設(shè)計(jì)圖是以px為單位的殿怜,Android開發(fā)則是使用dp作為單位的,那么該如何轉(zhuǎn)換呢曙砂?
| 密度類型 | 代表的分辨率(px) | 屏幕密度(dpi)|換算(px/dp) |比例|
| ------------- |:-------------:| -------------:| -------------:|
| 低密度(ldpi) | 240x320 | 120 |1dp=0.75px|3|
| 中密度(mdpi) | 320x480 | 160 |1dp=1px|4|
| 高密度(hdpi) | 480x800 | 240|1dp=1.5px|6|
| 超高密度(xhdpi) | 720x1280 | 320|1dp=2px|8|
| 超超高密度(xxhdpi) | 1080x1920 | 480 |1dp=3px|12|
在Android中头谜,規(guī)定以160dpi(即屏幕分辨率為320x480)為基準(zhǔn):1dp=1px
獨(dú)立比例像素
- 含義:scale-independent pixel,叫sp或sip
- 單位:sp
- Android開發(fā)時(shí)用此單位設(shè)置文字大小鸠澈,可根據(jù)用戶的偏好文字大小/字體大小首選項(xiàng)進(jìn)行縮放
- 推薦使用12sp柱告、14sp、18sp笑陈、22sp作為字體設(shè)置的大小际度,不推薦使用奇數(shù)和小數(shù),容易造成精度的丟失問題涵妥;小于12sp的字體會(huì)太小導(dǎo)致用戶看不清
所以乖菱,為了能夠進(jìn)行不同屏幕像素密度的匹配,我們推薦:
- 使用dp來代替px作為控件長(zhǎng)度的統(tǒng)一度量單位
- 使用sp作為文字的統(tǒng)一度量單位
可是,請(qǐng)看以下一種場(chǎng)景:
Nexus5的總寬度為360dp窒所,我們現(xiàn)在在水平方向上放置兩個(gè)按鈕鹉勒,一個(gè)是150dp左對(duì)齊,另外一個(gè)是200dp右對(duì)齊吵取,那么中間留有10dp間隔禽额;但假如同樣地設(shè)置在Nexus S(屏幕寬度是320dp),會(huì)發(fā)現(xiàn)海渊,兩個(gè)按鈕會(huì)重疊绵疲,因?yàn)?20dp<200+150dp
從上面可以看出哲鸳,由于Android屏幕設(shè)備的多樣性臣疑,如果使用dp來作為度量單位,并不是所有的屏幕的寬度都具備相同的dp長(zhǎng)度
再次明確徙菠,屏幕寬度和像素密度沒有任何關(guān)聯(lián)關(guān)系
所以說讯沈,dp解決了同一數(shù)值在不同分辨率中展示相同尺寸大小的問題(即屏幕像素密度匹配問題),但卻沒有解決設(shè)備尺寸大小匹配的問題婿奔。(即屏幕尺寸匹配問題)
當(dāng)然缺狠,我們一開始討論的就是屏幕尺寸匹配問題,使用match_parent萍摊、wrap_content和weight挤茄,盡可能少用dp來指定控件的具體長(zhǎng)寬,大部分的情況我們都是可以做到適配的冰木。
那么該如何解決控件的屏幕尺寸和屏幕密度的適配問題呢穷劈?
從上面可以看出:
- 因?yàn)槠聊幻芏龋ǚ直媛剩┎灰粯樱圆荒苡霉潭ǖ膒x
- 因?yàn)槠聊粚挾炔灰粯佑环校砸⌒牡挠胐p
因?yàn)楸举|(zhì)上是希望使得布局組件在不同屏幕密度上顯示相同的像素效果歇终,那么,之前是繞了個(gè)彎使用dp解決這個(gè)問題逼龟,那么到底能不能直接用px解決呢评凝?
即根據(jù)不同屏幕密度,控件選擇對(duì)應(yīng)的像素值大小
接下來介紹一種方法:百分比適配方法腺律,步驟如下:
- 以某一分辨率為基準(zhǔn)奕短,生成所有分辨率對(duì)應(yīng)像素?cái)?shù)列表
- 將生成像素?cái)?shù)列表存放在res目錄下對(duì)應(yīng)的values文件下
- 根據(jù)UI設(shè)計(jì)師給出設(shè)計(jì)圖上的尺寸,找到對(duì)應(yīng)像素?cái)?shù)的單位匀钧,然后設(shè)置給控件即可
步驟1:以某一分辨率為基準(zhǔn)翎碑,生成所有分辨率對(duì)應(yīng)像素?cái)?shù)列表
現(xiàn)在我們以320x480的分辨率為基準(zhǔn):
- 將屏幕的寬度分為320份,取值為x1~x320
- 將屏幕的高度分為480份榴捡,取值為y1~y480
然后生成該分辨率對(duì)應(yīng)像素?cái)?shù)的列表杈女,如下圖:
- lay_x.xml(寬)
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="x1">1.0px</dimen>
<dimen name="x2">2.0px</dimen>
<dimen name="x3">3.0px</dimen>
<dimen name="x4">4.0px</dimen>
<dimen name="x5">5.0px</dimen>
<dimen name="x6">6.0px</dimen>
<dimen name="x7">7.0px</dimen>
<dimen name="x8">8.0px</dimen>
<dimen name="x9">9.0px</dimen>
<dimen name="x10">10.0px</dimen>
...
<dimen name="x300">300.0px</dimen>
<dimen name="x301">301.0px</dimen>
<dimen name="x302">302.0px</dimen>
<dimen name="x303">303.0px</dimen>
<dimen name="x304">304.0px</dimen>
<dimen name="x305">305.0px</dimen>
<dimen name="x306">306.0px</dimen>
<dimen name="x307">307.0px</dimen>
<dimen name="x308">308.0px</dimen>
<dimen name="x309">309.0px</dimen>
<dimen name="x310">310.0px</dimen>
<dimen name="x311">311.0px</dimen>
<dimen name="x312">312.0px</dimen>
<dimen name="x313">313.0px</dimen>
<dimen name="x314">314.0px</dimen>
<dimen name="x315">315.0px</dimen>
<dimen name="x316">316.0px</dimen>
<dimen name="x317">317.0px</dimen>
<dimen name="x318">318.0px</dimen>
<dimen name="x319">319.0px</dimen>
<dimen name="x320">320px</dimen>
</resources>
- lay_y.xml(高)
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="y1">1.0px</dimen>
<dimen name="y2">2.0px</dimen>
<dimen name="y3">3.0px</dimen>
<dimen name="y4">4.0px</dimen>
...
<dimen name="y480">480px</dimen>
</resources>
找到基準(zhǔn)后,是時(shí)候把其他分辨率補(bǔ)全了,現(xiàn)今以寫1080x1920的分辨率為例:
因?yàn)榛鶞?zhǔn)是320x480达椰,所以1080/320=3.375px翰蠢,1920/480=4px,所以相應(yīng)文件應(yīng)該是
- lay_x.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="x1">3.375px</dimen>
<dimen name="x2">6.65px</dimen>
<dimen name="x3">10.125px</dimen>
...
<dimen name="x320">1080px</dimen>
</resources>
- lay_y.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="y1">4px</dimen>
<dimen name="y2">8px</dimen>
<dimen name="y3">12px</dimen>
<dimen name="y4">16px</dimen>
...
<dimen name="y480">1920px</dimen>
</resources>
用上面的方法把你需要適配的分辨率的像素列表補(bǔ)全吧~
作為程序猿的我們當(dāng)然不會(huì)做手寫的這些蠢事ⅰA翰住!多謝 @鴻洋大神 提供了自動(dòng)生成工具(內(nèi)置了常用的分辨率)蝇裤,大家可以直接點(diǎn)擊這里下載
注:工具默認(rèn)基準(zhǔn)為400*320廷支,當(dāng)然對(duì)于特殊需求,通過命令行指定即可:
java -jar 文件名.jar 基準(zhǔn)寬 基準(zhǔn)高 額外支持尺寸1的寬栓辜,額外支持尺寸1的高_(dá)額外支持尺寸2的寬,額外支持尺寸2的高:
例如:需要設(shè)置的基準(zhǔn)是800x1280恋拍,額外支持尺寸:735x1152 ;3200x4500藕甩;
java -jar 文件名.jar 800 1280 735施敢,1152_3200,4500
步驟2:把生成的各像素?cái)?shù)列表放到對(duì)應(yīng)的資源文件
將生成像素?cái)?shù)列表(lay_x.xml和lay_y.xml)存放在res目錄下對(duì)應(yīng)的values文件(注意寬、高要對(duì)應(yīng))狭莱,如下圖:
注:
- 分辨率為480x320的資源文件應(yīng)放在res/values-480x320文件夾中僵娃;同理分辨率為1920x1080的資源文件應(yīng)放在res/values-1920x1080文件夾中。(其中values-480x320是分辨率限定符)
- 必須在默認(rèn)values里面也創(chuàng)建對(duì)應(yīng)默認(rèn)lay_x.xml和lay_y.xml文件腋妙,如下圖
lay_x.xml
<?xml version="1.0" encoding="utf-8">
<resources>
<dimen name="x1">1.0dp</dimen>
<dimen name="x2">2.0dp</dimen>
...
</resources>
- 因?yàn)閷?duì)于沒有生成對(duì)應(yīng)分辨率文件的手機(jī)默怨,會(huì)使用默認(rèn)values文件夾,如果默認(rèn)values文件夾沒有(即沒有對(duì)應(yīng)的分辨率骤素、沒有對(duì)應(yīng)dimen)就會(huì)報(bào)錯(cuò)匙睹,從而無法進(jìn)行屏幕適配。
(注意對(duì)應(yīng)單位改為dp谆甜,而不同于上面的px垃僚。因?yàn)椴恢罊C(jī)型的分辨率,所以默認(rèn)分辨率文件只好默認(rèn)為x1=1dp以保證盡量兼容(又回到dp老方法了)规辱,這也是這個(gè)解決方案的一個(gè)弊端)
步驟3:根據(jù)UI設(shè)計(jì)師給出某一分辨率設(shè)計(jì)圖上的尺寸谆棺,找到對(duì)應(yīng)像素?cái)?shù)的單位,然后設(shè)置給控件即可
如下圖:
<FrameLayout >
<Button
android:layout_gravity="center"
android:gravity="center"
android:text="@string/hello_world"
android:layout_width="@dimen/x160"
android:layout_height="@dimen/y160"/>
</FrameLayout>
總結(jié)
使用上述的適配方式罕袋,應(yīng)該能進(jìn)行90%的適配了改淑,但其缺點(diǎn)還是很明顯:
- 由于實(shí)際上還是使用px作為長(zhǎng)度的度量單位,所以和google的要求使用dp作為度量單位會(huì)有所背離
- 必須盡可能多的包含所有分辨率浴讯,因?yàn)檫@個(gè)是使用這個(gè)方案的基礎(chǔ)朵夏,如果有某個(gè)分辨率缺少,將無法完成該屏幕的適配
- 過多的分辨率像素描述xml文件會(huì)增加軟件包的大小和維護(hù)的難度
“圖片資源”匹配
本質(zhì):使得圖片資源在不同屏幕密度上顯示相同的像素效果
- 做法:提供備用位圖(符合屏幕尺寸的圖片資源)
由于 Android 可在各種屏幕密度的設(shè)備上運(yùn)行榆纽,因此我們提供的位圖資源應(yīng)該始終可以滿足各類密度的要求:
密度類型 | 代表的分辨率(px) | 系統(tǒng)密度(dpi) |
---|---|---|
低密度(ldpi) | 240x320 | 120 |
中密度(mdpi) | 320x480 | 160 |
高密度(hdpi) | 480x800 | 240 |
超高密度(xhdpi) | 720x1280 | 320 |
超超高密度(xxhdpi) | 1080x1920 | 480 |
- 步驟1:根據(jù)以下尺寸范圍針對(duì)各密度生成相應(yīng)的圖片仰猖。
比如說捏肢,如果我們?yōu)?xhdpi 設(shè)備生成了 200x200 px尺寸的圖片,就應(yīng)該按照相應(yīng)比例地為 hdpi饥侵、mdpi 和 ldpi 設(shè)備分別生成 150x150鸵赫、100x100 和 75x75 尺寸的圖片
即一套分辨率=一套位圖資源(這個(gè)當(dāng)然是Ui設(shè)計(jì)師做了)
- 步驟2:將生成的圖片文件放在 res/ 下的相應(yīng)子目錄中(mdpi、hdpi躏升、xhdpi辩棒、xxhdpi),系統(tǒng)就會(huì)根據(jù)運(yùn)行您應(yīng)用的設(shè)備的屏幕密度自動(dòng)選擇合適的圖片
- 步驟3:通過引用 @drawable/id膨疏,系統(tǒng)都能根據(jù)相應(yīng)屏幕的 屏幕密度(dpi)自動(dòng)選取合適的位圖一睁。
注:
- 如果是.9圖或者是不需要多個(gè)分辨率的圖片,放在drawable文件夾即可
- 對(duì)應(yīng)分辨率的圖片要正確的放在合適的文件夾佃却,否則會(huì)造成圖片拉伸等問題者吁。
更好地方案解決“圖片資源”適配問題
上述方案是常見的一種方案,這固然是一種解決辦法双霍,但缺點(diǎn)在于:
- 每套分辨率出一套圖砚偶,為美工或者設(shè)計(jì)增加了許多工作量
- 對(duì)Android工程文件的apk包變的很大
那么,有沒有一種方法:
- 保證屏幕密度適配
- 可以最小占用設(shè)計(jì)資源
- 使得apk包不變大(只使用一套分辨率的圖片資源)
下面我們就來介紹這個(gè)方法:
- 只需選擇唯一一套分辨率規(guī)格的圖片資源
方法介紹
1. 先來理解下Android 加載資源過程
Android SDK會(huì)根據(jù)屏幕密度自動(dòng)選擇對(duì)應(yīng)的資源文件進(jìn)行渲染加載(自動(dòng)渲染)
比如說洒闸,SDK檢測(cè)到你手機(jī)的分辨率是320x480(dpi=160),會(huì)優(yōu)先到drawable-mdpi文件夾下找對(duì)應(yīng)的圖片資源均芽;但假設(shè)你只在xhpdi文件夾下有對(duì)應(yīng)的圖片資源文件(mdpi文件夾是空的)丘逸,那么SDK會(huì)去xhpdi文件夾找到相應(yīng)的圖片資源文件,然后將原有大像素的圖片自動(dòng)縮放成小像素的圖片掀宋,于是大像素的圖片照樣可以在小像素分辨率的手機(jī)上正常顯示深纲。
具體請(qǐng)看http://blog.csdn.net/xiebudong/article/details/37040263
所以理論上來說只需要提供一種分辨率規(guī)格的圖片資源就可以了。
那么應(yīng)該提供哪種分辨率規(guī)格呢梦抢?
如果只提供ldpi規(guī)格的圖片厌秒,對(duì)于大分辨率(xdpi夺颤、xxdpi)的手機(jī)如果把圖片放大就會(huì)不清晰
所以需要提供一套你需要支持的最大dpi分辨率規(guī)格的圖片資源,這樣即使用戶的手機(jī)分辨率很小币呵,這樣圖片縮小依然很清晰。那么這一套最大dpi分辨率規(guī)格應(yīng)該是哪種呢侨颈?是現(xiàn)在市面手機(jī)分辨率最大可達(dá)到1080X1920的分辨率(dpi=xxdpi=480)嗎余赢?
2. xhdpi應(yīng)該是首選
原因如下:
- xhdpi分辨率以內(nèi)的手機(jī)需求量最旺盛
目前市面上最普遍的高端機(jī)的分辨率還多集中在720X1080范圍內(nèi)(xhdpi),所以目前來看xhpdi規(guī)格的圖片資源成為了首選 - 節(jié)省設(shè)計(jì)資源&工作量
在現(xiàn)在的App開發(fā)中(iOS和Android版本)哈垢,有些設(shè)計(jì)師為了保持App不同版本的體驗(yàn)交互一致妻柒,可能會(huì)以iPhone手機(jī)為基礎(chǔ)進(jìn)行設(shè)計(jì),包括后期的切圖之類的耘分。
設(shè)計(jì)師們一般都會(huì)用最新的iPhone6和iPhone5s(5s和5的尺寸以及分辨率都一樣)來做原型設(shè)計(jì)举塔,所有參數(shù)請(qǐng)看下圖
機(jī)型 | 分辨率(px) | 屏幕尺寸(inch) | 系統(tǒng)密度(dpi) |
---|---|---|---|
iPhone 5s | 640X1164 | 4 | 332 |
iPhone 6 | 1334x750 | 4.7 | 326 |
iPhone 6 Plus | 1080x1920 | 5 | 400 |
iPhone主流的屏幕dpi約等于320, 剛好屬于xhdpi绑警,所以選擇xhdpi作為唯一一套dpi圖片資源,可以讓設(shè)計(jì)師不用專門為Android端切圖央渣,直接把iPhone的那一套切好的圖片資源放入drawable-xhdpi文件夾里就好待秃,這樣大大減少的設(shè)計(jì)師的工作量!
額外小tips
ImageView的ScaleType屬性
設(shè)置不同的ScaleType會(huì)得到不同的顯示效果痹屹,一般情況下章郁,設(shè)置為centerCrop能獲得較好的適配效果。動(dòng)態(tài)設(shè)置
使用場(chǎng)景:有些情況下志衍,我們需要?jiǎng)討B(tài)的設(shè)置控件大小或者是位置暖庄,比如說popwindow的顯示位置和偏移量等
這時(shí)我們可以動(dòng)態(tài)獲取當(dāng)前的屏幕屬性,然后設(shè)置合適的數(shù)值
public class ScreenSizeUtil {
public static int getScreenWidth(Activity activity) {
return activity.getWindowManager().getDefaultDisplay().getWidth();
}
public static int getScreenHeight(Activity activity) {
return activity.getWindowManager().getDefaultDisplay().getHeight();
}
}
總結(jié)
- 本文根據(jù)現(xiàn)今主流Android的適配方法楼肪,以邏輯清晰的方式進(jìn)行了主流Android適配方法的全面整理
- 下面我將繼續(xù)對(duì)
Android
中的知識(shí)進(jìn)行深入講解培廓,感興趣的同學(xué)可以繼續(xù)關(guān)注Carson_Ho的簡(jiǎn)書
相關(guān)系列文章閱讀
Carson帶你學(xué)Android:學(xué)習(xí)方法
Carson帶你學(xué)Android:四大組件
Carson帶你學(xué)Android:自定義View
Carson帶你學(xué)Android:異步-多線程
Carson帶你學(xué)Android:性能優(yōu)化
Carson帶你學(xué)Android:動(dòng)畫
歡迎關(guān)注Carson_Ho的簡(jiǎn)書
不定期分享關(guān)于安卓開發(fā)的干貨,追求短春叫、平肩钠、快,但卻不缺深度暂殖。