思路:通过计算设计稿上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>