Android屏幕适配之自定义View屏幕适配

Android屏幕适配一直都是一个让人头疼的问题,到底要怎么做才能让自己那完美无瑕、惊世骇俗的App在各种机型上看起来都那么优雅、清新、脱俗呢?今天要讲的就是开发中自定义View的适配方式,大家上车,直接走!

                                                       

现在很多公司UI设计师切图时都只会给出一套图,一般设计标准都是按照市面上主流分辨率(如 1080x1920)。那么这里我们就以1080x1920屏幕分辨率为例,有个需求来了,有个图片需要其宽度为360px,其高度为200px,那么该肿么做呢?这里还不简单?直接设置ImageView 宽度360px,高度200px不就ok了吗!这样真的可行吗?我们一起来看下。

                

可以看到,当该图片显示在720x1280和1080x1920手机上时,其显示结果完全不一样,图片并没有因为屏幕宽度的变化而自行调整大小。这样就产生了屏幕适配的问题啊!那么该怎样才能让图片在不同手机上显示的效果一致呢?也就是图片的宽高会根据当前屏幕宽高自动适配呢?仔细想想其实主要原因就是屏幕像素不一致嘛!在1080x1920屏幕上显示的效果就是我想要的,那么在720x1280手机上图片的宽高必须得发生变化,但是这个宽高得设置为多少呢?这里就涉及到一点数学知识了,屏幕宽度从1080至720,这里可以设想为屏幕宽度缩小了,那么缩小的倍数就应该是1080/720(scaleX),同理,屏幕高度也缩小了1920/1280(scaleY)倍。既然屏幕宽高缩小了,为了在720x1280手机上显示出在1080x1920手机上相同的效果,图片宽高的缩小倍数就是对应的1080/720、1920/1280。也就是在720x1280手机上图片宽度应该为360/scaleX,高度应该为200/scaleY,上述图片展示效果是以1080x1920分辨率手机为标准,那么这里我们是不是可以得出一个结论:

在某个手机分辨率(这里以STANDART_WIDTH ,STANDART_HEIGHT分别代表宽高)下,控件(其宽高分别为S_WIDTH,S_HEIGHT)展示出了我们想要的效果,要在其他分辨率(这里以WIDTH,HEIGHT代表宽高)手机中也展示出对应的效果,那么该控件(这里宽高分别为C_WIDTH,C_HEIGHT)的宽高应该满足以下关系:

                           C_WIDTH= WIDTH/STANDART_WIDTH  *S_WIDTH

                           C_HEIGHT = HEIGHT/STANDART_HEIGHT*S_HEIGHT

一般子View都会存在于父容器中,那么这里带给大家解决适配的方式就是自定义父容器。既然已经得出结论,那么就开始写代码了。

这里以继承RelativeLayout自定义View为例。

//这里为什么会集成RelativeLayout呢?在使用RelativeLayout原有特性的前提下,对其中的子View进行适配
public class CustomRelativeLayout extends RelativeLayout {

    private int displayMetricsWidth;//当前屏幕的宽度
    private int displayMetricsHeight;//当前屏幕的高度
    
    private float scaleX;//屏幕宽度缩放倍数
    private float scaleY;//屏幕高度缩放倍数
    
    private boolean flag;//是否已经测量,该变量是个标识,在RelativeLayout中,当子控件不满足父容器分配的宽高大小时,会再次进行测量。

    //标准值  这里以UI设计师给的设计标准为准  目前市面上主流分辨率为 1080x1920
    public static float STANDARD_WIDTH = 1080f;
    public static float STANDARD_HEIGHT = 1920f;

    public CustomRelativeLayout(Context context) {
        this(context, null);
    }

    public CustomRelativeLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
          WindowManager wm = (WindowManager)             
                         context.getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics displayMetrics = new DisplayMetrics();
            //注意:获取屏幕的高度是除了底部虚拟按键栏的高度
            wm.getDefaultDisplay().getMetrics(displayMetrics);//忽略Navigationbar高度
            //wm.getDefaultDisplay().getRealMetrics(displayMetrics);//获取整个屏幕宽高
    
            displayMetricsWidth= displayMetrics.widthPixels;
            displayMetricsHeight= displayMetrics.heightPixels;

            scaleX = displayMetricsWidth/STANDARD_WIDTH ;//计算屏幕宽度缩放因子
            scaleY = displayMetricsHeight/STANDARD_HEIGHT;//计算屏幕高度缩放因子
    }


     @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          if(!flag){
            //获取子控件个数
            int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {//遍历子控件,重新设置子控件宽高以及margin
                View child = getChildAt(i);
                LayoutParams params = (LayoutParams) child.getLayoutParams();
                params.width = (int) (scaleX * params.width);
                params.height = (int) (scaleY * params.height);
                params.leftMargin = (int) (scaleX * params.leftMargin);
                params.rightMargin = (int) (scaleX * params.rightMargin);
                params.topMargin = (int) (scaleY * params.topMargin);
                params.bottomMargin = (int) (scaleY * params.bottomMargin);
            }
            flag = true;
          }
           
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);

    }

}

上述代码就实现了对RelativeLayout中子View宽高设置,不管在什么分辨率手机上,其子View的宽高都可按照标准值范围内设置。这里有人就提出质疑了,为什么要在onMeasure方法中添加以上逻辑呢?在其他地方该不行吗?好!我来告诉你答案!

 不行!

因为View的宽高大小就是onMeasure方法决定的,在其他地方不能改变View宽高。

那我们来使用下自定义View?

<?xml version="1.0" encoding="utf-8"?>
<CustomRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <ImageView
        android:layout_width="360px"//设置宽度,这里是以1080x1920分辨率为标准,所以控件宽高值必须在标准值范围内 
        android:layout_height="200px"//设置高度
        android:src="@drawable/pika" />
</CustomRelativeLayout>

这样不管显示在何种分辨率手机中,显示效果都会一致,这样也就完成了对不同手机屏幕分辨率适配的问题。效果图这里就不给出了,具体童鞋们可以去手写测试下,还是挺好用的。   

今天的文章就到这里啦!我是你们的小佩琪,下期见!由于佩琪水平有限,若文中存在错误,欢迎指正!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值