Android 自定义View总结 —— LayoutParams

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gucun4848/article/details/53536945

说明:本博客为原创,转载请注明出处 CSDN-ANDROID笔记栈
由于作者水平有限,错误在所难免,请见谅,可以留言,本人会及时改正


索引


<FrameLayout ...>
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_gravity="center"
        android:layout_marginLeft="12dp"
        .../>
<FrameLayout/>

上面这段代码想必大家都不陌生,在xml文件中定义了一个TextView标签,并且对TextView期望的大小及对齐方式做了说明:和父视图一样宽,48dp高,居中对齐。
其实这几个属性对应的就是LayoutParams中的width、height、gravity属性。
LayoutParams是View告诉ParentView自己想要多大,想以哪种方式对齐等

下面来看下LayoutParent的源码

LayoutParams

//这是所有的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

// 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;

    ...
}

FrameLayout LayoutParams

// FrameLayoutParams 定义在FrameLayout类中继承于MarginLayoutParams
public static class LayoutParams extends MarginLayoutParams{
    public static final int UNSPECIFIED_GRAVITY = -1;

    public int gravity = UNSPECIFIED_GRAVITY; // 对齐方式

    ...
}

LinearLayoutParams

// LinearLayoutParams定义在LinearLayout类中继承与MarginLayoutParams
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
    public float weight; // 权重比
    public gravity=-1; // 对齐方式
    ...
}

LayoutParams 有很多分支,一般特殊的ViewGroup都定义特殊的LayoutPrams以实现自己的布局方式,这里只对最常见的几个做了介绍

<FrameLayout ...>
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_gravity="center"
        android:layout_marginLeft="12dp"
        .../>
<FrameLayout/>

再次回到这段代码,如果你想在这个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 ^^
}

Demo

GitHub地址: GitHub
环境: Windows7+JAVA8
IDE: AndroidStdio2.2.2
compileSdkVersion:24
测试设备:Nexus5(6.0.1)

运行结果截图
CustomViewLayoutParams

Demo中有多段实例,在manifest中更改默认启动项就可以了

// 自定义ViewGroup 支持attrs ‘ignore’,layout支持对于margin属性的支持
<com.neulion.android.dl.customviewdemo.widget.DLCustomViewGroup
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#888888">

        <TextView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_marginLeft="12dp"
                android:layout_marginRight="12dp"
                android:background="@color/colorAccent" />

        <TextView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_marginLeft="12dp"
                android:layout_marginRight="12dp"
                android:background="@color/colorPrimary" />

        <TextView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_marginLeft="12dp"
                android:layout_marginRight="12dp"
                android:background="#000000"
                app:ignore="true" />

        <TextView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_marginLeft="12dp"
                android:layout_marginRight="12dp"
                android:background="#ffbb00" />

 </com.neulion.android.dl.customviewdemo.widget.DLCustomViewGroup>

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);
    }
}

展开阅读全文

没有更多推荐了,返回首页