在 Android 开发中,不同设备的屏幕尺寸和分辨率千差万别,导致同一个界面在不同设备上的显示效果可能大相径庭。因此,为了在各种设备上都能呈现出优秀的 UI,开发者需要进行 UI 自适应的设计。
一、ScreenAdapterLayout
ScreenAdapterLayout 是一个自定义的继承自 RelativeLayout 的布局,它可以帮助开发者快速在不同尺寸的设备上实现 UI 自适应。使用 ScreenAdapterLayout 的过程也十分简单,只需将原来页面的根布局替换成 ScreenAdapterLayout 即可,ScreenAdapterLayout代码如下:
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;
/**
* 自定义布局,实现屏幕适配,将页面根布局换成 ScreenAdapterLayout
* <p>
* ScreenAdapterLayout 会在 onMeasure() 中计算子控件缩放后的尺寸和位置
*/
public class ScreenAdapterLayout extends RelativeLayout {
//flag 用于避免重复计算
private boolean flag;
public ScreenAdapterLayout(Context context) {
super(context);
}
public ScreenAdapterLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScreenAdapterLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//只有第一次 onMeasure 时才进行计算
if (!flag) {
//获取缩放比例
float scaleX = Utils.getInstance(getContext()).getHorizontalScale();
float scaleY = Utils.getInstance(getContext()).getVerticalScale();
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
LayoutParams params = (LayoutParams) child.getLayoutParams();
//根据缩放比例计算子控件的尺寸和位置
params.width = (int) (params.width * scaleX);
params.height = (int) (params.height * scaleY);
params.leftMargin = (int) (params.leftMargin * scaleX);
params.rightMargin = (int) (params.rightMargin * scaleX);
params.topMargin = (int) (params.topMargin * scaleY);
params.bottomMargin = (int) (params.bottomMargin * scaleY);
}
//标记已经计算过
flag = true;
}
//调用父类 onMeasure()
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
在 ScreenAdapterLayout 中,onMeasure() 方法被重写。在这个方法中,首先获取了屏幕的宽高和缩放比例。然后遍历布局中所有子 View,根据缩放比例对它们进行缩放。最后将 flag 设置为 true,避免重复缩放。
使用方法非常简单,只需将你原来的布局类改为 ScreenAdapterLayout 即可,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<com.study.pixel.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">
<TextView
android:layout_width="540px"
android:layout_height="540px"
android:layout_marginLeft="10px"
android:text="Hello World!"
android:background="@color/colorAccent"/>
</com.study.pixel.ScreenAdapterLayout>
二、Utils工具类
工具类Utils代码如下:
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;
public class Utils {
private static Utils utils;
//这里是设计稿参考宽高
private static final float STANDARD_WIDTH = 1080;
private static final float STANDARD_HEIGHT = 1920;
//这里是屏幕显示宽高
private int mDisplayWidth;
private int mDisplayHeight;
private Utils(Context context){
//获取屏幕的宽高
if(mDisplayWidth == 0 || mDisplayHeight == 0){
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (manager != null){
DisplayMetrics displayMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(displayMetrics);
if (displayMetrics.widthPixels > displayMetrics.heightPixels){
//横屏
mDisplayWidth = displayMetrics.heightPixels;
mDisplayHeight = displayMetrics.widthPixels;
}else{
mDisplayWidth = displayMetrics.widthPixels;
mDisplayHeight = displayMetrics.heightPixels - getStatusBarHeight(context);
}
}
}
}
public int getStatusBarHeight(Context context){
int resID = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resID > 0){
return context.getResources().getDimensionPixelSize(resID);
}
return 0;
}
public static Utils getInstance(Context context){
if (utils == null){
utils = new Utils(context.getApplicationContext());
}
return utils;
}
//获取水平方向的缩放比例
public float getHorizontalScale(){
return mDisplayWidth / STANDARD_WIDTH;
}
//获取垂直方向的缩放比例
public float getVerticalScale(){
return mDisplayHeight / STANDARD_HEIGHT;
}
}
这是工具类 Utils,用于计算设备屏幕尺寸与设计稿尺寸的比例。
首先,在类中定义了两个常量:STANDARD_WIDTH 和 STANDARD_HEIGHT,表示设计稿的宽度和高度,即 UI 设计师设计时所参考的标准尺寸。
其次,该类的构造函数 Utils(Context context) 中获取了屏幕的宽高,并将其存储在成员变量 mDisplayWidth 和 mDisplayHeight 中。如果 mDisplayWidth 和 mDisplayHeight 已经被赋值,就不会再次获取屏幕宽高。该构造函数还调用了 getStatusBarHeight(Context context) 方法,用于获取状态栏的高度。
getStatusBarHeight(Context context) 方法通过获取系统资源的方式,获得了状态栏的高度,并返回这个值。在计算高度的缩放比例时,要减去状态栏的高度,避免状态栏影响缩放比例。
getInstance(Context context) 方法是单例模式的实现,它用于获取 Utils 类的实例。如果 utils 为 null,就创建一个 Utils 对象并返回。否则,直接返回 utils。
最后,getHorizontalScale() 和 getVerticalScale() 方法用于计算水平方向和垂直方向的缩放比例。它们分别将屏幕的宽高与设计稿的宽高相除,得到一个缩放比例。这些方法可以帮助开发者在不同尺寸的设备上实现 UI 的自适应。文章来源:https://www.toymoban.com/news/detail-835982.html
如果设计稿的屏幕宽度为1080,设置一个宽度为540的TextView,android:layout_width="540px",将ScreenAdapterLayout设置成根布局,那么不管在任何屏幕尺寸的设备上,TextView的宽度都会显示成屏幕宽度的一半。文章来源地址https://www.toymoban.com/news/detail-835982.html
到了这里,关于实现 Android UI 自适应的最佳实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!