美文网首页
屏幕适配(二)——自定义像素适配

屏幕适配(二)——自定义像素适配

作者: 王志强_9380 | 来源:发表于2019-09-26 19:32 被阅读0次

    由于不管dp、sp、pt,最终显示在屏幕上的时候,都是px,那么我们在做设计图的时候,可以以px为基准来设计,然后在显示的时候,获取屏幕的分辨率,计算出比例,缩放坐标。最终达到屏幕适配

    首先需要设置一个基准值,这个基准值的单位是px

    public static final float STANDARD_WIDTH = 1080f;
    public static final float STANDARD_HEIGHT = 1920f;
    

    然后我们可以通过windowManager.getDefaultDisplay().getMetrics(displayMetrics);获取到屏幕的分辨率

    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics displayMetrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(displayMetrics);
    //windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
    if (displayMetrics.widthPixels > displayMetrics.heightPixels) {
        //横屏
        this.displayMetricsWidth = displayMetrics.heightPixels;
        this.displayMetricsHeight = displayMetrics.widthPixels;
    } else {
        //竖屏
        this.displayMetricsWidth = displayMetrics.widthPixels;
        this.displayMetricsHeight = displayMetrics.heightPixels;
    }
    

    上面的getMetrics是获取当前窗口的分辨率,不包括虚拟按键。getRealMetrics是获取完整的分辨率。
    然后就可以计算缩放比例了

    public float getHorizontalScaleValue() {
        return displayMetricsWidth / STANDARD_WIDTH;
    }
    public float getVerticalScaleValue() {
    
        return displayMetricsHeight / STANDARD_HEIGHT;
    }
    public int getWidth(int width) {
        return Math.round((float) width * this.displayMetricsWidth / STANDARD_WIDTH);
    }
    public int getHeight(int height) {
        return Math.round((float) height * this.displayMetricsHeight / STANDARD_HEIGHT);
    }
    

    缩放系数得到了,然后就是对布局进行缩放了
    这里有两个做法,第一个,自定义容器,第二个,直接修改子View大小和位置

    测试机
    机器 尺寸(英寸) widthPixels heightPixels 对角线 计算出的densityDpi densityDpi density
    机器A 10.5 1920 1200 2264 215.6 240 1.5
    机器D 6 2160 1080 2415 402.5 420 2.625
    自定义容器

    在容器类测量(Measure)的时候,直接修改对子View遍历

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (flag) {
    
            flag = false;
            float scaleX = UIUtils.getInstance(getContext()).getHorizontalScaleValue();
            float scaleY = UIUtils.getInstance().getVerticalScaleValue();
            int childCount = this.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = this.getChildAt(i);
                LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
                layoutParams.width = (int) (layoutParams.width * scaleX);
                layoutParams.height = (int) (layoutParams.height * scaleY);
                layoutParams.leftMargin = (int) (layoutParams.leftMargin * scaleX);
                layoutParams.rightMargin = (int) (layoutParams.rightMargin * scaleX);
                layoutParams.topMargin = (int) (layoutParams.topMargin * scaleY);
                layoutParams.bottomMargin = (int) (layoutParams.bottomMargin * scaleY);
            }
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    

    我们在布局中测试一下
    假设ui给的图的基准是1280*800 px
    TextView要求占据屏幕的1/4,那么就是320*200

    <?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:orientation="horizontal">
    
        <com.example.screenfit.custom.UIRelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
    
            <TextView
                android:text="容器内自适应200*320px"
                android:layout_width="200px"
                android:layout_height="320px"
                android:background="#50f0" />
        </com.example.screenfit.custom.UIRelativeLayout>
    
        <TextView
            android:text="200*320px"
            android:layout_width="200px"
            android:layout_height="320px"
            android:background="#5f0f" />
        <TextView
            android:text="200*320dp"
            android:layout_width="200dp"
            android:layout_height="320dp"
            android:background="#5ff0" />
    </LinearLayout>
    

    注意,容器内子View的大小的单位是px,如果是dp,就会先转成px再缩放,那样大小就不对了

    看下结果


    2222222.png
    修改子View大小

    接下来看看修改子View大小
    因为是直接获取到子View并修改大小,我们要知道父布局是什么并且去获取响应的LayoutParams,我们的父布局是LinearLayout,那么我们就要相应的去获取LinearLayout.LayoutParams,修改大小后,再把LayoutParams设置回去

    public static void setViewLinearLayoutParam(View view, int width, int height, int topMargin, int bottomMargin, int lefMargin,
                                                    int rightMargin, boolean asWidth) {
    
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view.getLayoutParams();
        if (width != RelativeLayout.LayoutParams.MATCH_PARENT && width != RelativeLayout.LayoutParams.WRAP_CONTENT && width != RelativeLayout.LayoutParams.FILL_PARENT) {
            layoutParams.width = UIUtils.getInstance().getWidth(width);
        } else {
            layoutParams.width = width;
        }
        if (height != RelativeLayout.LayoutParams.MATCH_PARENT && height != RelativeLayout.LayoutParams.WRAP_CONTENT && height != RelativeLayout.LayoutParams.FILL_PARENT) {
            layoutParams.height = asWidth ? UIUtils.getInstance().getWidth(height) : UIUtils.getInstance().getHeight(height);
        } else {
            layoutParams.height = height;
        }
    
        layoutParams.topMargin = asWidth ? UIUtils.getInstance().getWidth(topMargin) : UIUtils.getInstance().getHeight(topMargin);
        layoutParams.bottomMargin = asWidth ? UIUtils.getInstance().getWidth(bottomMargin) : UIUtils.getInstance().getHeight(bottomMargin);
        layoutParams.leftMargin = UIUtils.getInstance().getWidth(lefMargin);
        layoutParams.rightMargin = UIUtils.getInstance().getWidth(rightMargin);
        view.setLayoutParams(layoutParams);
    }
    

    布局文件

    <?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:orientation="horizontal">
    
        <!--<com.example.screenfit.custom.UIRelativeLayout-->
            <!--android:layout_width="wrap_content"-->
            <!--android:layout_height="wrap_content">-->
    
            <!--<TextView-->
                <!--android:text="容器内自适应200*320px"-->
                <!--android:layout_width="200px"-->
                <!--android:layout_height="320px"-->
                <!--android:background="#50f0" />-->
        <!--</com.example.screenfit.custom.UIRelativeLayout>-->
        <TextView
            android:id="@+id/text"
            android:text="容器内自适应200*320px"
            android:layout_width="200px"
            android:layout_height="320px"
            android:background="#50f0" />
        <TextView
            android:text="200*320px"
            android:layout_width="200px"
            android:layout_height="320px"
            android:background="#5f0f" />
        <TextView
            android:text="200*320dp"
            android:layout_width="200dp"
            android:layout_height="320dp"
            android:background="#5ff0" />
    </LinearLayout>
    

    然后在activity中重新设置大小

    TextView text = findViewById(R.id.text);
    UIUtils.getInstance(this);
    ViewCalculateUtil.setViewLinearLayoutParam(text, 200, 320, 0, 0, 0, 0, true);
    

    看下效果图


    device-2019-09-20-103839_spec.png

    看到和方法一一样的效果

    相关文章

      网友评论

          本文标题:屏幕适配(二)——自定义像素适配

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