当前位置:   article > 正文

实现 Android UI 自适应的最佳实践_android 自适应设计

android 自适应设计

        在 Android 开发中,不同设备的屏幕尺寸和分辨率千差万别,导致同一个界面在不同设备上的显示效果可能大相径庭。因此,为了在各种设备上都能呈现出优秀的 UI,开发者需要进行 UI 自适应的设计。

一、ScreenAdapterLayout

        ScreenAdapterLayout 是一个自定义的继承自 RelativeLayout 的布局,它可以帮助开发者快速在不同尺寸的设备上实现 UI 自适应。使用 ScreenAdapterLayout 的过程也十分简单,只需将原来页面的根布局替换成 ScreenAdapterLayout 即可,ScreenAdapterLayout代码如下:

  1. import android.content.Context;
  2. import android.util.AttributeSet;
  3. import android.view.View;
  4. import android.widget.RelativeLayout;
  5. /**
  6. * 自定义布局,实现屏幕适配,将页面根布局换成 ScreenAdapterLayout
  7. * <p>
  8. * ScreenAdapterLayout 会在 onMeasure() 中计算子控件缩放后的尺寸和位置
  9. */
  10. public class ScreenAdapterLayout extends RelativeLayout {
  11. //flag 用于避免重复计算
  12. private boolean flag;
  13. public ScreenAdapterLayout(Context context) {
  14. super(context);
  15. }
  16. public ScreenAdapterLayout(Context context, AttributeSet attrs) {
  17. super(context, attrs);
  18. }
  19. public ScreenAdapterLayout(Context context, AttributeSet attrs, int defStyleAttr) {
  20. super(context, attrs, defStyleAttr);
  21. }
  22. @Override
  23. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  24. //只有第一次 onMeasure 时才进行计算
  25. if (!flag) {
  26. //获取缩放比例
  27. float scaleX = Utils.getInstance(getContext()).getHorizontalScale();
  28. float scaleY = Utils.getInstance(getContext()).getVerticalScale();
  29. int count = getChildCount();
  30. for (int i = 0; i < count; i++) {
  31. View child = getChildAt(i);
  32. LayoutParams params = (LayoutParams) child.getLayoutParams();
  33. //根据缩放比例计算子控件的尺寸和位置
  34. params.width = (int) (params.width * scaleX);
  35. params.height = (int) (params.height * scaleY);
  36. params.leftMargin = (int) (params.leftMargin * scaleX);
  37. params.rightMargin = (int) (params.rightMargin * scaleX);
  38. params.topMargin = (int) (params.topMargin * scaleY);
  39. params.bottomMargin = (int) (params.bottomMargin * scaleY);
  40. }
  41. //标记已经计算过
  42. flag = true;
  43. }
  44. //调用父类 onMeasure()
  45. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  46. }
  47. }

         在 ScreenAdapterLayout 中,onMeasure() 方法被重写。在这个方法中,首先获取了屏幕的宽高和缩放比例。然后遍历布局中所有子 View,根据缩放比例对它们进行缩放。最后将 flag 设置为 true,避免重复缩放。

        使用方法非常简单,只需将你原来的布局类改为 ScreenAdapterLayout 即可,如下所示:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <com.study.pixel.ScreenAdapterLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent">
  7. <TextView
  8. android:layout_width="540px"
  9. android:layout_height="540px"
  10. android:layout_marginLeft="10px"
  11. android:text="Hello World!"
  12. android:background="@color/colorAccent"/>
  13. </com.study.pixel.ScreenAdapterLayout>

二、Utils工具类

工具类Utils代码如下:

  1. import android.content.Context;
  2. import android.util.DisplayMetrics;
  3. import android.view.WindowManager;
  4. public class Utils {
  5. private static Utils utils;
  6. //这里是设计稿参考宽高
  7. private static final float STANDARD_WIDTH = 1080;
  8. private static final float STANDARD_HEIGHT = 1920;
  9. //这里是屏幕显示宽高
  10. private int mDisplayWidth;
  11. private int mDisplayHeight;
  12. private Utils(Context context){
  13. //获取屏幕的宽高
  14. if(mDisplayWidth == 0 || mDisplayHeight == 0){
  15. WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  16. if (manager != null){
  17. DisplayMetrics displayMetrics = new DisplayMetrics();
  18. manager.getDefaultDisplay().getMetrics(displayMetrics);
  19. if (displayMetrics.widthPixels > displayMetrics.heightPixels){
  20. //横屏
  21. mDisplayWidth = displayMetrics.heightPixels;
  22. mDisplayHeight = displayMetrics.widthPixels;
  23. }else{
  24. mDisplayWidth = displayMetrics.widthPixels;
  25. mDisplayHeight = displayMetrics.heightPixels - getStatusBarHeight(context);
  26. }
  27. }
  28. }
  29. }
  30. public int getStatusBarHeight(Context context){
  31. int resID = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
  32. if (resID > 0){
  33. return context.getResources().getDimensionPixelSize(resID);
  34. }
  35. return 0;
  36. }
  37. public static Utils getInstance(Context context){
  38. if (utils == null){
  39. utils = new Utils(context.getApplicationContext());
  40. }
  41. return utils;
  42. }
  43. //获取水平方向的缩放比例
  44. public float getHorizontalScale(){
  45. return mDisplayWidth / STANDARD_WIDTH;
  46. }
  47. //获取垂直方向的缩放比例
  48. public float getVerticalScale(){
  49. return mDisplayHeight / STANDARD_HEIGHT;
  50. }
  51. }

         这是工具类 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 的自适应。

        如果设计稿的屏幕宽度为1080,设置一个宽度为540的TextView,android:layout_width="540px",将ScreenAdapterLayout设置成根布局,那么不管在任何屏幕尺寸的设备上,TextView的宽度都会显示成屏幕宽度的一半。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/332384
推荐阅读
相关标签
  

闽ICP备14008679号