正常情况下,ui设计的图都是按照一款机型的宽高作为标准。android中机型众多,宽高比不同,也加大了适配的复杂度。
本文将介绍一种思路,用来解决控件的适配,自动根据当前机型的宽高,缩放控件。
比如,ui以1280*720的手机作为设计尺寸的标准。设计图中也都是以像素为单位,标注各个view的宽高和间距。一般我们会把px转换成dp,这里,我将直接使用px作为单位使用。
首先介绍下思路,后面再贴出主要代码。
思路:
标准机型的宽 / 当前机型的宽 = 标准view的宽 / 实际显示view的宽。
根据显示机型和参考机型的比例,来缩放view。
代码
首先创建一个类,用来获取当前机型的屏幕尺寸,计算出宽高的缩放比例
public class Utils {
private static Utils utils;
//效果图标准尺寸为1280*720
private final float UI_HEIGHT = 1280;
private final float UI_WIDTH = 720;
//记录屏幕尺寸
private float screenWidth;
private float screenHeight;
private float statusBarHeight;
private Utils(Context context) {
screenMeasure(context);
getStatusBarHeight(context);
}
public static Utils getInstance(Context context) {
if (utils == null) {
utils = new Utils(context.getApplicationContext());
}
return utils;
}
/**
* 获取屏幕的宽高
*
* @param context
*/
private void screenMeasure(Context context) {
if (screenWidth == 0 || screenHeight == 0) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (wm != null) {
DisplayMetrics displayMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(displayMetrics);
screenHeight = displayMetrics.heightPixels;
screenWidth = displayMetrics.widthPixels;
}
}
}
/**
* 获取屏幕的状态栏高度
*
* @param context
* @return
*/
private void getStatusBarHeight(Context context) {
int resID = context.getResources().getIdentifier(“status_bar_height”, “dimen”, “android”);
if (resID > 0) {
statusBarHeight = context.getResources().getDimensionPixelSize(resID);
} else {
statusBarHeight = 0f;
}
}
/**
* 获得横向缩放比例
*
* @return
*/
public float getHorizontalScale() {
return screenWidth / UI_WIDTH;
}
/**
* 获得竖直方向缩放比例
*
* @return
*/
public float getVerticalScale() {
return screenHeight / UI_HEIGHT;
}
/**
* 获得状态栏高度
*
* @return
*/
public float getStatusBarHeight() {
return statusBarHeight;
}
}
自定义一个layout,用来改变子view的宽高,这里以RelativeLayout为例。
获取当前机型和标准机型的宽高比例,遍历所有的子view,修改子view的宽高。
/**
* 屏幕适配:按效果图自动缩放内部控件
*/
public class ScreenAdapterLayout extends RelativeLayout {
/**
* 标记是否缩放子view,防止多次缩放。
*/
private boolean hasScale = false;
public ScreenAdapterLayout(Context context) {
this(context, null);
}
public ScreenAdapterLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScreenAdapterLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!hasScale) {
//得到缩放比例
float horizontalScale = Utils.getInstance(getContext()).getHorizontalScale();
float verticalScale = Utils.getInstance(getContext()).getVerticalScale();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
//动态缩放子view的宽高
layoutParams.width = (int) (layoutParams.width * horizontalScale);
layoutParams.height = (int) (layoutParams.height * verticalScale);
//考虑子view的margin间隔
layoutParams.leftMargin = (int) (layoutParams.leftMargin * horizontalScale);
layoutParams.rightMargin = (int) (layoutParams.rightMargin * horizontalScale);
layoutParams.topMargin = (int) (layoutParams.topMargin * verticalScale);
layoutParams.bottomMargin = (int) (layoutParams.bottomMargin * verticalScale);
child.setLayoutParams(layoutParams);
}
hasScale = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
xml中,直接使用自定义layout。以px为单位,等比适配所有机型。
<space.learning.myui.screenAdapter.layout.ScreenAdapterLayout 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=“.screenAdapter.ScreenAdapterActivity”>
<TextView
android:layout_width="360px"
android:layout_height="360px"
android:background="@color/colorPrimary" />
</space.learning.myui.screenAdapter.layout.ScreenAdapterLayout>
该方案比较简单理解,就不多啰嗦了。
下一篇手撸百分比布局。
网友评论