总结Android屏幕适配(源自简书:李俊的博客)
基礎知識
屏幕尺寸、屏幕分辨率、屏幕像素密度
1、屏幕尺寸是指屏幕對角線的長度。單位是英寸,1英寸=2.54厘米。
2、屏幕分辨率是指在橫縱向上的像素點數,單位是px,1px=1像素點,一般是縱向像素橫向像素,如1280×720。
3、屏幕像素密度是指每英寸上的像素點數,單位是dpi(dot per inch),像素密度和屏幕尺寸和屏幕分辨率有關。
dip、dp、sp、dpi、px、in、pt
1、dip或dp(device independent pixels,設備獨立像素):以160dpi為基準,1dp=1px。
2、sp(scaled pixels):可以根據文字大小首選項自動進行縮放。
3、dpi(dots per inch,密度):屏幕像素密度的單位,屏幕每英寸所包含的像素數。
4、px(pixels,像素):物理上的絕對單位。
5、in(inch,英寸):一英寸=2.54cm。
6、pt(磅):一磅=1/72英寸。
mdpi、hdpi、xdpi、xxdpi、xxxdpi
| mdpi | 120~160dpi | 320x480px | 48x48px | 1 |
| hdpi | 160~240dpi | 480x800px | 72x72px | 1.5 |
| xhdpi | 240~320dpi | 720x1280px | 96x96px | 2 |
| xxhdpi | 320~480dpi | 1080x1920px | 144x144px | 3 |
| xxxhdpi | 480~640dpi | 1440x2560px | 192x192px | 4 |
實戰
獲取屏幕的數據
// 獲取DisplayMetrics實例 DisplayMetrics dm = context.getResources().getDisplayMetrics();// 屏幕高的像素個數 int heightPixels = dm.heightPixels; // 屏幕寬的像素個數 int widthPixels = dm.widthPixels;// 屏幕密度:每英寸所含的像素的個數 int densityDpi = dm.densityDpi; // 屏幕密度:densityDpi/160 float density = dm.density;dp與px相互轉換
/*** 轉換工具類*/ public class ConvertUtil {/*** dp轉換成px** @param context 上下文* @param value 多少dp* @return 返回轉換后等于多少px*/public static int dp2px(Context context, float value) {// 獲取屏幕的密度:density = densityDpi/160final float scale = context.getResources().getDisplayMetrics().density;// dp轉換成px,value*density// + 0.5f是為了四舍五入轉換成int類型return (int) (value * scale + 0.5f);}public static int px2dp(Context context, float value) {final float scale = context.getResources().getDisplayMetrics().density;// px轉換成dp,value/densityreturn (int) (value / scale + 0.5f);} }注意:因為分辨率不一樣,所以不能用px;因為屏幕寬度不一樣,所以要小心的用dp。
解決方案
一、支持各種屏幕尺寸
1、使用wrap_content、math_parent、weight
wrap_content:根據控件的內容設置控件的尺寸
math_parent:根據父控件的尺寸大小設置控件的尺寸
weight:權重,在線性布局中可以使用weight屬性設置控件所占的比例
實現下圖所顯示的效果:當屏幕尺寸改變時,new reader控件兩邊的控件大小不變,new reader控件會占完剩余的空間。
android:layout_weight
公式:所占寬度=原來寬度+剩余空間所占百分比的寬度
2、使用相對布局,禁用絕對布局
簡單的布局一般都使用線性布局,而略微復雜點的布局,我們使用相對布局,大多數時候,我們都是使用這兩種布局的嵌套。我們使用相對布局的原因是,相對布局能在各種尺寸的屏幕上保持控件間的相對位置。
3、使用限定符
一、使用尺寸限定符
當我們要在大屏幕上顯示不同的布局,就要使用large限定符。例如,在寬的屏幕左邊顯示列表右邊顯示列表項的詳細信息,在一般寬度的屏幕只顯示列表,不顯示列表項的詳細信息,我們就可以使用large限定符。
單面板:res/layout/activity_qualifier.xml
雙面板:res/layout-large/activity_qualifier.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/news_title_fragment"android:name="com.jun.androidexample.qualifier.NewsTitleFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><FrameLayoutandroid:id="@+id/news_content_layout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"><fragmentandroid:id="@+id/news_content_fragment"android:name="com.jun.androidexample.qualifier.NewsContentFragment"android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout> </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/activity_qualifier.xml
雙面板:res/layout-sw600dp/activity_qualifier.xml,Small Width最小寬度
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/news_title_fragment"android:name="com.jun.androidexample.qualifier.NewsTitleFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><FrameLayoutandroid:id="@+id/news_content_layout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"><fragmentandroid:id="@+id/news_content_fragment"android:name="com.jun.androidexample.qualifier.NewsContentFragment"android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout> </LinearLayout>這就要求我們維護兩個相同功能的文件,為了避免繁瑣操作,我們就要使用布局別名。
三、使用布局別名
單面板:res/layout/activity_qualifier.xml
雙面板:res/layout-large/activity_qualifier.xml
雙面板:res/layout-sw600dp/activity_qualifier.xml
因為雙面板的布局一樣,所以為了方便管理使用以下2個文件代替上面的3個文件。
單面板:res/layout/activity_qualifier_onepane.xml
雙面板:res/layout/activity_qualifier_twopanes.xml
然后創建如下3個文件
默認布局,單面板:res/values/layout.xml
Android3.2之前的大屏布局,雙面板:res/values-large/layout.xml
<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_twopanes</item> </resources>Android3.2之后的大于600dp屏布局,雙面板:res/values-sw600dp/layout.xml
<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_twopanes</item> </resources>這樣無論是哪一種名字都叫activity_qualifier。
記得將之前創建的res/layout-large和res/layout-sw600dp
雙面板:res/layout-large/activity_qualifier.xml
雙面板:res/layout-sw600dp/activity_qualifier.xml,Small Width最小寬度
都刪掉,因為已經不需要了。
四、使用屏幕方向限定符
res/values-port/layout.xml,縱向,單面板
<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_onepane</item> </resources>res/values-land/layout.xml,橫向,雙面板
<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_twopanes</item> </resources>4、使用自動拉伸位圖
.9.png格式圖片
二、支持各種屏幕密度
1、統一劃分
統一劃分解決分辨率不一致,寬高不一致的問題。把需要適配的手機屏幕的寬度像素均分為320份,高度像素均分為480份。使用我們寫好的程序自動生成資源values-×文件夾,里面包含lay_x.xml和lay_y.xml,分別對應寬度和高度的像素。
在Eclipse中運行如下代碼自動生成需要的文件
/*** 將所有不同分辨率的屏幕都分成480x320*/ public class MakeXml {// 生成文件存放的地址是C:\layoutRootprivate final static String rootPath = "C:\\layoutRoot\\values-{0}x{1}\\";// 分成480x320private final static float dw = 320f;private final static float dh = 480f;private final static String WTemplate = "<dimen name=\"x{0}\">{1}px</dimen>\n";private final static String HTemplate = "<dimen name=\"y{0}\">{1}px</dimen>\n";public static void main(String[] args) {setResolution();}// 設置需要適配的不同屏幕的分辨率public static void setResolution(){makeString(320, 480);makeString(480, 800);makeString(480, 854);makeString(540, 960);makeString(600, 1024);makeString(720, 1184);makeString(720, 1196);makeString(720, 1280);makeString(768, 1024);makeString(800, 1280);makeString(1080, 1812);makeString(1080, 1920);makeString(1440, 2560);}public static void makeString(int w, int h) {StringBuffer sb = new StringBuffer();sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");sb.append("<resources>");float cellw = w / dw;for (int i = 1; i < 320; i++) {sb.append(WTemplate.replace("{0}", i + "").replace("{1}",change(cellw * i) + ""));}sb.append(WTemplate.replace("{0}", "320").replace("{1}", w + ""));sb.append("</resources>");StringBuffer sb2 = new StringBuffer();sb2.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");sb2.append("<resources>");float cellh = h / dh;for (int i = 1; i < 480; i++) {sb2.append(HTemplate.replace("{0}", i + "").replace("{1}",change(cellh * i) + ""));}sb2.append(HTemplate.replace("{0}", "480").replace("{1}", h + ""));sb2.append("</resources>");String path = rootPath.replace("{0}", h + "").replace("{1}", w + "");File rootFile = new File(path);if (!rootFile.exists()) {rootFile.mkdirs();}File layxFile = new File(path + "lay_x.xml");File layyFile = new File(path + "lay_y.xml");try {PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));pw.print(sb.toString());pw.close();pw = new PrintWriter(new FileOutputStream(layyFile));pw.print(sb2.toString());pw.close();} catch (FileNotFoundException e) {e.printStackTrace();}}public static float change(float a) {int temp = (int) (a * 100);return temp / 100f;} }將C:\layoutRoot目錄下的文件拷貝到Android Studio中app/src/main/res/目錄下
使用示例:
<Buttonandroid:background="#abd123"android:layout_width="@dimen/x160"android:layout_height="@dimen/y240"/>寬和高都是屏幕的一半
2、提供備用位圖
針對不同分辨率的屏幕提供不同分辨率的位圖
res/drawable-mdpi
res/drawable-hdpi
res/drawable-xhdpi
res/drawable-xxhdpi
res/drawable-xxxhdpi
如果只提供一張位圖就應該放置在應對分辨率的文件夾中
三、實施自適應用戶界面流程
1、確定當前布局
boolean isTwoPane; // 能找到news_content_layout就是雙頁否則就是單頁 View view = getActivity().findViewById(R.id.news_content_layout); if (view != null && view.getVisibility() == View.VISIBLE) {isTwoPane = true; } else {isTwoPane = false; }2、根據當前布局做出響應
在單面板模式下,用戶點擊了新聞標題,我們要打開一個新的Activity來顯示新聞詳細信息;在雙面板模式下,用戶點擊了新聞標題,我們要在右邊面板上顯示詳細信息。
Percent Support Library(百分比布局庫)
添加依賴
compile 'com.android.support:percent:23.3.0'總結
以上是生活随笔為你收集整理的总结Android屏幕适配(源自简书:李俊的博客)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 熊猫烧香制造者李俊出狱以后的六种出路
- 下一篇: 基于突变的模糊测试