Android 屏幕适配—自定义像素适配

作者: 大虾啊啊啊 | 来源:发表于2020-03-02 22:53 被阅读0次

1、思路

自定义像素适配,也就是自定义View进行适配,我们知道在我们的xml布局文件中都有一个容器或者N个容器,在View的绘制流程中我们知道,View的测量是先测量最里层的子View,那么每个子View的测量又是和他的父容器测量规格(MeasureSpec)以及自身的布局属性有关。当所有的子View测量完毕,再对父容器进行测量,父容器的测量大小也是根据所有子View测量大小,以及自身设置的一些属性等等计算而来。明白了View的测量原理之后,我们可以这样做,自定义一个容器,继承我们常用的RelativeLayout等,然后重写onMeasure方法,我们知道在容器的RelativeLayout的onMeasure方法中会对所有的子View进行测量,而子View的测量大小又和自身的设置属性有关,那么我们可以在onMeasure方法中获取所有的子View重新设置他的布局属性。那么具体要设置多少呢?
举个例子,设计图的标准为320720,设计图上的一个按钮为160px,刚好是屏幕的一半,那如果我们的目标设备为7201080,此时我们也希望我们的按钮是屏幕的一半,那我们需要在控件上写360px,但是设计图上的大小为160px,我们怎么知道写360px呢,通过上面的公式我们就可以计算出:360 = (720/320)*160。

2、示例

package com.netease.screenadapter.pixel;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;

public class ScreenAdapterLayout extends RelativeLayout {

    private boolean flag;

    public ScreenAdapterLayout(Context context) {
        super(context);
    }

    public ScreenAdapterLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScreenAdapterLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (!flag){
            float scaleX = Utils.getInstance(getContext()).getHorizontalScale();
            float scaleY = Utils.getInstance(getContext()).getVerticalScale();

            int count = getChildCount();
            for (int i = 0; i < count; i++) {
                View child = getChildAt(i);
                LayoutParams params = (LayoutParams) child.getLayoutParams();
                params.width = (int) (params.width * scaleX);
                params.height = (int) (params.height * scaleY);
                params.leftMargin = (int)(params.leftMargin * scaleX);
                params.rightMargin = (int)(params.rightMargin * scaleX);
                params.topMargin = (int)(params.topMargin * scaleY);
                params.bottomMargin = (int)(params.bottomMargin * scaleY);
            }
            flag = true;
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

package com.netease.screenadapter.pixel;

import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;

public class Utils {

    private static Utils utils;

    //这里是设计稿参考宽高
    private static final float STANDARD_WIDTH = 1080;
    private static final float STANDARD_HEIGHT = 1920;

    //这里是屏幕显示宽高
    private int mDisplayWidth;
    private int mDisplayHeight;

    private Utils(Context context){
        //获取屏幕的宽高
        if(mDisplayWidth == 0 || mDisplayHeight == 0){
            WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            if (manager != null){
                DisplayMetrics displayMetrics = new DisplayMetrics();
                manager.getDefaultDisplay().getMetrics(displayMetrics);
                if (displayMetrics.widthPixels > displayMetrics.heightPixels){
                    //横屏
                    mDisplayWidth = displayMetrics.heightPixels;
                    mDisplayHeight = displayMetrics.widthPixels;
                }else{
                    mDisplayWidth = displayMetrics.widthPixels;
                    mDisplayHeight = displayMetrics.heightPixels - getStatusBarHeight(context);
                }
            }
        }

    }

    public int getStatusBarHeight(Context context){
        int resID = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resID > 0){
            return context.getResources().getDimensionPixelSize(resID);
        }
        return 0;
    }

    public static Utils getInstance(Context context){
        if (utils == null){
            utils = new Utils(context.getApplicationContext());
        }
        return utils;
    }

    //获取水平方向的缩放比例
    public float getHorizontalScale(){
        return mDisplayWidth / STANDARD_WIDTH;
    }

    //获取垂直方向的缩放比例
    public float getVerticalScale(){
        return mDisplayHeight / STANDARD_HEIGHT;
    }

}

<?xml version="1.0" encoding="utf-8"?>
<com.netease.screenadapter.pixel.ScreenAdapterLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="540px"
        android:layout_height="540px"
        android:layout_marginLeft="10px"
        android:text="Hello World!"
        android:background="@color/colorAccent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</com.netease.screenadapter.pixel.ScreenAdapterLayout>

相关文章

网友评论

    本文标题:Android 屏幕适配—自定义像素适配

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