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源码上基本上了解了元素结构,做个总结图如下。