屏幕适配

一些关于屏幕的概念:

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.469

Dpi跟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.433dp
dimen_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.10dp
dimen_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;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值