屏幕适配的一种解决方案

android屏幕适配

  • 屏幕适配的一种解决方案
    • 方法说明
    • 实现代码
    • 效果图

屏幕适配的一种解决方案

众所周知,安卓屏幕适配一直以来是一个头疼闹热的问题,市面上的解决方案也层出不群,比如: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);
    }
}

效果图

屏幕适配的一种解决方案_第1张图片

你可能感兴趣的:(android项目)