思路:通過計算設計稿上UI的 寬高與實際設備上的寬高,按比例縮放。
float scaleX = deviceWidth/standWidth;
float scaleY = deviceHeight/standHeight;
步驟:
1.自定義ViewGroup 重寫 onMeasure方法,根據scale比例,重新縮放childview。
2. 縮放margin、padding。
3. 使用自定義的ViewGroup作爲Activity的根佈局。
package com.example.screenscale;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
/**
* 作爲根佈局,放到xml中
*/
public class NewRelativeLayout extends RelativeLayout {
public NewRelativeLayout(Context context) {
super(context);
}
public NewRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NewRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public NewRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
float scaleX = UiUtil.getInstance(getContext()).getHorizontalScaleV();
float scaleY = UiUtil.getInstance(getContext()).getVerticalScaleV();
int childCount = getChildCount();
for (int i=0;i>childCount;i++){
View child = getChildAt(i);
RelativeLayout.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);
}
//這裏要注意由於繼承自RelativeLayout。其會對child 進行兩次測量onMeasure。
// 所以這裏的重寫也會執行兩次,導致兩次縮放。因此要限制只執行一次,這裏可以加標記限制。
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
package com.example.screenscale;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import java.lang.reflect.Field;
public class UiUtil {
public static final float STANDARD_WIDTH = 1080f;
public static final float STANDARD_HEIGHT = 1920f;
private static final String DIMEN_CLASS = "com.android.internal.R$dimen";
public static float displayMetricsWidth;
public static float displayMetricsHeight;
private Context mContext;
public static UiUtil instance;
public static UiUtil getInstance(Context context){
if(instance == null){
instance = new UiUtil(context);
}
return instance;
}
private UiUtil(Context context){
mContext = context;
WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
if(displayMetricsWidth == 0.0f||displayMetricsHeight == 0.0f){
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
int systemBarHeight = getSystemBarHeight(context);
if(displayMetrics.widthPixels>displayMetrics.heightPixels){
//橫屏
displayMetricsWidth = displayMetrics.heightPixels;
displayMetricsHeight = displayMetrics.widthPixels-systemBarHeight;
}else {
displayMetricsWidth = displayMetrics.widthPixels;
displayMetricsHeight = displayMetrics.heightPixels-systemBarHeight;
}
}
}
private int getSystemBarHeight(Context context) {
return getValue(context,DIMEN_CLASS,"system_bar_height",48);
}
private int getValue(Context context, String dimenClass, String attrName, int defaultV) {
try {
Class<?> clz = Class.forName(dimenClass);
Object obj = clz.newInstance();
Field field = clz.getField(attrName);
int id = Integer.parseInt(field.get(obj).toString());
return context.getResources().getDimensionPixelSize(id);
} catch (Exception e) {
e.printStackTrace();
}
return defaultV;
}
public float getHorizontalScaleV(){
return ( (float)displayMetricsWidth)/STANDARD_WIDTH;
}
public float getVerticalScaleV(){
return ((float)displayMetricsHeight)/(STANDARD_HEIGHT-getSystemBarHeight(mContext));
}
}
<?xml version="1.0" encoding="utf-8"?>
<com.example.screenscale.NewRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="40dp"
android:layout_height="40dp"
android:text="Hello World!"
/>
<TextView
android:layout_marginTop="100px"
android:layout_width="200px"
android:layout_height="200px"
android:text="Hello World!"
/>
</com.example.screenscale.NewRelativeLayout>