LayoutParams
子View
通过 LayoutParams
告诉 ViewGroup
应该如何放置自己,主要用来协助 ViewGroup
进行布局。
在自定义 ViewGroup
的过程中,如果需要定义 LayoutParams
的话,首先要创建一个类(通常是静态内部类),并继承自 ViewGroup.LayoutParams
或其子类。
在 ViewGroup
中,我们需要重写几个方法:
generateDefaultLayoutParams()
generateLayoutParams(ViewGroup.LayoutParams p)
checkLayoutParams(ViewGroup.LayoutParams p)
- 第一个方法,顾名思义,是生成默认的
LayoutParams
。这个方法会在往ViewGroup
中添加子View
时被调用(如果该子View
的LayoutParams
为空,或者没有直接调用有LayoutParams
参数的addView()
方法的话)。 - 第二个方法,在
ViewGroup
添加子View
的过程中,往往和第三个方法checkLayoutParams()
配合使用, 这个checkLayoutParams()
就是检查传进来的LayoutParams
是否合法。怎么样算合法,就要看怎么重写了。默认的实现是做个非空检查。如果检查到传进来的LayoutParams
不合法,接着就会调用这个generateLayoutParams()
方法。 - 第三个方法, 虽说不重写,在一般情况下也不会报错,但还是建议重写,并且在里面判断这个传进来的
LayoutParams
是不是你自定义的LayoutParams
。
自定义 LayoutParams 属性
自定义 LayoutParams
就像自定义 View
属性那样,在 attrs.xml
中去定义一些需要用到的属性,这个 styleable
的命名格式一般为: ViewGroup名_Layout
。
<resources>
<declare-styleable name="SimpleViewGroup_Layout">
<!-- 自定义的属性 -->
<attr name="layout_simple_attr" format="integer" />
<!-- 使用系统预置的属性 -->
<attr name="android:layout_gravity" />
</declare-styleable>
</resources>
回到自定义 LayoutParams
中,找到 (Context c, AttributeSet attrs)
这个构造方法,在这里面就可以获取到自定义的属性了。
public static class SimpleLayoutParams extends ViewGroup.MarginLayoutParams {
public int simpleAttr;
public int gravity;
public SimpleLayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
// 解析布局属性
TypedArray typedArray = c.obtainStyledAttributes(attrs, R.styleable.SimpleViewGroup_Layout);
simpleAttr = typedArray.getInteger(R.styleable.SimpleViewGroup_Layout_layout_simple_attr, 0);
gravity=typedArray.getInteger(R.styleable.SimpleViewGroup_Layout_android_layout_gravity, -1);
//释放资源
typedArray.recycle();
}
// ...
}
最后回到 ViewGroup
中,重写 generateLayoutParams(AttributeSet attrs)
方法(该方法主要用于 inflate
处理)。
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new SimpleViewGroup.SimpleLayoutParams(getContext(), attrs);
}
/**
* 解析XML文件中的View
* @param parser 解析器
* @param root 父容器(可能为null)
* @param attachToRoot View是否需要附加到父容器中
*/
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
// ...
View result = root;
// ...
final String name = parser.getName();
if (TAG_MERGE.equals(name)) { // 针对<merge>标签
// ...
} else { // 针对普通标签
// ...
ViewGroup.LayoutParams params = null;
if (root != null) {
// 通过XML中的布局参数生成对应的LayoutParams
params = root.generateLayoutParams(attrs);
// ...
}
// ...
}
// ...
return result;
}