美文网首页
android屏幕适配方案(一)

android屏幕适配方案(一)

作者: wenzb | 来源:发表于2017-09-22 14:30 被阅读0次

    三句话适配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定义变量值引用如:<dimen name="dp_1">1.3dp</dimen>,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="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n";
            for (int i = 1; i <= 640; i++) {
                double a=i;
                String b=df.format(a*swDp/360);
                str+="<dimen name=\"dp_"+i+"\">"+b+"dp</dimen>\n";
            }
            str+="</resources>";
    
            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出来放到项目。

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

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">
        <TextView
            android:id="@+id/textView"
            android:layout_width="@dimen/dp_300"
            android:layout_height="@dimen/dp_200"
            android:background="#f4546a"
            android:gravity="center"
            android:text="你好 世界"
            android:textColor="#ffffff"
            android:textSize="30sp" />
    
    </LinearLayout>
    
    4.0_480x800_233dpi_hdpi_sw320.png 4.7_720x1280_312dpi_xhdpi_sw360.png 5.0_1080x1920_440dpi_xxhdpi_sw431.png 5.5_1080x1920_400dpi_xxhdpi_sw431.png 6.0_1080x1920_367dpi_xxhdpi_sw480.png 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屏幕适配方案(一)

          本文链接:https://www.haomeiwen.com/subject/cxuvjxtx.html