屏幕適配的一種解決方案

屏幕適配的一種解決方案

衆所周知,安卓屏幕適配一直以來是一個頭疼鬧熱的問題,市面上的解決方案也層出不羣,比如:google的百分比適配,還有像素目錄適配等,這裏要說的是另外的一種方式,而且這種方式幾乎能夠適配所有的屏幕

方法說明

其實很簡單,大致需要兩個步驟:

  • 根據ui切圖的尺寸與當前屏幕的尺寸計算出尺寸比例
  • 繼承需要適配的控件對需要的屬性進行一個縮放就行了

實現代碼

首先通過工具類得到尺寸比例

package com.example.screenadaptiondemo

import android.content.Context
import android.util.DisplayMetrics
import android.view.WindowManager
import java.lang.Exception

class UiUtils {

    companion object{
        private const val DIME_CLASS = "com.android.internal.R\$dimen"
        /**這兩個值一般是ui設計給出的標準的尺寸*/
        private const val UI_HEIGHT = 1920f
        private const val UI_WIDTH = 1080f

        /**當前屏幕除了狀態欄的寬度*/
        private var disPlayMetricsWidth = -1f
        /**當前屏幕除了狀態欄的高度*/
        private var disPlayMetricsHeight = -1f

        private var mUiUtils: UiUtils? = null
        fun getInstance(context: Context): UiUtils{
            if(mUiUtils == null){
                mUiUtils = UiUtils(context)
            }
            return mUiUtils!!
        }
    }

    private  var mContext: Context
    private constructor(context: Context){
        mContext = context
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager

        val disPlayMetrics = DisplayMetrics()
        if(disPlayMetricsHeight == -1f || disPlayMetricsWidth == -1f){
            windowManager.defaultDisplay.getMetrics(disPlayMetrics)
            val statusBarHeight = getStatusHeight(context)
            //判斷橫屏還是豎屏
            if(disPlayMetrics.widthPixels > disPlayMetrics.heightPixels){
                //橫屏
                disPlayMetricsWidth = disPlayMetrics.heightPixels.toFloat()
                disPlayMetricsHeight = (disPlayMetrics.widthPixels - statusBarHeight).toFloat()
            }else {
                disPlayMetricsWidth = disPlayMetrics.widthPixels.toFloat()
                disPlayMetricsHeight = (disPlayMetrics.heightPixels - statusBarHeight).toFloat()
            }
        }
    }


    /**
     * 得到寬度的比例值
     */
    fun getWidthScaleValue(): Float = (disPlayMetricsWidth/ UI_WIDTH)

    /**
     * 得到高度上的比例值
     */
    fun getHeightScaleValue(): Float  = (disPlayMetricsHeight / (UI_HEIGHT - getStatusHeight(mContext)))

    /**
     * 獲取狀態欄的高度
     */
    private fun getStatusHeight(context: Context): Int {
        return getValue(context, DIME_CLASS, "system_bar_height", 48)
    }

    private fun getValue(context: Context, dimeClass: String, sysbarHeight: String, defValue: Int): Int {
        try {
            val clazz = Class.forName(dimeClass)
            val obj = clazz.newInstance()
            val filedObj = clazz.getField(sysbarHeight)
            val statusHeight = filedObj.get(obj).toString().toInt()
            return context.resources.getDimensionPixelSize(statusHeight)
        }catch (e: Exception){
            return defValue
        }
        return defValue
    }
}

然後繼承需要適配的佈局控件,進行相關屬性值的計算

package com.example.screenadaptiondemo;

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

public class MyRelativeLayout extends RelativeLayout {

    private static final String TAG = "MyRelativeLayout";
    /**需要這個標誌來控制自己在onMeasure裏面寫的方法只走一次*/
    private boolean isFlag = false;
    public MyRelativeLayout(Context context) {
        super(context);
    }

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

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


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if(!isFlag){
            //拿到寬度與高度的比例值
            float scaleX = UiUtils.Companion.getInstance(getContext()).getWidthScaleValue();
            float scaleY = UiUtils.Companion.getInstance(getContext()).getHeightScaleValue();

            for (int i = 0; i < getChildCount(); i++) {
                LayoutParams layoutParams = (LayoutParams) getChildAt(i).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);

            }
            isFlag = true;
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

效果圖

left-1080p right-480p

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