该篇文章从eoeAndroid搬迁过来的,原文地址:学习之随堂笔记——屏幕适配
注:该帖子为本人学习时随手记录的,内容杂乱,敬请见谅
一、各种适配相关知识
1.屏幕尺寸
屏幕对角线的长度,单位英寸,1英寸=2.54厘米
2.屏幕分辨率
在纵横向上的像素点数,单位px,1px=1个像素点,一般以纵向像素*横向像素,如1920*1080
3.屏幕像素密度
每英寸上的像素点数,单位dpi,屏幕的像素密度与屏幕尺寸和屏幕分辨率有关
计算方式:纵向像素的平方+横向像素的平方,开根号,结果除以屏幕尺寸
例如:Nexus 5,屏幕尺寸 4.95英寸,分辨率 1920*1080,dpi 445
(√ ̄(1920^2+1080^2)) / 4.95 ≈ 445
4.px
构成图像的最小单位
5.dp,dip
密度无关像素,以160dpi为基准,1dip=1px
6.sp
可以根据文字大小首选项进行放缩,google推荐使用12sp以上大小的文字(12sp,14sp,18sp,22sp首选大小),不要使用奇数或小数,字体放缩时会造成精度的丢失。
7.ldpi,mdpi,hdpi,xdpi,xxdpi,xxxhdpi
名称 | 像素密度范围 | 倍数 | 图标尺寸 |
---|---|---|---|
ldpi | 小于或等于120dpi(过低,可以忽略,系统会自动根据hdpi尺寸的图标缩小到1/2进行匹配) | ||
mdpi | 120dpi~160dpi | 1x | 48x48px |
hdpi | 160dpi~240dpi | 1.5x | 72x72px |
xdpi | 240dpi~320dpi | 2x | 96x96px |
xxhdpi | 320dpi~480dpi | 3x | 144x144px |
xxxhdpi | 480dpi~640dpi(刚出) | 4x | 192x192px |
在设计图标时,对于五种主流像素密度(mdpi,hdpi,xhdpi,xxhdpi,xxxhdpi)应按照2:3:4:6:8的比例进行缩放
二、屏幕适配解决方案
1.支持各种屏幕尺寸
使用wrap_content、match_parent、weight
weight计算出的宽度=原来宽度(width属性)+剩余空间所占百分比宽度
使用相对布局,禁用绝对布局
使用限定符
尺寸限定符large(android3.2之前有作用)
最小宽度限定符small width最小宽度(android3.2之后推出的)
为了兼容高低版本,减少布局,可以使用布局别名,进行统一管理
屏幕方向限定符 land,port
例子:
使用自动拉伸位图 .9图
2.支持各种屏幕密度
使用非密度制约像素
提供备用位图(最好根据不同的屏幕密度提供不同的切图,从而保证使用图片资源的时候减少内存压力)
3.实施自适应用户界面流程
确定当前布局
根据当前布局做出响应
重复使用其-他活动中的片段
处理屏幕配置变化
4.最佳实践
关于高清设计图尺寸
动态设置
学习完成后,本人做了一个根据不同分辨率和屏幕密度计算生成dimens的小例子,主要思路如下:
1.确定设计图纸的宽度尺寸,如例子中的640
2.获取需要适配手机的分辨率与屏幕密度,,可以根据手机型号在网上搜索,如ZOL产品报价网站,红米note手机,分辨率1280x720,屏幕密度267dpi
3.因为屏幕密度为160(mdpi)的手机1dp=1px,所以我们可以生成一个基准dimens.xml文件放在values中,里面的所有dimens数值都是1:1生成的,其余的屏幕密度倍数分别为:120(ldpi,0.75),240(hdpi,1.5),320(xhdpi,2),480(xxhdpi,3),640(xxxhdpi,4),以红米note为例,生成对应的dimens.xml文件,红米note屏幕密度为267,靠近240,所以我们取hdpi 1.5倍,以宽度为值,红米note的宽度为720,图纸尺寸为640,所以对应得dimens计算倍数为:720/(640*1.5),然后用该倍数就能获取红米note机器下的dimens值,具体代码如下:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
public class DimensTools {
private static final String BASE_FOLDER = "C:/Users/krubo/Desktop/dimens";
/** 基准宽度 */
private static final int BASE_WIDHT = 640;
// ldpi-0.75(120),mdpi-1(160),hdpi-1.5(240),xhdpi-2(320),xxhdpi-3(480),xxxhdpi-4(640)
public static void main(String[] args) {
getBaseDimens();
getDimens(1440, 2560, "xxxhdpi");
getDimens(720, 1280, "xhdpi");
getDimens(720, 1280, "hdpi");
getDimens(540, 960, "hdpi");
getDimens(480, 800, "hdpi");
}
private static void getBaseDimens() {
File folder = new File(BASE_FOLDER + "/values");
if (!folder.exists()) {
folder.mkdirs();
}
File file = new File(folder.getAbsoluteFile() + "/" + "dimens.xml");
if (file.exists()) {
file.delete();
}
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getBaseDimens fail");
return;
}
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>").append("\n");
sb.append("<resources>").append("\n");
for (int i = 1; i <= 2000; i++) {
sb.append("<dimen name=\"DIMEN_" + i + "DP\">");
sb.append(i + "dp");
sb.append("</dimen>").append("\n");
}
sb.append("</resources>");
try {
PrintWriter pw = new PrintWriter(file);
pw.write(sb.toString());
pw.flush();
pw.close();
System.out.println("getBaseDimens success");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getBaseDimens fail");
}
}
private static void getDimens(int widht, int height, String dpiName) {
double dpi = 1;
if (dpiName.equals("ldpi")) {
dpi = 0.75d;
} else if (dpiName.equals("mdpi")) {
dpi = 1;
} else if (dpiName.equals("hdpi")) {
dpi = 1.5d;
} else if (dpiName.equals("xhdpi")) {
dpi = 2;
} else if (dpiName.equals("xxhdpi")) {
dpi = 3;
} else if (dpiName.equals("xxxhdpi")) {
dpi = 4;
}
File folder = new File(BASE_FOLDER + "/values-" + dpiName + "-"
+ height + "x" + widht);
if (!folder.exists()) {
folder.mkdirs();
}
File file = new File(folder.getAbsoluteFile() + "/" + "dimens.xml");
if (file.exists()) {
file.delete();
}
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getdimens file fail");
return;
}
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>").append("\n");
sb.append("<resources>").append("\n");
double multiple = (double) widht / (BASE_WIDHT * dpi);
System.out.println("multiple:" + multiple);
for (int i = 1; i <= 1500; i++) {
sb.append("<dimen name=\"DIMEN_" + i + "DP\">");
sb.append((double) i * 2 * multiple + "dp");
sb.append("</dimen>").append("\n");
}
sb.append("</resources>");
try {
PrintWriter pw = new PrintWriter(file);
pw.write(sb.toString());
pw.flush();
pw.close();
System.out.println("getdimens success");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getdimens write fail");
}
}
}