天天看點

Android螢幕适配(2)

方案二:

自定義,按設計比例縮放,先簡單說下原理:

開發設計的時候會有參照尺寸,比如1080*1920,後續在不同手機上使用時,按照長寬算出比例系數,對每個控件重新計算長寬

先寫工具類

public class ScreenMatchUtils {
    private Context context;

    //單例
    private static ScreenMatchUtils screenMatchUtils;
    public static ScreenMatchUtils getInstance(Context context){
        if(screenMatchUtils == null){
            screenMatchUtils=new ScreenMatchUtils(context);
        }
        return screenMatchUtils;
    }

    //設計寬高
    public final float DESIGN_WIDTH = 1080;
    public final float DESIGN_HEIGHT = 1920;

    //實際可用寬高(有虛拟按鍵的要去掉虛拟按鍵)
    public float actualUseWidth;
    public float actualUseHeight;

    //用反射從R中擷取狀态欄高度
    public final String DIMEN_CLASS = "com.android.internal.R$dimen";

    private ScreenMatchUtils(Context context){
        this.context=context;

        //擷取目前裝置可用寬高
        DisplayMetrics displayMetrics = new DisplayMetrics();
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        //windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);//擷取的是螢幕所有尺寸包括虛拟按鍵
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);//不包括虛拟按鍵

        if(actualUseHeight == 0.0f || actualUseWidth == 0.0f){
            //用反射從R中擷取狀态欄高度,擷取失敗則用預設值48
            int systemBarHeight =getValue(context,"system_bar_height",48);

            if(displayMetrics.widthPixels > displayMetrics.heightPixels){
                //橫屏
                actualUseWidth = displayMetrics.heightPixels;
                actualUseHeight = displayMetrics.widthPixels - systemBarHeight;
            }else{
                //豎屏
                actualUseWidth = displayMetrics.widthPixels;
                actualUseHeight = displayMetrics.heightPixels - systemBarHeight;
            }
        }
    }

    public int getValue(Context context,String sysId,int defValue){
        try{
            Class<?> clazz = Class.forName(DIMEN_CLASS);
            Object o = clazz.newInstance();
            Field field =clazz.getField(sysId);
            int x = (int) field.get(o);
            return  context.getResources().getDimensionPixelOffset(x);
        }catch (Exception e){
            return  defValue;
        }
    }

    //X系數
    public float getScaleX(){
        return actualUseWidth/DESIGN_WIDTH;
    }

    //Y系數
    public float getScaleY(){
        return actualUseHeight/DESIGN_HEIGHT;
    }
}
           

再寫布局類繼承自系統布局,比如ConstraintLayout,也可以重寫控件類,這裡隻提供一種思路,具體根據實際情況處理

重寫onMeasure,這裡用剛才的工具類得到系數,重新測量

//安卓測量會測兩次,加個辨別,隻測一次
    public static boolean flag = true;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if(flag){
            int count = this.getChildCount();
            float scaleX = ScreenMatchUtils.getInstance(this.getContext()).getScaleX();
            float scaleY = ScreenMatchUtils.getInstance(this.getContext()).getScaleY();

            //循環子控件
            for (int i = 0;i < count;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);
            }
            flag = false;
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
           

針對劉海屏的沉浸式布局這裡就不寫了,網上資源很多,這種劉海屏也隻是過渡,随着技術的發展以後一定會把劉海砍掉,後面如果工作中遇到再整了解決方案發出來