说明:本博客为原创,转载请注明出处 CSDN-ANDROID笔记栈
由于作者水平有限,错误在所难免,请见谅,可以留言,本人会及时改正
索引
"match_parent"
android:layout_height="48dp"
android:layout_gravity="center"
android:layout_marginLeft="12dp"
.../>
上面这段代码想必大家都不陌生,在xml文件中定义了一个TextView标签,并且对TextView期望的大小及对齐方式做了说明:和父视图一样宽,48dp高,居中对齐。
其实这几个属性对应的就是LayoutParams中的width、height、gravity属性。
LayoutParams是View告诉ParentView自己想要多大,想以哪种方式对齐等
下面来看下LayoutParent的源码
//这是所有的LayoutParams的基类,定义在ViewGroup类中
public static class LayoutParams {
@Deprecated
public static final int FILL_PARENT = -1;
public static final int MATCH_PARENT = -1; //和父View一样大
public static final int WRAP_CONTENT = -2; //根据内容自适应大小
public int width; //宽:只能是-1,-2,或者是>0的一个精确值
public int height; //高
public LayoutAnimationController.AnimationParameters layoutAnimationParameters;
public LayoutParams(Context c, AttributeSet attrs) {
// xml中读取属性,设置witdh和height
TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout);
setBaseAttributes(a,
R.styleable.ViewGroup_Layout_layout_width,
R.styleable.ViewGroup_Layout_layout_height);
a.recycle();
}
public LayoutParams(int width, int height) {
this.width = width;
this.height = height;
}
}
// MarginLayoutParams 也定义在ViewGroup中继承LayoutParams
public static class MarginLayoutParams extends ViewGroup.LayoutParams {
public int leftMargin; //左边距值,对应xml中的layout_marginLeft属性
public int topMargin; //上边距,和leftMargin类似
public int rightMargin;
public int bottomMargin;
private int startMargin = DEFAULT_MARGIN_RELATIVE;
private int endMargin = DEFAULT_MARGIN_RELATIVE;
...
}
// FrameLayoutParams 定义在FrameLayout类中继承于MarginLayoutParams
public static class LayoutParams extends MarginLayoutParams{
public static final int UNSPECIFIED_GRAVITY = -1;
public int gravity = UNSPECIFIED_GRAVITY; // 对齐方式
...
}
// LinearLayoutParams定义在LinearLayout类中继承与MarginLayoutParams
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
public float weight; // 权重比
public gravity=-1; // 对齐方式
...
}
LayoutParams 有很多分支,一般特殊的ViewGroup都定义特殊的LayoutPrams以实现自己的布局方式,这里只对最常见的几个做了介绍
"match_parent"
android:layout_height="48dp"
android:layout_gravity="center"
android:layout_marginLeft="12dp"
.../>
再次回到这段代码,如果你想在这个TextView中添加android:layout_weight这个属性,你会发现代码提示功能无法完成自动添加,即使你手动添加也没有任何作用。
因为TextView的父亲是FrameLayout,对于layout_weight 这个属性,FrameLayout不认识它!
public class View {
...
// 在View类中有一个ViewGroup.LayoutParams
protected ViewGroup.LayoutParams mLayoutParams;
// android在解析xml之后会对这个LayoutPrams赋值,在上面的xml中,这个LayoutParams会被赋值成FrameLayout.LayoutParams对象!
// 在FrameLayout和View类中找不到对LayoutParams赋值的代码
// 关于具体如何赋值在哪里赋值可以自己google ^^
}
GitHub地址: GitHub
环境: Windows7+JAVA8
IDE: AndroidStdio2.2.2
compileSdkVersion:24
测试设备:Nexus5(6.0.1)
Demo中有多段实例,在manifest中更改默认启动项就可以了
// 自定义ViewGroup 支持attrs ‘ignore’,layout支持对于margin属性的支持
"match_parent"
android:layout_height="match_parent"
android:background="#888888">
"48dp"
android:layout_height="48dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="@color/colorAccent" />
"48dp"
android:layout_height="48dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="@color/colorPrimary" />
"48dp"
android:layout_height="48dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="#000000"
app:ignore="true" />
"48dp"
android:layout_height="48dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="#ffbb00" />
CustomViewGroup中重载了如下方法
protected boolean checkLayoutParams(ViewGroup.LayoutParams p){
return p instanceof CustomLayoutParams;
}
protected ViewGroup.LayoutParams generateDefaultLayoutParams(){
return new CustomLayoutParams(CustomLayoutParams.WRAP_CONTENT, CustomLayoutParams.WRAP_CONTENT);
}
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p){
if (p instanceof MarginLayoutParams){
return new CustomLayoutParams((MarginLayoutParams) p);
}
return new CustomLayoutParams(p);
}
新增了自定义的LayoutParams类
public static class CustomLayoutParams extends MarginLayoutParams{
public boolean ignore = false;
public CustomLayoutParams(Context c, AttributeSet attrs){
super(c, attrs);
TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.DLCustomViewGroup);
ignore = a.getBoolean(R.styleable.DLCustomViewGroup_ignore, false);
a.recycle();
}
public CustomLayoutParams(int width, int height){
super(width, height);
}
public CustomLayoutParams(MarginLayoutParams source){
super(source);
}
public CustomLayoutParams(ViewGroup.LayoutParams source){
super(source);
}
}