方案二:
自定義,按設計比例縮放,先簡單說下原理:
開發設計的時候會有參照尺寸,比如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);
}
針對劉海屏的沉浸式布局這裡就不寫了,網上資源很多,這種劉海屏也隻是過渡,随着技術的發展以後一定會把劉海砍掉,後面如果工作中遇到再整了解決方案發出來