欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

屏幕适配的一种解决方案

程序员文章站 2022-03-11 09:01:22
...

屏幕适配的一种解决方案

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

效果图

屏幕适配的一种解决方案

相关标签: android项目