屏幕适配

来源:互联网 发布:linux 修改文件权限 编辑:程序博客网 时间:2024/06/05 09:53

一些关于屏幕的概念:

px

像素, 即 屏幕上最小的点 可以显示一个颜色值

inch

英寸, 外国单位,1英寸=2.54厘米

分辨率

宽高所拥有的像素值 720*1280 宽为720个像素 高位1280个px

ppi

pixels per inch : 每英寸的像素点 通常我们是算的屏幕对角线的

ppi=(斜对角线的像素个数)/(斜对角线长度 单位为英寸) 即ppi=√(分辨率高的平方+分辨率宽的平方)/√(屏幕长度的平方+屏幕宽度的平方)其实就是用勾股定理算出对角线的像素个数和对角线的长度 相除 比如以720*1280 4.7寸屏为例(4.7寸屏就是指斜对角线长度)  即  ppi=√(1280^2+720^2)/4.7=312.469Dpi跟ppi是一个概念  意思是屏幕密度 数字越大 表示一英寸里容纳了越多的像素点,屏幕看起来就越精细

这里 对android 对ppi的大小设置了几个级别

DENSITY_LOW = 120  DENSITY_MEDIUM = 160  //默认值  DENSITY_HIGH = 240  //高清DENSITY_XHIGH = 320  //超清DENSITY_XXHIGH = 480  DENSITY_XXXHIGH = 640

超过某个值 就大概在哪个级别,比如刚才算出来的312.469 其实就在hdpi与xhdpi之间. 差不多就是xhdpi 商家是肯定会这么号称:超清屏

android设备比较乱 所以跟标准值一样的很少
另外
同一个ppi下,分辨率越大就越清晰
同一个ppi下,屏幕越大就越模糊 大电视上的颜色块我们应该都见过.

我就遇到过一个奇葩手机,他的屏幕跟其他手机一样大, 但是分辨率很低, 结果就造成了 手机看上去跟其他手机一样,价格都差不多,然后显示就是比别人的粗糙 显示的控件就是比别人的大

接下来轮到dp了

dp

dp是一种我们计算出来的单位 , 它在不同ppi上表示的像素个数不同,具体换算公式如下:

px=dp*(实际ppi/160)

在上面分出的等级里 我们把 ppi=160 定义为标准屏幕密度(几年前的标注 那时普遍ppi都低)

dp的作用是:为了在不同屏幕手机上显示出一样的大小

问题的出现:
320像素
在ppi160屏幕上显示的是2(320/160)英寸
在ppi 320的屏幕上 就只有1(320/320)英寸了
在ppi 640的屏幕上 只有0.5(320/640)英寸

越清晰就显示得越小,在低分屏还能看清 到了高分屏上就难说了,所以我们用px作为单位 就很不合适了 因为不能随屏幕变化而变化
由此引进dp这个单位,对px和ppi进行统一

其实就是根据比例缩放
像素不是在高分屏上缩小了么 那么缩小多少 我就乘以多少,
比如上面的
320像素 在 ppi160屏幕上显示的是2英寸
到ppi320 1英寸要显示为2英寸 那么就乘以2
到ppi640 0.5英寸要显示为2英寸 那么就乘以4

dp就是这里的比例关系
dp=px*160/ppi

也就是说
dp是为了保证在不同屏幕手机上显示出一样物理的大小

google这个设置 大致解决了分辨率的问题 保证了你在这个手机上设置的东西在另一台手机上都能看清.但新的问题来了 我们上面看到的是这个效果
dp保证了显示的物理大小相同

但是一般来说,高ppi手机屏幕实际上就比低的大,
有两台手机配置如下:
4.0英寸–800x480–233ppi
5.0英寸–1920x1080–441ppi

你按第一台手机上写了控件高度549dp(549*233/160=800),也就是整个屏幕,结果到了5.0英寸的手机上549dp占多长呢
549*441/160=1513px
也就是说在4.0手机上显示的全屏的控件 在5.0手机上只有78%(1513/1920),还有一部分是空余.

再说我们实际要求吧 其实我们想要的效果是显示比例相同
如图:
这里写图片描述
一个控件在小手机上显示占50% 那么 我想要在大屏幕上也显示占50%

相信大部分人都看过这样的文件夹
这里写图片描述

各种value 里面的dimen 配置不同的比例dp

这里用到了屏幕等分,让一个东西在所有手机上看起来比例都一样,我们把屏幕高等分成320(份数自己定 保证够细)份 然后计算出不同屏幕上 每一份对应的dp的值
比如
在800x480分辨率ppi233的屏幕上,将高分成320份,创建320个dimen值
dp=px*160/实际ppi=800*160/233=549.35
800px换成ppi下的dp就是549.35dp
dp与每一等份的关系如下

dimen_y_1=549.35 *1/320=1.716dp dimen_y_2=549.35 *2/320=3.433dpdimen_y_3=549.35 *3/320=4.609dp.........dimen_y_320=549.35 *320/320=549.35dp

在720*1280分辨率ppi312屏幕上 同样也是分成320份 属性值和上面一样
dp=px*160/ppi=1280*160/312=656.41
1280px换成ppi下的dp就是656.41dp 将 656.41dp平均分成320份

dimen_y_1=2.05dp dimen_y_2=4.10dpdimen_y_3=6.15dp.........dimen_320=656.41dp

这是设置高, 我们再设置宽的时候也加这个属性
dimen_x_1=XXXdp

这样我们设置的时候用我们自己的单位
android:layout_width=”@dimen/dimen_x_320”
android:layout_width=”@dimen/dimen_y_32”
如此 :
宽为全屏
高位10%

当然 分辨率太多不会要你自己一个个算,网上有写好的生成这些文件的脚本执行下就行了,代码如下:

import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.PrintWriter;public class MakeXml {    private final static String rootPath = "D:\\layoutroot\\values-{0}x{1}\\";    private 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) {        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;    }}
原创粉丝点击