重要概念
什么是屏幕尺寸、屏幕分辨率、屏幕像素密度?
什么是dp、dip、dpi、sp、px?之间的关系是什么?
什么是mdpi、hdpi、xdpi、xxdpi?如何计算和区分?
屏幕尺寸
屏幕尺寸是指屏幕的对角线的长度
单位是英寸,1英寸 = 2.54厘米
屏幕分辨率
屏幕分辨率是指在横纵向上的像素点数
单位是px,1px = 1 像素点
一般以纵向像素 * 横向像素,如1910 * 1080
屏幕像素密度
屏幕像素密度是指每英寸上的像素点数
单位是dpi,即"dot per inch"的缩写
屏幕像素密度与屏幕尺寸和屏幕分辨率有关
Nexus 5
屏幕4.95inch
1920 * 1080
DPI = 445
(1920 ^ 2 + 1920 ^ 2) 开方 / 4.95
px
构成图像的最小单位
dp、dip
密度无关像素
以160dpi为基准,1dip = 1 px
sp
可以根据文字大小首选项进行放缩
mdpi、hdpi、xdpi、xxdpi
解决方案
1)支持各种屏幕尺寸
使用wrap_content、match_parent、weight
使用相对布局、禁用绝对布局
使用限定符
(1) 尺寸限定符
res/layout_large/main.xml 双面板布局 3.2之前版本
(2) 最小宽度限定符
res/layout_sw600dp/main.xml 双面板布局 small width 最小宽度
(3) 布局别名
res/layout_/main.xml 单面板布局
res/layout_large/main.xml 多面板布局
res/layout_sw600dp/main.xml 多面板布局
res/layout/main.xml
res/layout/main_twopanes.xml
setContentView(R.layout.main); 这里要使用布局别名
默认布局
res/values/layout.xml
<resources>
<item name="main" type="layout">@layout/main</item>
</resources>
3.2之前的平板布局
res/values-large/layout.xml
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
3.2之后的平板布局
res/values-sw600dp/layout.xml
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
(4) 方向限定符
res/values-sw600dp-land/layouts.xml
res/values-sw600dp-port/layouts.xml
res/values-sw600dp-land/layouts.xml
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
res/values-sw600dp-land/layouts.xml
<resources>
<item name="main" type="layout">@layout/main</item>
</resources>
使用自动拉伸位图
2) 支持各种屏幕密度
使用非密度制约像素
提供备用位图
3) 实施自适应用户界面流程
确定当前布局
根据当前布局做出响应
https://github.com/android/platform_development/tree/master/samples/training/multiscreen/newsreader
重复使用其他活动中的片段
处理屏幕配置变化
什么是屏幕尺寸、屏幕分辨率、屏幕像素密度?
什么是dp、dip、dpi、sp、px?之间的关系是什么?
什么是mdpi、hdpi、xdpi、xxdpi?如何计算和区分?
屏幕尺寸
屏幕尺寸是指屏幕的对角线的长度
单位是英寸,1英寸 = 2.54厘米
屏幕分辨率
屏幕分辨率是指在横纵向上的像素点数
单位是px,1px = 1 像素点
一般以纵向像素 * 横向像素,如1910 * 1080
屏幕像素密度
屏幕像素密度是指每英寸上的像素点数
单位是dpi,即"dot per inch"的缩写
屏幕像素密度与屏幕尺寸和屏幕分辨率有关
Nexus 5
屏幕4.95inch
1920 * 1080
DPI = 445
(1920 ^ 2 + 1920 ^ 2) 开方 / 4.95
px
构成图像的最小单位
dp、dip
密度无关像素
以160dpi为基准,1dip = 1 px
sp
可以根据文字大小首选项进行放缩
mdpi、hdpi、xdpi、xxdpi
解决方案
1)支持各种屏幕尺寸
使用wrap_content、match_parent、weight
使用相对布局、禁用绝对布局
使用限定符
(1) 尺寸限定符
res/layout_large/main.xml 双面板布局 3.2之前版本
(2) 最小宽度限定符
res/layout_sw600dp/main.xml 双面板布局 small width 最小宽度
(3) 布局别名
res/layout_/main.xml 单面板布局
res/layout_large/main.xml 多面板布局
res/layout_sw600dp/main.xml 多面板布局
res/layout/main.xml
res/layout/main_twopanes.xml
setContentView(R.layout.main); 这里要使用布局别名
默认布局
res/values/layout.xml
<resources>
<item name="main" type="layout">@layout/main</item>
</resources>
3.2之前的平板布局
res/values-large/layout.xml
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
3.2之后的平板布局
res/values-sw600dp/layout.xml
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
(4) 方向限定符
res/values-sw600dp-land/layouts.xml
res/values-sw600dp-port/layouts.xml
res/values-sw600dp-land/layouts.xml
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
res/values-sw600dp-land/layouts.xml
<resources>
<item name="main" type="layout">@layout/main</item>
</resources>
使用自动拉伸位图
2) 支持各种屏幕密度
使用非密度制约像素
提供备用位图
3) 实施自适应用户界面流程
确定当前布局
根据当前布局做出响应
https://github.com/android/platform_development/tree/master/samples/training/multiscreen/newsreader
重复使用其他活动中的片段
处理屏幕配置变化
使用非密度制约像素源码
public class MakeXml { private final static String rootPath = "C:/Users/lidx3/Desktop/values/value-{0}x{1}/"; private final static float dw = 320f; // 320 1单位长度=1px 640px 1单位长度=2px 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"; private final static NumberFormat numberFormat = NumberFormat.getNumberInstance(); public static void main(String[] args) { numberFormat.setMaximumFractionDigits(2); makeString(320, 480); makeString(480, 800); makeString(480, 854); makeString(1080, 1812); } private static void makeString(int w, int h) { StringBuffer sb = new StringBuffer(); sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); sb.append("<resources>\n"); 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>\n"); 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("</resource>"); 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(Exception e) { e.printStackTrace(); } } private static String change(float f) { // int temp = (int) (f * 100); // return temp / 100; return numberFormat.format(f) ; } }