安卓布局适配的另一种姿势

一:

安卓布局适配一直都是安卓开发者比较头痛的问题,我们不仅需要考虑代码的质量,同时也需要面对数千品种的手机型号而考虑界面适配的工作;

Android屏幕适配全攻略(最权威的官方适配指导)
http://blog.csdn.net/zhaokaiqiang1992/article/details/45419023

这是基于google 官方去适配的一套方案,也是作为安卓工程师必须掌握的一套布局适配的方案。

Android 百分比布局库(percent-support-lib) 解析与扩展http://blog.csdn.net/lmj623565791/article/details/46695347

这是基于Android-percent-support 增强库,实现的百分比布局(详情点击链接查看)

二:

今天我要说的是按照一定的比例(宽高比)去自动适配控件的大小,什么意思呢?请看下幅图:

这里写图片描述

我们暂且,先把这个控件看作是imageview

这是我公司UI设计师给出的原型设计图,图中选中的控件宽是750px,高是220px。我们普通的做法就是把控件的宽设置为match_parent,高度设置为转换后的dip,然后直接开始布局,这样可以是可以,但是我发现在有些手机上,展现的高度不是很理想;

安卓布局适配的另一种姿势:

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:auto="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="com.example.myapplication.MainActivity"
    android:orientation="vertical">

        <com.example.myapplication.AutoAdapterImageView
        auto:ration="0.29"
        auto:anchor="width"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ff0000"
        ></com.example.myapplication.AutoAdapterImageView>

</LinearLayout>

如果我这样布局是不是更加完美呢?
我们已经知道这个控件的宽度是填满整个屏幕,它是个固定值(屏幕有多宽,我就多宽),高度是宽度的0.293333……计算方式:220 / 750 = 0.2933… 这样,无论碰到什么样的情况,他们永远会保持最佳状态。

解释下:

xmlns:auto=”http://schemas.android.com/apk/res-auto” 自定义属性,命名空间
ration :宽高比
anchor:宽度,意思是,根据宽度去自动计算该控件的高度,当然反之,也可以根据高度去自动计算控件的宽度。这里注意,根据什么(宽度或者高度),该值一定要有明确值,不能wrap_content

是不是突然觉得很nice ~

好,那么看它是如何实现的

自定义属性部分:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="AutoAdpaterStyleable">
        <!-- 比例 -->
        <attr name="ratio" format="float"></attr>
        <!-- 根据宽还是根据高 -->
        <attr name="anchor">
            <enum name="width" value="1" />
            <enum name="heigh" value="2" />
        </attr>

    </declare-styleable>

</resources>

这里都有备注,应该很容易理解

Autoadapterimageview 实现:

public class AutoAdapterImageView extends ImageView {

//这里都是自定义属性相关的变量
private float ration = 0;
private int anchor;
private final int WIDTH_ANCHOR = 1;
private final int HEIGHT_ANCHOR = 2;

public AutoAdapterImageView(Context context, AttributeSet attrs) {
    super(context, attrs);

//读取自定属性,记得释放资源 recycle()
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AutoAdpaterStyleable);
    ration = typedArray.getFloat(R.styleable.AutoAdpaterStyleable_ratio, ration);
    anchor = typedArray.getInt(R.styleable.AutoAdpaterStyleable_anchor, WIDTH_ANCHOR);
    typedArray.recycle();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取模式,以及大小    mode 下面说明会有   
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

//如果宽高都是精确值,那么我们不处理,交给系统
    if(widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
//如果根据宽度自动适配,我们获取到宽度的值 然后计算并设置进去
else if(anchor == WIDTH_ANCHOR && widthMode == MeasureSpec.EXACTLY && ration > 0){
        int height = MeasureSpec.makeMeasureSpec((int) (widthSize * ration + 0.5f), MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, height);
    }
//如果根据高度自动适配,我们获取到高度的值 然后计算并设置进去
else if(anchor == HEIGHT_ANCHOR && heightMode == MeasureSpec.EXACTLY && ration > 0){
        int width = MeasureSpec.makeMeasureSpec((int) (heightSize * ration + 0.5f), MeasureSpec.EXACTLY);
        super.onMeasure(width, heightMeasureSpec);
    }
//否则交给系统处理
else{
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
}

MODE的三种情况,
取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOST。

MeasureSpec.EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width=”50dip”,或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。

MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。

MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

Over~

代码不多,如果有什么疑问,请指出,谢谢~

github 简单封装了几个常用的控件,需要的请自行查看

这里写图片描述

Github 地址 https://github.com/andmizi/AutoAdapterView

发布了35 篇原创文章 · 获赞 73 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_28268507/article/details/53319104
今日推荐