Android AutoLayout 使用记录

来源:互联网 发布:sql数据库文件修复 编辑:程序博客网 时间:2024/06/07 18:18

一、概述
最近学习使用Android AutoLayout解决适配问题,想要单纯使用这个库将适配很轻松的做好,还是有些问题需要注意的,个人就探索过程中遇到的问题进行记录,希望对后来者有所参考。
本库的地址:https://github.com/hongyangAndroid/AndroidAutoLayout
对于适配,我希望的效果是这样的:拿到设计图,meta信息中填入设计图的尺寸,然后不需要额外计算,布局直接抄设计图上的尺寸,不产生任何多余的资源文件,完成各种分辨率的适配。

二、直观的体验
通常带有标注的设计图如下:
这里写图片描述

如果没有提供这样的设计图,可以自己去测量,测量的方法有很多,这里不赘述了。

对于 新增旅客 布局文件可以这么写

<RelativeLayoutandroid:layout_width="match_parent"android:layout_height="86px"android:layout_marginTop="26px"android:background="#ffffffff"><ImageView    android:id="@+id/id_tv_add"    android:layout_width="34px"    android:layout_height="34px"    android:layout_gravity="center_vertical"    android:layout_marginLeft="276px"    android:layout_marginTop="26px"    android:src="@mipmap/add"    /><TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_centerVertical="true"    android:layout_marginLeft="26px"    android:layout_toRightOf="@id/id_tv_add"    android:text="新增旅客"    android:textColor="#1fb6c4"    android:textSize="32px"    /></RelativeLayout>

对于Item的布局文件,可以这么写:

<RelativeLayout    android:layout_width="match_parent"    android:layout_height="108px"    android:layout_marginTop="26px"    android:background="#ffffffff"    >    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginLeft="22px"        android:layout_marginTop="16px"        android:text="王大炮 WANG.DAPAO"        android:textColor="#333"        android:textSize="28px"        />    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_marginBottom="16px"        android:layout_marginLeft="22px"        android:text="护照:G50786449"        android:textColor="#999"        android:textSize="26px"        /></RelativeLayout>

说明:这里的px并不代表1像素,在内部会进行百分比化处理。按照百分比的规则,完美实现了适配,这样的好处是:
再也不用拿着设计稿去想这控件的宽高到底取多少dp
再也不用去为多个屏幕去写多个dimens
再也不用去计算百分比了(如果使用百分比控件完成适配)
再也不用去跟UI MM去解释什么是dp了

三、用法
(1)将AutoLayout引入

dependencies {    compile project(':autolayout')}

也可以直接

dependencies {    compile 'com.zhy:autolayout:1.4.3'}

(2)注册设计图尺寸
在项目的AndroidManifest中注明设计稿的尺寸。

<meta-data android:name="design_width" android:value="768"></meta-data><meta-data android:name="design_height" android:value="1280"></meta-data>

(3)开启适配
有两种方式开启适配
1)将Activity继承AutoLayoutActivity
2)手动替换Layout布局文件中的
LinearLayout -> AutoLinearLayout
RelativeLayout -> AutoRelativeLayout
FrameLayout -> AutoFrameLayout

四、注意事项
(1)如何开启PreView
写布局文件的时候,如果不能实时的预览效果,那么体验真的是非常的不好,也在很大程度上降低开发效率,所以下面说明如何用好,用对PreView(针对该库)。
首先,要记得设计稿的尺寸,比如 768 * 1280
然后,在PreView面板,选择分辨率一致的设备:
这里写图片描述

然后就可以看到最为精确的预览了。

(2)TextView的高度问题
关于TextView这个控件,可能和设计稿上会有一些出入,并非是此库的原因,而是与生俱来的特性。
设计稿一般只会标识一个字体的大小,比如你设置textSize=”20px”,实际上TextView所占据的高度肯定大于20px,字的上下都会有一定的间隙,所以一定要灵活去写字体的高度,比如对于text上下的margin可以选择尽可能小一点。或者选择别的约束条件去定位(比如上例,选择了marginBottom)
比如:

<TextView textSize="32px" layout_height="wrap_contnt" />

运行后肯定不是32px的高度,文字的上下方都会有一定的空隙。如果将高度写死,也会发现文字显示不全。
恩,所以呢,灵活应对这个问题,对于存在字体标识很精确的值,你可以选择:对于TextView与其他控件的上下边距呢,尽可能的稍微写小一点。

其实我上面的例子,几乎都是TextView,所有我在编写Item里面的时候,也有意缩小了一下marginTop值等。不过,对于其他控件是不存在这样的问题的。

ps:因为TextView的上述问题:所以对于居中,虽然可以使用本库通过编写margin_left,margin_top等很轻松的完成居中。但是为了精确起见,还是建议使用gravity,centerInXXX等属性完成。

(3)指定设置的值参考宽度或者高度
由于该库的特点,布局文件中宽高上的1px是不相等的,于是如果需要宽高保持一致的情况,布局中使用属性:

app:layout_auto_basewidth="height",代表height上编写的像素值参考宽度。

app:layout_auto_baseheight="width",代表width上编写的像素值参考高度。

如果需要指定多个值参考宽度即:

app:layout_auto_basewidth="height|padding"

用|隔开,类似gravity的用法,取值为:

width,heightmargin,marginLeft,marginTop,marginRight,marginBottompadding,paddingLeft,paddingTop,paddingRight,paddingBottomtextSize.

(4)将状态栏区域作为内容区域

