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

2019-09-26  本文已影响0人  王志强_9380

由于不管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

看到和方法一一样的效果

上一篇下一篇

猜你喜欢

热点阅读