美文网首页程序员Android技术知识Android开发
android 屏幕适配一:通过自定义View的方式实现适配

android 屏幕适配一:通过自定义View的方式实现适配

作者: cff70524f5cf | 来源:发表于2019-03-23 22:47 被阅读22次

    实现原理

    以一个特定的宽度尺寸的设备为参考,在View加载的过程中,根据当前设备的实际像素换算出目标像素,再作用到控件上。

    通常UI给我们的设计稿只有一种像素的标准,例如720 * 1280。 例如在设计稿上有一个控件宽度为屏幕尺寸的一半,即360px,假设我们真机的屏幕尺寸为1080 * 1920像素,我们再布局中设置控件尺寸也为360px,则显示为屏幕的三分之一。但是我们想要效果仍然是显示屏幕的一半。即宽度应该设置为540px,这里的540px是如何得到的呢,这就是通过真实屏幕尺寸与参考设计稿的尺寸比例来得到的,即:(1080/720)*360 = 540。

    下面通过代码来实现这一功能:
    public class Utils {
        private static Utils utils;
    
        //这是设计稿参考的宽高
        private static final float STANDARD_WIDTH = 720;
        private static final float STANDARD_HEIGHT = 1080;
    
        //这里是屏幕的显示宽高
        private int mDisPlayWidth;
        private int mDisPlayHeight;
    
        public static Utils getInstance(Context context) {
            if (utils == null) {
                utils = new Utils(context.getApplicationContext()); //获取application的context是防止内存泄漏
            }
            return utils;
        }
    
        private Utils(Context context) {
            //获取屏幕的宽高
            if (mDisPlayHeight == 0 || mDisPlayWidth == 0) { //宽高还未赋值
                WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
                if (manager != null) {
                    DisplayMetrics displayMetrics = new DisplayMetrics();
                    manager.getDefaultDisplay().getMetrics(displayMetrics); //此时displayMetrics就可以获取到屏幕宽高信息了
                    if (displayMetrics.widthPixels > displayMetrics.heightPixels) {
                        //横屏
                        mDisPlayWidth = displayMetrics.heightPixels;
                        mDisPlayHeight = displayMetrics.widthPixels - getStatusBarHeight(context);
                    } 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 float getHorizontalScale() {
            return mDisPlayWidth / STANDARD_WIDTH;
        }
    
        //获取垂直方向的缩放比例
        public float getVerticalScale() {
            return mDisPlayHeight / STANDARD_HEIGHT;
        }
    
    }
    
    

    Utils工具类用来计算设计稿屏幕分辨率和真实屏幕分辨率的比例。

    下面以RelativeLayout为例:

    public class ScreenAdapterLayout extends RelativeLayout {
    
        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) {
            //计算宽高之前获取缩放比例的值
            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.leftMargin * scaleY);
                    params.bottomMargin = (int) (params.leftMargin * scaleY);
                }
                flag = true;
            }
    
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
    

    下面在资源布局中使用ScreenAdapterLayout。

    image.png

    这里我设置的宽度为360px,我手机的像素为1080*2248,但是显示的view的宽度仍然为屏幕的一半。这是因为根据Utils把view的宽高做了换算。我们不需要关注真实屏幕的分辨率。只需要根据设计稿的分辨率来设置view的宽高。

    image.png
    【附】相关架构及资料
    image

    资料领取

    点赞+加群免费获取 Android IOC架构设计

    加群领取获取往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

    相关文章

      网友评论

        本文标题:android 屏幕适配一:通过自定义View的方式实现适配

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