高性能屏幕適配解決方案

思路:通過計算設計稿上UI的 寬高與實際設備上的寬高,按比例縮放。
float scaleX = deviceWidth/standWidth;
float scaleY = deviceHeight/standHeight;

步驟:
1.自定義ViewGroup 重寫 onMeasure方法,根據scale比例,重新縮放childview。
2. 縮放margin、padding。
3. 使用自定義的ViewGroup作爲Activity的根佈局。

package com.example.screenscale;

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

/**
 * 作爲根佈局,放到xml中
 */
public class NewRelativeLayout extends RelativeLayout {
    public NewRelativeLayout(Context context) {
        super(context);
    }

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

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

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        float scaleX = UiUtil.getInstance(getContext()).getHorizontalScaleV();
        float scaleY = UiUtil.getInstance(getContext()).getVerticalScaleV();
        int childCount = getChildCount();
        for (int i=0;i>childCount;i++){
            View child = getChildAt(i);
            RelativeLayout.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);
        }
        //這裏要注意由於繼承自RelativeLayout。其會對child 進行兩次測量onMeasure。
        // 所以這裏的重寫也會執行兩次,導致兩次縮放。因此要限制只執行一次,這裏可以加標記限制。
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

package com.example.screenscale;

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

import java.lang.reflect.Field;

public class UiUtil {

    public static final float STANDARD_WIDTH = 1080f;
    public static final float STANDARD_HEIGHT = 1920f;
    private static final String DIMEN_CLASS = "com.android.internal.R$dimen";
    public static float displayMetricsWidth;
    public static float displayMetricsHeight;
    private Context mContext;
    public static UiUtil instance;
    public static UiUtil getInstance(Context context){
        if(instance == null){
            instance = new UiUtil(context);
        }
        return instance;
    }
   private UiUtil(Context context){
       mContext = context;
       WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
       DisplayMetrics displayMetrics = new DisplayMetrics();
       if(displayMetricsWidth == 0.0f||displayMetricsHeight == 0.0f){
           windowManager.getDefaultDisplay().getMetrics(displayMetrics);
            int systemBarHeight = getSystemBarHeight(context);
            if(displayMetrics.widthPixels>displayMetrics.heightPixels){
                //橫屏
                displayMetricsWidth = displayMetrics.heightPixels;
                displayMetricsHeight = displayMetrics.widthPixels-systemBarHeight;
            }else {
                displayMetricsWidth = displayMetrics.widthPixels;
                displayMetricsHeight = displayMetrics.heightPixels-systemBarHeight;
            }
       }
   }

    private int getSystemBarHeight(Context context) {
        return  getValue(context,DIMEN_CLASS,"system_bar_height",48);
    }

    private int getValue(Context context, String dimenClass, String attrName, int defaultV) {
        try {
            Class<?> clz = Class.forName(dimenClass);
            Object obj = clz.newInstance();
            Field field = clz.getField(attrName);
            int id = Integer.parseInt(field.get(obj).toString());
            return context.getResources().getDimensionPixelSize(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return defaultV;
    }

    public  float getHorizontalScaleV(){

        return ( (float)displayMetricsWidth)/STANDARD_WIDTH;
    }
    public  float getVerticalScaleV(){

        return  ((float)displayMetricsHeight)/(STANDARD_HEIGHT-getSystemBarHeight(mContext));
    }

}

<?xml version="1.0" encoding="utf-8"?>
<com.example.screenscale.NewRelativeLayout 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"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:text="Hello World!"
     />
    <TextView
        android:layout_marginTop="100px"
        android:layout_width="200px"
        android:layout_height="200px"
        android:text="Hello World!"
        />

</com.example.screenscale.NewRelativeLayout>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章