android屏幕适配方案(一)

三句话适配android设备

①将(https://github.com/wenzb/ScreenAdaptive/tree/master/app/src/main/res)的values-sw320dp、values-sw360dp、values-sw431dp、values-sw480dp、values-sw540dp文件夹copy到项目res文件夹下。

②在布局文件用到dp时改成使用"@dimen/dp_**"形式,如:android:layout_width="200dp"改成android:layout_width="@dimen/dp_200"。

③在布局文件下Design选用Nexus4(4.7,768x1280,xhdpi)查看布局基准调整布局

适配原理

屏幕适配有多种方案这里选用dp适配方案,即使用不同values-sw**dp命名

sw指的是最小屏幕宽度即是手机屏幕宽度的dp值

在values的dimens.xml定义变量值引用如:1.3dp,android系统会根据屏幕的相关信息去取对应变量值

假设屏幕是属于sw360dp取出dp_1为1dp,假设屏幕属于480dp取出dp_1为1.3dp,通过这种方式从而实现屏幕适配

如何根据原理适配

android中各种单位的含义:
px:(像素) 屏幕上的小灯泡,假设是1920x1080可以理解为横向有1080个小灯泡排列
sp: scaled pixels(放大像素). 用于字体显示,会根据系统字体大小设置改变
dp(dip): (设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关
dpi:屏幕密度,每英寸(2.54cm)所含像素点,相当于ios的ppi,
density:概念跟dpi是一样,都是屏幕密度只是数值上等于dpi/160,余数不足时进0.5,假设148dpi/160 density=1 假设220dpi/160 density=1.5

dp跟dip是一样的,这个单位比较难理解但是根据运算公式:dp=px/(dpi/160) 或者是dp=px/density,dp跟像素还有屏幕密度有关,假设屏幕密度一定,当然屏幕越长或者说越多的像素dp值就增大

假设像素一定,分辨率越小dp就越大,同是假设1920x1080的6寸屏幕跟1920x1080的14寸平板,他们的屏幕长度不一样导致dpi不一样,所以根据公式可以知道这个1920x1080的14寸平板比1920x1080的6寸手机dp值大得多

谷歌提供的方案

核心是根据设备相关信息去取不同的res文件夹,如上面的例子,是根据不同sw取不同的资源文件,文件夹命名如下:
values-mcc310-en-sw320dp-w720dp-h720dp-large-long-port-car-night-ldpi-notouch-keysexposed-nokeys-navexposed-nonav-v7

属性是按优先级匹配先后排列出来的,各种含义:
values-mcc310(sim卡运营商)-en(语言)-sw320dp(屏幕最小宽度)-w720dp(屏幕最佳宽度)-h720dp(屏幕最佳高度)-large(屏幕尺寸)-long(屏幕长短边模式)-port(当前屏幕横竖屏显示模式)-car(dock模式)-night(白天或夜晚)-ldpi(屏幕最佳dpi)-notouch(触摸屏模类型)-keysexposed(键盘类型)-nokey(硬按键类型)-navexposed(方向键是否可用)-nonav(方向键类型)-v7(android版本)

假设我是横屏,屏幕是1920x1080 android系统就会去解析values-1920x1080-prot文件

同理layout文件夹也适用,所以在你开发项目的时候一定要知道你的app是会适用在哪些屏幕,如果你App运行在values-sw480dp的设备,但是你没有定义values-sw480dp文件,就会去解析相近sw-480dp的,最后都没有就会去匹配默认values

生成适配文件
public class MainActivity extends AppCompatActivity {
    DecimalFormat df = new DecimalFormat("0.0");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                saveDimens(320);
                saveDimens(360);
                saveDimens(431);
                saveDimens(480);
                saveDimens(540);
                saveDimens(768);
                saveDimens(1080);
            }
        }).start();
    }

    /**
     * 以sw360dp为基准在sd卡根目录生成对应dimens.xml 文件
     */
    private void saveDimens(int swDp){
        String str="\n\n";
        for (int i = 1; i <= 640; i++) {
            double a=i;
            String b=df.format(a*swDp/360);
            str+=""+b+"dp\n";
        }
        str+="";

        File file=new File(Environment.getExternalStorageDirectory()+"/"+"values-sw"+swDp+"dp");
        if (!file.exists()){
            file.mkdirs();
        }

        byte[] buff=str.getBytes();
        try {
            FileOutputStream out=new FileOutputStream(file.getPath()+"/dimens.xml");
            out.write(buff, 0, buff.length);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行上面的代码,几秒后进入手机根目录copy出来放到项目。

生成文件后,布局文件如下在各个手机屏幕上的效果



    


android屏幕适配方案(一)_第1张图片
4.0_480x800_233dpi_hdpi_sw320.png
android屏幕适配方案(一)_第2张图片
4.7_720x1280_312dpi_xhdpi_sw360.png
android屏幕适配方案(一)_第3张图片
5.0_1080x1920_440dpi_xxhdpi_sw431.png
android屏幕适配方案(一)_第4张图片
5.5_1080x1920_400dpi_xxhdpi_sw431.png
android屏幕适配方案(一)_第5张图片
6.0_1080x1920_367dpi_xxhdpi_sw480.png
android屏幕适配方案(一)_第6张图片
6.0_1440x2560_490dpi_xxxhdpi_sw480.png
授之于渔

是否有疑问这个320 360 431 480 540 是怎么来的?
这是目前市面上的主流手机dp值多去算算就知道了
假设android后面发展有其他奇葩或者更高清的屏幕,只需要改一下生成适配代码重新生成就可以了

同理如果要用px方案适配,生成类似values-1920x1080是一样的做法

为什么不使用px方案不是更精准吗?市面上的手机之间的px相差太大,比如480x800跟1440x2560,px适配方案可能在在不同的设备相差会几倍 ,如果处理不好布局就会大乱,而且很多奇葩分辨率,但dp就算是有问题相差也少看起来问题不大,总的来说dp设配比较稳

你可能感兴趣的:(android屏幕适配方案(一))