QMUI Android源码分析之QMUICommonListItemView的元素结构

QMUICommonListItemView官方说可以单独使用,也可以配合QMUIGroupListView使用。配合QMUIGroupListView使用时,实际上是放到了QMUIGroupListView的Section里面。

那么这个QMUICommonListItemView到底包含了哪些内容,去看看它的源码吧。它的源码位置如图所示。


打开类文件,可以看到它比之前的QMUIGroupListSectionHeaderFooterView要复杂一些。通过结构图可以看到,主要是set和get方法。


那么从头开始看起,首先是定义了静态常量,右侧选项类型、详细文本的方向、以及红点位置。

3个构造函数,最终都是调用的第3个,然后调用init进行初始化。通过研究init函数的功能,基本上了解了布局结构。init函数做了注释处理。

    protected void init(Context context, AttributeSet attrs, int defStyleAttr) {
        //可以进入到qmui_common_list_item这个布局去看看,就是一行的元素内容
        LayoutInflater.from(context).inflate(R.layout.qmui_common_list_item, this, true);

        //获取一些自定义的属性,从QMUICommonListItemView中进去看看,发现orientation、accessory_type都是可以直接在layout.xml文件中定义的
        //可以在layout.xml中定义的还有titleColor、detailColor
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.QMUICommonListItemView, defStyleAttr, 0);
        @QMUICommonListItemOrientation int orientation = array.getInt(R.styleable.QMUICommonListItemView_qmui_orientation, HORIZONTAL);
        @QMUICommonListItemAccessoryType int accessoryType = array.getInt(R.styleable.QMUICommonListItemView_qmui_accessory_type, ACCESSORY_TYPE_NONE);
        final int initTitleColor = array.getColor(R.styleable.QMUICommonListItemView_qmui_commonList_titleColor, QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_gray_1));
        final int initDetailColor = array.getColor(R.styleable.QMUICommonListItemView_qmui_commonList_detailColor, QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_gray_5));
        array.recycle();

        //找到各个控件
        //最左边的图标
        mImageView = (ImageView) findViewById(R.id.group_list_item_imageView);
        //一个LinearLayout,里面有左边的文本、右边的详细文本、以及中间一个填充空间控件
        mTextContainer = (LinearLayout) findViewById(R.id.group_list_item_textContainer);
        //左边的文本
        mTextView = (TextView) findViewById(R.id.group_list_item_textView);
        mTextView.setTextColor(initTitleColor);
        //小红点。代表有更新,可以设置显示左边或右边。默认是gone,就是不显示。
        mRedDot = (ImageView) findViewById(R.id.group_list_item_tips_dot);
        //显示一个new图标。显示在左边文本的右边,一般也表示是新功能,或者有更新。
        mNewTipViewStub = (ViewStub) findViewById(R.id.group_list_item_tips_new);
        //右边的详细文本。也可以通过orientation这个属性设置为VERTICAL,把它放到下面显示。
        mDetailTextView = (TextView) findViewById(R.id.group_list_item_detailTextView);
        //左边文本和右边文本中间的填充空间,目的就是使右边的文本右对齐。它设置了weight为1,所以会填充剩余空间。
        mTextDetailSpace = (Space) findViewById(R.id.group_list_item_space);
        mDetailTextView.setTextColor(initDetailColor);
        LinearLayout.LayoutParams detailTextViewLP = (LinearLayout.LayoutParams) mDetailTextView.getLayoutParams();
        //如果是最后一行,要做兼容处理。安卓 5.0 以下版本中,最后一行会多出一个 LineSpacingExtra 的空白
        //一行空白qmui_common_list_item_detail_line_space定义的是5dp
        if (QMUIViewHelper.getIsLastLineSpacingExtraError()) {
            detailTextViewLP.bottomMargin = -QMUIResHelper.getAttrDimen(context, R.attr.qmui_common_list_item_detail_line_space);
        }
        //如果是垂直布局,那么右边的文本会显示到下面一行,所以设置一个上边距6dp
        //修改后,当时也不明白为什么不调用setLayoutParams。
        // 经测试修改后可以直接生效,那么应该返回的是引用,相当于是直接修改了值。
        //在后面的setOrientation方法中可以看到,如果设置为垂直的VERTICAL,则直接调整了LinearLayout的布局为VERTICAL
        if (orientation == VERTICAL) {
            detailTextViewLP.topMargin = QMUIDisplayHelper.dp2px(getContext(), 6);
        } else {
            detailTextViewLP.topMargin = 0;
        }
        //最右边(还在右边文字的右边)的修饰符,可有4种选择:向右箭头、开关按钮、自定义、无。
        mAccessoryView = (ViewGroup) findViewById(R.id.group_list_item_accessoryView);
        setOrientation(orientation);
        setAccessoryType(accessoryType);
    }

从初始化代码中可以看到,可以在layout布局文件中定义titleColor、detailColor、orientation、accessory_type的属性值。不过经过亲测qmui_orientation没有生效,看源码定义的declare-styleable没有给qmui_orientation设置format。可能这个原因导致设置无效吧,为也不知道是不是。

    <declare-styleable name="QMUICommonListItemView">
        <attr name="qmui_orientation"/>
        <attr name="qmui_accessory_type" format="enum">
            <enum name="none" value="0"/>
            <enum name="chevron" value="1"/>
            <enum name="switcher" value="2"/>
            <enum name="custom" value="3"/>
        </attr>
        <attr name="qmui_commonList_titleColor" format="color"/>
        <attr name="qmui_commonList_detailColor" format="color"/>
    </declare-styleable>

后面都是一些set和get方法。看set方法,如果传递进去的是null,那么就设置为GONE隐藏掉。

显示更新方法showNewTip,在里面将小红点移除了。即如果要显示new,那么就将小红点设置为GONE。所以想同时显示小红点和new时,需要先调用showNewTip,然后在调用showRedDot显示小红点。不过如果小红点显示在左边,也会被new的图标给覆盖掉,这个看onLayout的源码就知道了。不过可以将小红点显示在右边,new显示在左边,从而实现2个都显示。

    public void showNewTip(boolean isShow) {
        if (isShow) {
            if (mNewTip == null) {
                mNewTip = mNewTipViewStub.inflate();
            }
            mNewTip.setVisibility(View.VISIBLE);
            mRedDot.setVisibility(GONE);    //移除了小红点
        } else {
            if (mNewTip != null && mNewTip.getVisibility() == View.VISIBLE) {
                mNewTip.setVisibility(View.GONE);
            }
        }
    }

看setOrientation方法的源码,如果设置为VERTICAL,是直接将LinearLayout的布局方式设置为VERTICAL,这样3个子控件就调整了布局。同时调整了子控件里面的space控件,如果是VERTICAL,就不能将weight设置为1了。

setAccessoryType方法是设置最右边的附加选项,它实际上是一个FrameLayout。所以可以在里面添加自定义的View。

最后一个onLayout方法,主要是设置小红点和new图标的位置。从源码中得知,如果小红点显示在左边,显示new时会被覆盖掉,因为他们都显示在同一个位置。不过,在showNewTip方法中将小红点给设置为GONE了。

从QMUICommonListItemView源码上基本上了解了元素结构,做个总结图如下。

QMUICommonListItemView的UI布局结构图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值