如果某个Activity需要将状态栏区域作为实际的内容区域时,那么可用高度会变大,你所要做的只有一件事:让这个Activity实现UseStatusBar接口(仅仅作为标识左右,不需要实现任何方法),当然你肯定要自己开启windowTranslucentStatus或者设置FLAG_TRANSLUCENT_STATUS。
注意:仅仅是改变状态栏颜色,并不需要实现此接口,因为并没有实际上增加可用高度。

五、其他

目前支持属性

layout_widthlayout_heightlayout_margin(left,top,right,bottom)pading(left,top,right,bottom)textSizemaxWidth, minWidth, maxHeight, minHeight不会影响系统所有的其他属性,以及不会影响dp,sp的使用

性能的提升

通过本库的方式去编写代码,可以在很大程序上使用margin,也就是说,对于View的位置非常好控制,从而能够减少非常多的嵌套,甚至任何一个复杂的界面做到无嵌套。

以及,几乎不需要去使用RelativeLayout的规则了,比如rightOf,完全可以由marginLeft完成,其他的rule同理。

对于LinearLayout的weight,几乎也不需要使用了,比如屏幕宽度720px,想要四个控件横向均分,完全可以写layout_width=”180px”

相信通过上述的介绍,本库适配的做法可以说是目前见过的最方便的适配方案,最大化的减轻了适配的负担,甚至比不适配时编写UI都方便。目前本库,已经尝试用于项目中,尽可能去发现一些潜在的问题。

六、潜在的问题

(1)默认使用的高度是设备的可用高度,也就是不包括状态栏和底部的操作栏的,如果希望拿设备的物理高度进行百分比化,可以在Application的onCreate方法中进行设置:

public class UseDeviceSizeApplication extends Application{    @Override    public void onCreate()    {        super.onCreate();        AutoLayoutConifg.getInstance().useDeviceSize();    }}

(2)对于其他继承系统的FrameLayout、LinearLayout、RelativeLayout的控件,比如CardView,如果希望在其内部直接支持“px”百分比化,可以自己扩展,扩展方式为下面的代码,也可参考issue#21

package com.zhy.sample.view;import android.content.Context;import android.support.v7.widget.CardView;import android.util.AttributeSet;import com.zhy.autolayout.AutoFrameLayout;import com.zhy.autolayout.utils.AutoLayoutHelper;/** * Created by zhy on 15/12/8. */public class AutoCardView extends CardView{    private final AutoLayoutHelper mHelper = new AutoLayoutHelper(this);    public AutoCardView(Context context)    {        super(context);    }    public AutoCardView(Context context, AttributeSet attrs)    {        super(context, attrs);    }    public AutoCardView(Context context, AttributeSet attrs, int defStyleAttr)    {        super(context, attrs, defStyleAttr);    }    @Override    public AutoFrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs)    {        return new AutoFrameLayout.LayoutParams(getContext(), attrs);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)    {        if (!isInEditMode())        {            mHelper.adjustChildren();        }        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }}

(3)ListView、RecyclerView类的Item的适配(recyclerview 加载 RadioButton)
对于ListView这类控件的item,默认根局部写“px”进行适配是无效的,以为外层非AutoXXXLayout,而是ListView。但是,一行代码就可以支持了:

@Overridepublic View getView(int position, View convertView, ViewGroup parent){    ViewHolder holder = null;    if (convertView == null)    {        holder = new ViewHolder();        convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);        convertView.setTag(holder);        //对于listview,注意添加这一行,即可在item上使用高度        AutoUtils.autoSize(convertView);    } else    {        holder = (ViewHolder) convertView.getTag();    }    return convertView;}

注意AutoUtils.autoSize(convertView);这行代码的位置即可。
同类方法还有:
AutoUtils.autoPadding(convertView); 等。

对于RecyclerView

public ViewHolder(View itemView){      super(itemView);      AutoUtils.autoSize(itemView);}//...@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){     View convertView = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_item, parent, false);     return new ViewHolder(convertView);}

一定要记得LayoutInflater.from(mContext).inflate使用三个参数的方法!

(4)导入后出现org/gradle/api/publication/maven/internal/DefaultMavenFactory

最简单的方式,通过compile 'com.zhy:autolayout:x.x.x'进行依赖使用,如果一定要以module引用,参考该issue#74

(5)RadioGroup,Toolbar等控件中的子View无法完成适配
解决方法跟(2)一样,需要自己扩展。不过这个很多使用者贡献了他们的扩展类可以直接使用, 参考autolayout-widget, 如果没有发现你需要的容器类,那么你就真的需要自行扩展了,ps:需要用到哪个copy就好了,不要直接引用autolayout-widget,因为其引用了大量的库,可能很多 库你是用不到的。例如:RadioGroup 无法适配

(6)暂时没找到横屏适配的方法,从github上提问有人说是采用传统的方法,横屏拉出来单独适配。。。。

(7)java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

这个问题是因为默认AutoLayoutActivity会继承自AppCompatActivity,所以默认需要设置 Theme.AppCompat的theme;

如果你使用的依旧是FragmentActivity等,且不考虑使用AppCompatActivity, 你可以选择自己编写一个MyAutoLayoutActivity extends 目前你使用的Activity基类,例如 MyAutoLayoutActivity extends FragmentActivity,然后将该库中AutoLayoutActivity中的逻辑 拷贝进去即可,以后你就继承你的MyAutoLayoutActivity就好了。

ps:还是建议尽快更新SDK版本使用AppCompatActivity,截止文档编写日期,SDK最新版本为1.4.3。

0 0
原创粉丝点击