添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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>

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

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

import android.content.Context; import android.util.DisplayMetrics; import android.view.WindowManager; public class ScreenAdaptationUtils { //设计稿的宽高像素 private static ..
为什么要屏幕适配 同一个界面需要在不同尺寸的屏幕上显示,即使屏幕的尺寸一样,密度也可能不一样。导致App的界面元素在不同屏幕尺寸上显示不一致。所以我们让布局,布局组件,资源,用户界面流程,匹配不同屏幕尺寸。 屏幕适配常见方式 布局适配 避免写死控件尺寸,使用wrap_content, match_parent LinearLayout xxx:layout_weight=“0.5” //线性布局...
例如:my_view.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/person" android:orientation="vertical" android:
自定义View中的适配 自定义view中,使用的单位都是px,那如何去适配屏幕呢?获取屏幕宽度px等数据,然后根据这些去设置 view的宽度px,字体的大小 我们可以把想要显示的大小用dp、sp作为单位,然后在代码中通过工具类转换为px package com.zhy.utils;import android.content.Context; import android.util.TypedV
最近遇到一个问题是这样的,App一般自己都会有一个UINavigationController,顶部TableView如果有tableHeaderView如果设置起始位置是(0,0)是在导航栏的下面的,为了更好地UI希望从屏幕的(0,0)开始,就遇到了上面的这个问题,简单的看一下效果: 一般在UIViewController的基类里面加以下代码: if (IOS7) {
整理并总结自鸿洋的博客:http://blog.csdn.net/lmj623565791/article/details/24252901 一、不重写onMeasure,在res/layout/activity_main.xml中限定view高度和宽度 com.cctvjiatao.customview01.act.MainActivity.java * 自定义View 第一课
根据具体情况选择合适的布局,尽可能的优化布局,使其自适配分辨率。 1.1.  对于左中右布局,使用相对布局,优先布局左右两边并让其靠近父view边界,中间view居于两个view之间填充全部局。 1.2.  对于左中右布局且view贴在一起使用线性布局 1.3.  对于横向布局且均分(有规律