自定义控件知识储备-LayoutParams的那些事

在上一篇文章里,我总结了一下自定义控件需要了解的基础知识:View的绘制流程——《自定义控件知识储备-View的绘制流程》。其中,在View的测量流程里,View的测量宽高是由父控件的MeasureSpec和View自身的LayoutParams共同决定的。MeasureSpec是什么,上一篇文章里已经说得很清楚了(啥,没看过?快去路克路克,(๑•̀ㅂ•́)و✧)。而LayoutParams呢?是时候在这里做个了断了。

LayoutParams是什么?

LayoutParams,顾名思义,就是Layout Parameters :布局参数。
很久很久以前,我就知道LayoutParams了,并且几乎天天见面。那时候在布局文件XML里,写的最多的肯定是android:layout_width = "match_parent"之类的了。比如:

常见布局文件的栗子

<TextView
    style="@style/text_flag_01"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:layout_marginLeft="10dp"
    android:layout_gravity="center"
    android:gravity="center"
    android:text="英明神武蘑菇君"
    android:textColor="@color/white"
    android:background="@color/colorAccent"/>

我们都知道layout_widthlayout_height这两个属性是为View指定宽度的。不过,当时年轻的我心里一直有个疑问:为什么要加上”layout_”前缀修饰呢?其它的描述属性,如textColorbackground,都很正常啊!讲道理,应该用widthheight描述宽高才对啊?

后来呀,我遇到了LayoutParams,它说layout_width是它的属性而非View的,并且不只是针对这一个,而是所有以”layout_”开头的属性都与它有关!所以,它的东西当然要打上自己的标识”layout_”。(呵呵,嚣张个啥,到头来你自己还不是属于View的一部分( ̄┰ ̄*))

既然layout_width这样的属性是LayoutParams定义的,那为何会出现在描述View的xml属性里呢?View和LayoutParams之间有什么恩怨纠缠呢?

不吹不黑,咱们来看看官方文档是怎么说的:

  1. LayoutParams are used by views to tell their parents how they want to be laid out.
    – LayoutParams是View用来告诉它的父控件如何放置自己的。

  2. The base LayoutParams class just describes how big the view wants to be for both width and height.
    – 基类LayoutParams(也就是ViewGroup.LayoutParams)仅仅描述了这个View想要的宽度和高度。

  3. There are subclasses of LayoutParams for different subclasses of ViewGroup.
    – 不同ViewGroup的继承类对应着不同的ViewGroup.LayoutParams的子类。

看着我妙到巅峰的翻译,想必大家都看懂了<( ̄▽ ̄)/。看不懂?那我再来画蛇添足稍微解释一下:

  1. 上面我们提到过,描述View直接用它们自己的属性就好了,如textColorbackground等等,为什么还需要引入LayoutParams呢?在我看来,textColorbackground这样的属性都是只与TextView自身有关的,无论这个TextView处于什么环境,这些属性都是不变的。而layout_widthlayout_marginLeft这样的属性是与它的父控件息息相关的,是父控件通过LayoutParams提供这些”layout_”属性给孩子们用的;是父控件根据孩子们的要求(LayoutParams)来决定怎么测量,怎么安放孩子们的;是父控件……(写不下去了,我都快被父控件感动了,不得不再感慨一句,当父母的都不容易啊(′⌒`)) )。所以,View的LayoutParams离开了父控件,就没有意义了。

  2. 基类LayoutParams是ViewGroup类里的一个静态内部类(看吧,这就证明了LayoutParams是与父控件直接相关的),它的功能很简单,只提供了widthheight两个属性,对应于xml里的layout_widthlayout_height。所以,对任意系统提供的容器控件或者是自定义的ViewGroup,其chid view总是能写layout_widthlayout_height属性的。

  3. 自从有了ViewGroup.LayoutParams后,我们就可以在自定义ViewGroup时,根据自己的逻辑实现自己的LayoutParams,为孩子们提供更多的布局属性。不用说,系统里提供给我们的容器控件辣么多,肯定也有很多LayoutParams的子类啦。let us see see:

ViewGroup.LayoutParams的截图

果然,我们看到了很多ViewGroup.LayoutParams的子类,里面大部分我们应该都比较熟悉。如果你觉得和它们不熟,那就是你一厢情愿啦,你早就“偷偷摸摸”的用过它们好多次了→_→

ViewGroup.MarginLayoutParams

我们首先来看看ViewGroup.MarginLayoutParams,看名字我们也能猜到,它是用来提供margin属性滴。margin属性也是我们在布局时经常用到的。看看这个类里面的属性:

public static class MarginLayoutParams extends ViewGroup.LayoutParams {
   

        public int leftMargin;

        public int topMargin;

        public int rightMargin;

        public int bottomMargin;

        private int startMargin = DEFAULT_MARGIN_RELATIVE;

        private int endMargin = DEFAULT_MARGIN_RELATIVE;

        ...
    }    

前面4个属性是我们以前在布局文件里常用的,而后面的startMarginendMargin是为了支持RTL设计出来代替leftMarginrightMargin的。

一般情况下,View开始部分就是左边,但是有的语言目前为止还是按照从右往左的顺序来书写的,例如阿拉伯语。在Android 4.2系统之后,Google在Android中引入了RTL布局,更好的支持了从右往左文字布局的显示。为了更好的兼容RTL布局ÿ

  • 42
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值