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);
}
}