屏幕适配:自定义像素适配

作者: space0o0 | 来源:发表于2019-10-11 17:24 被阅读0次

    正常情况下,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>
    

    该方案比较简单理解,就不多啰嗦了。
    下一篇手撸百分比布局。

    相关文章

      网友评论

        本文标题:屏幕适配:自定义像素适配

        本文链接:https://www.haomeiwen.com/subject/xgrxmctx.html