轉自:https://www.jianshu.com/p/ec5a1a30694bjavascript
Android的屏幕適配一直以來都在折磨着咱們Android開發者,本文將結合:php
給你帶來一種全新、全面而邏輯清晰的Android屏幕適配思路,只要你認真閱讀,保證你能解決Android的屏幕適配問題!css
使得某一元素在Android不一樣尺寸、不一樣分辨率的手機上具有相同的顯示效果java
Android手機常見的尺寸有5寸、5.5寸、6寸等等android
- 通常描述成屏幕的"寬x高」=AxB
- 含義:屏幕在橫向方向(寬度)上有A個像素點,在縱向方向
(高)有B個像素點- 例子:1080x1920,即寬度方向上有1080個像素點,在高度方向上有1920個像素點
UI設計師的設計圖會以px做爲統一的計量單位git
假設設備內每英寸有160個像素,那麼該設備的屏幕像素密度=160dpigithub
密度類型 | 表明的分辨率(px) | 屏幕像素密度(dpi) |
---|---|---|
低密度(ldpi) | 240x320 | 120 |
中密度(mdpi) | 320x480 | 160 |
高密度(hdpi) | 480x800 | 240 |
超高密度(xhdpi) | 720x1280 | 320 |
超超高密度(xxhdpi) | 1080x1920 | 480 |
一部手機的分辨率是寬x高,屏幕大小是以寸爲單位,那麼三者的關係是:bash
數學不太差的人應該能懂.....吧?ide
不懂不要緊,在這裏舉個例子
假設一部手機的分辨率是1080x1920(px),屏幕大小是5寸,問密度是多少?
解:請直接套公式
工具
- Android開發時用dp而不是px單位設置圖片大小,是Android特有的單位
- 場景:假如一樣都是畫一條長度是屏幕一半的線,若是使用px做爲計量單位,那麼在480x800分辨率手機上設置應爲240px;在320x480的手機上應設置爲160px,兩者設置就不一樣了;若是使用dp爲單位,在這兩種分辨率下,160dp都顯示爲屏幕一半的長度。
密度類型 | 表明的分辨率(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中,規定以160dpi(即屏幕分辨率爲320x480)爲基準:1dp=1px
- Android開發時用此單位設置文字大小,可根據字體大小首選項進行縮放
- 推薦使用12sp、14sp、18sp、22sp做爲字體設置的大小,不推薦使用奇數和小數,容易形成精度的丟失問題;小於12sp的字體會過小致使用戶看不清
請把上面的概念記住,由於下面講解都會用到!
因爲Android系統的開放性,任何用戶、開發者、OEM廠商、運營商均可以對Android進行定製,因而致使:
固然都是基於Google原生系統定製的
據友盟指數顯示,統計至2015年12月,支持Android的設備共有27796種
當Android系統、屏幕尺寸、屏幕密度出現碎片化的時候,就很容易出現同一元素在不一樣手機上顯示不一樣的問題。
試想一下這麼一個場景:
爲4.3寸屏幕準備的UI設計圖,運行在5.0寸的屏幕上,極可能在右側和下側存在大量的空白;而5.0寸的UI設計圖運行到4.3寸的設備上,極可能顯示不下。
爲了保證用戶得到一致的用戶體驗效果:
使得某一元素在Android不一樣尺寸、不一樣分辨率的手機上具有相同的顯示效果
因而,咱們便須要對Android屏幕進行適配。
使得佈局、佈局組件自適應屏幕尺寸;
根據屏幕的配置來加載相應的UI佈局、用戶界面流程
本質1:使得佈局元素自適應屏幕尺寸
開發中,咱們使用的佈局通常有:
因爲絕對佈局(AbsoluteLayout)適配性極差,因此極少使用。
對於線性佈局(Linearlayout)、相對佈局(RelativeLayout)和幀佈局(FrameLayout)須要根據需求進行選擇,但要記住:
因此,對於屏幕適配來講,使用相對佈局(RelativeLayout)將會是更好的解決方案
本質2:根據屏幕的配置來加載相應的UI佈局
應用場景:須要爲不一樣屏幕尺寸的設備設計不一樣的佈局
- 在平板電腦和電視的屏幕(>7英寸)上:實施「雙面板」模式以同時顯示更多內容
- 在手機較小的屏幕上:使用單面板分別顯示內容
所以,咱們可使用尺寸限定符(layout-large)經過建立一個文件
res/layout-large/main.xml
來完成上述設定:
- 讓系統在屏幕尺寸>7英寸時採用適配平板的雙面板佈局
- 反之(默認狀況下)採用適配手機的單面板佈局
文件配置以下:
<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>
<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>
請注意:
但要注意的是,這種方式只適合Android 3.2版本以前。
- 背景:上述提到的限定符「large」具體是指多大呢?彷佛沒有一個定量的指標,這便意味着可能沒辦法準確地根據當前設備的配置(屏幕尺寸)自動加載合適的佈局資源
- 例子:好比說large同時包含着5寸和7寸,這意味着使用「large」限定符的話我沒辦法實現爲5寸和7寸的平板電腦分別加載不一樣的佈局
因而,在Android 3.2及以後版本,引入了最小寬度(Smallest-width)限定符
定義:經過指定某個最小寬度(以 dp 爲單位)來精肯定位屏幕從而加載不一樣的UI資源
你須要爲標準 7 英寸平板電腦匹配雙面板佈局(其最小寬度爲 600 dp),在手機(較小的屏幕上)匹配單面板佈局
解決方案:您可使用上文中所述的單面板和雙面板這兩種佈局,但您應使用 sw600dp 指明雙面板佈局僅適用於最小寬度爲 600 dp 的屏幕,而不是使用 large 尺寸限定符。
- sw xxxdp,即small width的縮寫,其不區分方向,即不管是寬度仍是高度,只要大於 xxxdp,就採用次此佈局
代碼展現:
<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>
<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>
- 對於最小寬度≥ 600 dp 的設備
系統會自動加載 layout-sw600dp/main.xml(雙面板)佈局,不然系統就會選擇 layout/main.xml(單面板)佈局
(這個選擇過程是Android系統自動選擇的)
當你須要同時爲Android 3.2版本前和Android 3.2版本後的手機進行屏幕尺寸適配的時候,因爲尺寸限定符僅用於Android 3.2版本前,最小寬度限定符僅用於Android 3.2版本後,因此這會帶來一個問題,爲了很好地進行屏幕尺寸的適配,你須要同時維護layout-sw600dp和layout-large的兩套main.xml平板佈局,以下:
最後的兩個文件的xml內容是徹底相同的,這會帶來:文件名的重複從而帶來一些列後期維護的問題
仍是上面的例子,你能夠定義如下佈局:
而後加入如下兩個文件,以便進行Android 3.2前和Android 3.2後的版本雙面板佈局適配:
<resources> <item name="main" type="layout">@layout/main_twopanes</item> </resources>
<resources> <item name="main" type="layout">@layout/main_twopanes</item> </resources>
注:
這樣兩個layout.xml都只是引用了@layout/main_twopanes,就避免了重複定義佈局文件的狀況
取如下爲例子:
- 小屏幕, 豎屏: 單面板
- 小屏幕, 橫屏: 單面板
- 7 英寸平板電腦,縱向:單面板,帶操做欄
- 7 英寸平板電腦,橫向:雙面板,寬,帶操做欄
- 10 英寸平板電腦,縱向:雙面板,窄,帶操做欄
- 10 英寸平板電腦,橫向:雙面板,寬,帶操做欄
- 電視,橫向:雙面板,寬,帶操做欄
方法是:
定義在 res/layout/ 目錄下的某個 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.使用佈局別名進行相應的匹配
(屏幕尺寸(小屏、7寸、10寸)、方向(橫、縱))
res/values/layouts.xml:(默認佈局)
<resources> <item name="main_layout" type="layout">@layout/onepane_with_bar</item> <bool name="has_two_panes">false</bool> </resources>
可爲resources設置bool,經過獲取其值來動態判斷目前已處在哪一個適配佈局
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>
這裏沒有徹底把所有尺寸匹配類型的代碼貼出來,你們能夠本身去嘗試把其補充完整
本質:使得佈局組件自適應屏幕尺寸
- "wrap_content"
相應視圖的寬和高就會被設定成所需的最小尺寸以適應視圖中的內容- "match_parent"(在Android API 8以前叫做"fill_parent")
視圖的寬和高延伸至充滿整個父佈局- "weight"
1.定義:是線性佈局(Linelayout)的一個獨特比例分配屬性
2.做用:使用此屬性設置權重,而後按照比例對界面進行空間的分配,公式計算是:控件寬度=控件設置寬度+剩餘空間所佔百分比寬幅
具體能夠參考這篇文章,講解得很是詳細
經過使用"wrap_content"、"match_parent"和"weight"來替代硬編碼的方式定義視圖大小&位置,你的視圖要麼僅僅使用了須要的那邊一點空間,要麼就會充滿全部可用的空間,即按需佔據空間大小,能讓你的佈局元素充分適應你的屏幕尺寸
本質:使得圖片資源在不一樣屏幕密度上顯示相同的像素效果
使用場景:一個按鈕的背景圖片必須可以隨着按鈕大小的改變而改變。
使用普通的圖片將沒法實現上述功能,由於運行時會均勻地拉伸或壓縮你的圖片
1.必需要使用.9.png後綴名,由於系統就是根據這個來區別nine-patch圖片和普通的PNG圖片的;
2.當你須要在一個控件中使用nine-patch圖片時,如
android:background="@drawable/button"
系統就會根據控件的大小自動地拉伸你想要拉伸的部分
- 使用場景:咱們會根據設備特色顯示恰當的佈局,可是這樣作,會使得用戶界面流程可能會有所不一樣。
- 例如,若是應用處於雙面板模式下,點擊左側面板上的項便可直接在右側面板上顯示相關內容;而若是該應用處於單面板模式下,點擊相關的內容應該跳轉到另一個Activity進行後續的處理。
本質:根據屏幕的配置來加載相應的用戶界面流程
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; } }
這段代碼用於查詢「報道」面板是否可用,與針對具體佈局的硬編碼查詢相比,這段代碼的靈活性要大得多。
例如,在新聞閱讀器示例中,若是用戶界面處於雙面板模式下,那麼點擊標題列表中的標題就會在右側面板中打開相應報道;但若是用戶界面處於單面板模式下,那麼上述操做就會啓動一個獨立活動:
@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); } }
例如,在新聞閱讀器示例中,對於較大的屏幕,新聞報道文本會顯示在右側面板中;但對於較小的屏幕,這些文本就會以獨立活動的形式存在。
在相似狀況下,一般能夠在多個活動中重複使用相同的 Fragment 子類以免代碼重複。例如,在雙面板佈局中使用了 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佈局中重複使用了它 :
ArticleFragment frag = new ArticleFragment(); getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
例如,在運行 Android 3.0 或更高版本的標準 7 英寸平板電腦上,若是新聞閱讀器示例應用運行在縱向模式下,就會在使用獨立活動顯示新聞報道;但若是該應用運行在橫向模式下,就會使用雙面板佈局。
也就是說,若是用戶處於縱向模式下且屏幕上顯示的是用於閱讀報道的活動,那麼就須要在檢測到屏幕方向變化(變成橫向模式)後執行相應操做,即中止上述活動並返回主活動,以便在雙面板佈局中顯示相關內容:
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; } ... }
經過上面一系列步驟,咱們就徹底能夠創建一個能夠根據用戶界面配置進行自適應的應用程序App了。
通過上面的介紹,對於屏幕尺寸大小適配問題應該是不成問題了。
本質:使得佈局組件在不一樣屏幕密度上顯示相同的像素效果
- Android開發時用dp而不是px單位設置圖片大小,是Android特有的單位
- 場景:假如一樣都是畫一條長度是屏幕一半的線,若是使用px做爲計量單位,那麼在480x800分辨率手機上設置應爲240px;在320x480的手機上應設置爲160px,兩者設置就不一樣了;若是使用dp爲單位,在這兩種分辨率下,160dp都顯示爲屏幕一半的長度。
| 密度類型 | 表明的分辨率(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中,規定以160dpi(即屏幕分辨率爲320x480)爲基準:1dp=1px
獨立比例像素
- Android開發時用此單位設置文字大小,可根據用戶的偏好文字大小/字體大小首選項進行縮放
- 推薦使用12sp、14sp、18sp、22sp做爲字體設置的大小,不推薦使用奇數和小數,容易形成精度的丟失問題;小於12sp的字體會過小致使用戶看不清
因此,爲了可以進行不一樣屏幕像素密度的匹配,咱們推薦:
但是,請看如下一種場景:
Nexus5的總寬度爲360dp,咱們如今在水平方向上放置兩個按鈕,一個是150dp左對齊,另一個是200dp右對齊,那麼中間留有10dp間隔;但假如一樣地設置在Nexus S(屏幕寬度是320dp),會發現,兩個按鈕會重疊,由於320dp<200+150dp
從上面能夠看出,因爲Android屏幕設備的多樣性,若是使用dp來做爲度量單位,並非全部的屏幕的寬度都具有相同的dp長度
再次明確,屏幕寬度和像素密度沒有任何關聯關係
因此說,dp解決了同一數值在不一樣分辨率中展現相同尺寸大小的問題(即屏幕像素密度匹配問題),但卻沒有解決設備尺寸大小匹配的問題。(即屏幕尺寸匹配問題)
固然,咱們一開始討論的就是屏幕尺寸匹配問題,使用match_parent、wrap_content和weight,儘量少用dp來指定控件的具體長寬,大部分的狀況咱們都是能夠作到適配的。
從上面能夠看出:
由於本質上是但願使得佈局組件在不一樣屏幕密度上顯示相同的像素效果,那麼,以前是繞了個彎使用dp解決這個問題,那麼到底能不能直接用px解決呢?
即根據不一樣屏幕密度,控件選擇對應的像素值大小
接下來介紹一種方法:百分比適配方法,步驟以下:
如今咱們以320x480的分辨率爲基準:
而後生成該分辨率對應像素數的列表,以下圖:
<?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>
<?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>
找到基準後,是時候把其餘分辨率補全了,現今以寫1080x1920的分辨率爲例:
由於基準是320x480,因此1080/320=3.375px,1920/480=4px,因此相應文件應該是
<?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>
<?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>
用上面的方法把你須要適配的分辨率的像素列表補全吧~
做爲程序猿的咱們固然不會作手寫的這些蠢事!!!多謝 @鴻洋大神 提供了自動生成工具(內置了經常使用的分辨率),你們能夠直接點擊這裏下載
注:工具默認基準爲400*320,固然對於特殊需求,經過命令行指定便可:
java -jar 文件名.jar 基準寬 基準高 額外支持尺寸1的寬,額外支持尺寸1的高_額外支持尺寸2的寬,額外支持尺寸2的高:
例如:須要設置的基準是800x1280,額外支持尺寸:735x1152 ;3200x4500;
java -jar 文件名.jar 800 1280 735,1152_3200,4500
將生成像素數列表(lay_x.xml和lay_y.xml)存放在res目錄下對應的values文件(注意寬、高要對應),以下圖:
注:
<?xml version="1.0" encoding="utf-8"> <resources> <dimen name="x1">1.0dp</dimen> <dimen name="x2">2.0dp</dimen> ... </resources>
以下圖:
<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>
使用上述的適配方式,應該能進行90%的適配了,但其缺點仍是很明顯:
本質:使得圖片資源在不一樣屏幕密度上顯示相同的像素效果
密度類型 | 表明的分辨率(px) | 系統密度(dpi) |
---|---|---|
低密度(ldpi) | 240x320 | 120 |
中密度(mdpi) | 320x480 | 160 |
高密度(hdpi) | 480x800 | 240 |
超高密度(xhdpi) | 720x1280 | 320 |
超超高密度(xxhdpi) | 1080x1920 | 480 |
好比說,若是咱們爲 xhdpi 設備生成了 200x200 px尺寸的圖片,就應該按照相應比例地爲 hdpi、mdpi 和 ldpi 設備分別生成 150x150、100x100 和 75x75 尺寸的圖片
即一套分辨率=一套位圖資源(這個固然是Ui設計師作了)
注:
- 若是是.9圖或者是不須要多個分辨率的圖片,放在drawable文件夾便可
- 對應分辨率的圖片要正確的放在合適的文件夾,不然會形成圖片拉伸等問題。
上述方案是常見的一種方案,這當然是一種解決辦法,但缺點在於:
那麼,有沒有一種方法:
下面咱們就來介紹這個方法:
1. 先來理解下Android 加載資源過程
Android SDK會根據屏幕密度自動選擇對應的資源文件進行渲染加載(自動渲染)
好比說,SDK檢測到你手機的分辨率是320x480(dpi=160),會優先到drawable-mdpi文件夾下找對應的圖片資源;但假設你只在xhpdi文件夾下有對應的圖片資源文件(mdpi文件夾是空的),那麼SDK會去xhpdi文件夾找到相應的圖片資源文件,而後將原有大像素的圖片自動縮放成小像素的圖片,因而大像素的圖片照樣能夠在小像素分辨率的手機上正常顯示。
具體請看http://blog.csdn.net/xiebudong/article/details/37040263
因此理論上來講只須要提供一種分辨率規格的圖片資源就能夠了。
那麼應該提供哪一種分辨率規格呢?
若是隻提供ldpi規格的圖片,對於大分辨率(xdpi、xxdpi)的手機若是把圖片放大就會不清晰
因此須要提供一套你須要支持的最大dpi分辨率規格的圖片資源,這樣即便用戶的手機分辨率很小,這樣圖片縮小依然很清晰。那麼這一套最大dpi分辨率規格應該是哪一種呢?是如今市面手機分辨率最大可達到1080X1920的分辨率(dpi=xxdpi=480)嗎?
2. xhdpi應該是首選
緣由以下:
機型 | 分辨率(px) | 屏幕尺寸(inch) | 系統密度(dpi) |
---|---|---|---|
iPhone 5s | 640X1164 | 4 | 332 |
iPhone 6 | 1334x750 | 4.7 | 326 |
iPhone 6 Plus | 1080x1920 | 5 | 400 |
iPhone主流的屏幕dpi約等於320, 恰好屬於xhdpi,因此選擇xhdpi做爲惟一一套dpi圖片資源,可讓設計師不用專門爲Android端切圖,直接把iPhone的那一套切好的圖片資源放入drawable-xhdpi文件夾裏就好,這樣大大減小的設計師的工做量!
ImageView的ScaleType屬性
設置不一樣的ScaleType會獲得不一樣的顯示效果,通常狀況下,設置爲centerCrop能得到較好的適配效果。
動態設置
使用場景:有些狀況下,咱們須要動態的設置控件大小或者是位置,好比說popwindow的顯示位置和偏移量等
這時咱們能夠動態獲取當前的屏幕屬性,而後設置合適的數值
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(); } }
本文根據現今主流Android的適配方法,以邏輯清晰的方式進行了主流Android適配方法的全面整理,接下來我會介紹繼續介紹Android開發中的相關知識,有興趣能夠繼續關注Carson_Ho的安卓開發筆記