广告
返回顶部
首页 > 资讯 > 移动开发 >Android自定义View实现LayoutParams的方法详解
  • 142
分享到

Android自定义View实现LayoutParams的方法详解

摘要

目录第一层理解第二层理解第三层理解这一期我们来讲一讲LayoutParams这个玩意儿。Android入门的第一行代码就牵扯到这个东西,然而,你真的理解够了吗? 第一层理解 <

这一期我们来讲一讲LayoutParams这个玩意儿。Android入门的第一行代码就牵扯到这个东西,然而,你真的理解够了吗?

第一层理解

<RelativeLayout xmlns:android="Http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
</RelativeLayout>

layout_width和layout_height这个是不是最开始学的时候,就要搞清楚的基础知识,match_parent代表填充屏幕,wrap_content代表包裹内容。这些其实是系统控件定义的属性,通过TypedArray进行解析。

第二层理解

val lp = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
lp.addRule(RelativeLayout.CENTER_VERTICAL)
lp.addRule(RelativeLayout.BELOW, viewId)
lp.setMargins(10, 20, 10, 20)

使用代码动态布局的时候设置LayoutParams。

第三层理解

好了,知识是在不断打破旧的认识中进步的,第一层实际还没到LayoutParams,还只是AttributeSet。系统何时将布局中的AttributeSet解析成LayoutParams的呢?

@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
    return new RelativeLayout.LayoutParams(getContext(), attrs);
}

protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}

ViewGroup有个关键的方法,generateLayoutParams()。

public LayoutParams(Context c, AttributeSet attrs) {
    super(c, attrs);

    TypedArray a = c.obtainStyledAttributes(attrs,
            com.android.internal.R.styleable.RelativeLayout_Layout);

    final int targetSdkVersion = c.getApplicationInfo().targetSdkVersion;
    mIsRtlCompatibilityMode = (targetSdkVersion < JELLY_BEAN_MR1 ||
            !c.getApplicationInfo().hasRtlSupport());

    final int[] rules = mRules;
    //noinspection MismatchedReadAndWriteOfArray
    final int[] initialRules = mInitialRules;

    final int N = a.getIndexCount();
    for (int i = 0; i < N; i++) {
        int attr = a.getIndex(i);
        switch (attr) {
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignWithParentIfMissing:
                alignWithParent = a.getBoolean(attr, false);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toLeftOf:
                rules[LEFT_OF] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toRightOf:
                rules[RIGHT_OF] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_above:
                rules[ABOVE] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_below:
                rules[BELOW] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBaseline:
                rules[ALIGN_BASELINE] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignLeft:
                rules[ALIGN_LEFT] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignTop:
                rules[ALIGN_TOP] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignRight:
                rules[ALIGN_RIGHT] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBottom:
                rules[ALIGN_BOTTOM] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentLeft:
                rules[ALIGN_PARENT_LEFT] = a.getBoolean(attr, false) ? TRUE : 0;
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentTop:
                rules[ALIGN_PARENT_TOP] = a.getBoolean(attr, false) ? TRUE : 0;
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentRight:
                rules[ALIGN_PARENT_RIGHT] = a.getBoolean(attr, false) ? TRUE : 0;
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentBottom:
                rules[ALIGN_PARENT_BOTTOM] = a.getBoolean(attr, false) ? TRUE : 0;
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerInParent:
                rules[CENTER_IN_PARENT] = a.getBoolean(attr, false) ? TRUE : 0;
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerHorizontal:
                rules[CENTER_HORIZONTAL] = a.getBoolean(attr, false) ? TRUE : 0;
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerVertical:
                rules[CENTER_VERTICAL] = a.getBoolean(attr, false) ? TRUE : 0;
               break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toStartOf:
                rules[START_OF] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toEndOf:
                rules[END_OF] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignStart:
                rules[ALIGN_START] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignEnd:
                rules[ALIGN_END] = a.getResourceId(attr, 0);
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentStart:
                rules[ALIGN_PARENT_START] = a.getBoolean(attr, false) ? TRUE : 0;
                break;
            case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentEnd:
                rules[ALIGN_PARENT_END] = a.getBoolean(attr, false) ? TRUE : 0;
                break;
        }
    }
    mRulesChanged = true;
    System.arraycopy(rules, LEFT_OF, initialRules, LEFT_OF, VERB_COUNT);

    a.recycle();
}

这个代码熟悉吧,这就是我们之前讲过的自定义属性啊!没错,xml布局中的属性会先被解析成LayoutParams。那么我问你个问题,你觉得generateLayoutParams()和generateDefaultLayoutParams()的这个LayoutParams是给自己用的呢?还是给它的子控件用的呢?它是给子控件用的。自己的那个直接在构造方法中就从AttributeSet解析出来了。这样你就理解了,为什么RelativeLayout的那些个

android:layout_centerVertical="true"
android:layout_alignParentEnd="true"

怎么全部定义在子控件里面了。然后ViewGroup的addView()方法中就可以带上这个LayoutParams了。


public void addView(View child, int index) {
    if (child == null) {
        throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
    }
    LayoutParams params = child.getLayoutParams();
    if (params == null) {
        params = generateDefaultLayoutParams();
        if (params == null) {
            throw new IllegalArgumentException(
                    "generateDefaultLayoutParams() cannot return null  ");
        }
    }
    addView(child, index, params);
}

你不重写generateLayoutParams()方法,怎么在添加子控件的时候,让子控件用你的LayoutParams呢?

public static class LayoutParams extends ViewGroup.MarginLayoutParams {
}

以上是LinearLayout.LayoutParams的摘要,我们自定义ViewGroup的时候,是不是也可以继承个ViewGroup的LayoutParams玩一玩呢?然后重写generateLayoutParams()和generateDefaultLayoutParams()方法。

@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
    return new LinearLayout.LayoutParams(getContext(), attrs);
}

这里return你的ViewGroup的LayoutParams,然后在你的ViewGroup的LayoutParams的构造方法中就可以解析自定义属性attrs了。如果忘记了解析方式,我给你个提示,使用context的obtainStyledAttributes()方法。

大部分停留在第二层理解,你如果学会了第三层,那么你自定义View又可以玩出新的高度了。

到此这篇关于Android自定义View实现LayoutParams的方法详解的文章就介绍到这了,更多相关Android LayoutParams内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Android自定义View实现LayoutParams的方法详解

本文链接: https://www.lsjlt.com/news/193950.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作