最终实现的效果展示图:
类似支付宝微信,底部分隔线对齐标题效果:
完整渲染显示效果(包含三个条目右边不同颜色的文字):
立体效果:
隐藏资产总额条目右边更多箭头
隐藏中国历史条目右边的文字:
隐藏中国历史条目下边的分隔线:
隐藏条目2中国历史左边的图标:
效果说明:
上图中我们实现了自定义组合控件,每个条目中实际包含了至少5个安卓组件,箭头右边的文字及每个构成组件各个元素都可以实现灵活配置隐藏或更改颜色等操作。使用时,每个条目是一个整体,非常方便高效。当然我们还可以根据自己的需要在条目中添加更多的控件来实现高效的自定义控件效果:比如在右边的文字和箭头中间,又或者是左边的文字右边添加一个红色小圆圈,实现有更新内容的提示。类似微信或支付宝app的效果。
下面开始教程:
如下图所示,想必类似的条目布局大家都不陌生,在各种app的个人信息页面或者设置页面很常见,我们需要重复的将几种原生控件组合到一起使用:
这时我们就可以把这几个控件组合成一个控件来使用(自定义组合控件),方便高效简洁。
单个条目如下面的效果:
要实现上面的单个条目的组合,首先,我们根据条目的需求新建一个条目的布局文件item_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="@+id/item_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_margin="10dp"
android:src="@drawable/ic_baseline_supervisor_account_24"
android:layout_centerVertical="true"/>
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="用户名"
android:layout_centerVertical="true"
android:textColor="#000000"
android:layout_toRightOf="@+id/item_icon"/>
<TextView
android:id="@+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Crystal"
android:layout_centerVertical="true"
android:textColor="#B8860B"
android:visibility="visible"
android:layout_toLeftOf="@+id/item_arrow"/>
<ImageView
android:id="@+id/item_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="@drawable/ic_baseline_keyboard_arrow_right_24"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp" />
<View
android:id="@+id/item_line"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_alignParentBottom="true"
android:visibility="visible"
android:background="#D3D3D3"/>
</RelativeLayout>
如上,我们以RelativeLayout布局为根布局,包含一个条目的2个ImageView、2个TextView、一个View。然后需要创建一个自定义控件ItemView并继承自LinearLayout,并实现其构造方法,在构造方法中进行初始化,代码如下:
package com.example.CustomItem;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* @author wh445306
* @version 1.0
* @Description ItemView
* @Date 2023-03-14 1:23
*/
public class ItemView extends LinearLayout {
private Boolean isBottom;
private Boolean isItemText;
private Boolean isArrow;
private ImageView itemIcon;
private ImageView rightArrow;
private TextView leftTitle;
private TextView itemText;
private View itemLine;
public ItemView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(getContext()).inflate(R.layout.item_view, this);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ItemView);//解析布局
isBottom = ta.getBoolean(R.styleable.ItemView_show_bottom_line, true); //底部分割线是否显示
isItemText = ta.getBoolean(R.styleable.ItemView_show_right_text, true);//右边描述文字是否显示
isArrow = ta.getBoolean(R.styleable.ItemView_show_right_arrow, true); //右边箭头是否显示
itemIcon = findViewById(R.id.item_icon); //左边图标
rightArrow = findViewById(R.id.item_arrow);//右边箭头
leftTitle = findViewById(R.id.item_title); //左边标题文字
itemText = findViewById(R.id.item_text); //右边描述文字或数值
itemLine = findViewById(R.id.item_line); //底部分割线
itemIcon.setImageDrawable(ta.getDrawable(R.styleable.ItemView_left_icon)); //图标赋值
leftTitle.setText(ta.getText(R.styleable.ItemView_left_title));
itemText.setText(ta.getText(R.styleable.ItemView_right_text));
itemText.setTextColor(ta.getColor(R.styleable.ItemView_right_text_color, Color.BLACK));
itemText.setVisibility(isItemText ? VISIBLE : INVISIBLE);
itemLine.setVisibility(isBottom ? VISIBLE : INVISIBLE);
rightArrow.setVisibility(isArrow ? VISIBLE : GONE);
//回收属性对象
ta.recycle();
}
}
在初始化的方法中,首先我们使用布局填充器 LayoutInflater 的 inflate() 方法来加载刚刚定义的 item_view.xml 布局,并且要特别注意【参二】传入了一个 this 对象,表示指定当前的 ItemView 对象为加载的布局文件的父控件,即 item_view.xml 布局为 ItemView 的子布局。否则,如果传入 null 的话,则就需要我们再使用 addView(child) 方法为当前 ItemView 添加子布局。
然后使用 findViewById() 方法获取控件,并且提供了 setTitle() 和 setImageResource() 方法用于在外部分别设置每个条目的图片和标题,这样就可以在页面的布局文件中引用 ItemView 控件,并且在代码中为每个条目设置不用的内容,这样一个自定义组合控件就告一段落了。
现在我们可以在代码中为每个条目设置不同的内容(图片和标题)了,但是如果我们想直接在页面布局文件的 ItemView 标签内控制每个条目的内容,就像系统控件的各个属性那样,这就需要再为 ItemView 控件自定义一些其它属性了。
如何为我们的自定义控件:ItemView 自定义一些其它属性呢?
首先在 res/values 目录下创建 attrs.xml 属性文件,然后仿照系统的 attrs.xml 属性文件中的格式为 ItemView控件自定义属性,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ItemView">
<attr name="left_icon" format="integer" /><!--左侧图标-->
<attr name="left_title" format="string" /><!--左侧标题文字-->
<attr name="right_text" format="string" /><!--右侧描述文字-->
<attr name="right_text_color" format="color" /><!--右侧描述文字颜色-->
<attr name="show_right_text" format="boolean" /><!--是否显示右侧描述文字-->
<attr name="show_right_arrow" format="boolean" /> <!--是否显示右侧箭头-->
<attr name="show_bottom_line" format="boolean" /> <!--是否显示下划线-->
</declare-styleable>
</resources>
到这里我们就可以在app主布局页面中直接引用我们的自定义组合控件 ItemView 了,并且在布局文件中为控件设置不同的属性,布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical"
tools:context=".MainActivity">
<com.example.CustomItem.ItemView
android:id="@+id/txt1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:left_icon="@drawable/ic_baseline_supervisor_account_24"
app:left_title="用户名"
app:right_text="Crystal"
app:right_text_color="#228B22"
app:show_right_arrow="true"
app:show_bottom_line="true"/>
<com.example.CustomItem.ItemView
android:id="@+id/txt2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:left_icon="@drawable/ic_baseline_settings_24"
app:left_title="中国历史"
app:right_text="上下五千年的岁月"
app:right_text_color="#9400D3"
app:show_right_arrow="true"
app:show_right_text="true"
app:show_left_icon="true"
app:show_bottom_line="true"/>
<com.example.CustomItem.ItemView
android:id="@+id/txt3"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:left_icon="@drawable/ic_baseline_attach_money_24"
app:left_title="资产总额"
app:right_text="186,889.59"
app:show_right_arrow="true"
app:show_bottom_line="true"/>
</LinearLayout>
可以看到,此时我们并没有在代码中为条目设置内容,但布局文件的自定义属性已经生效,如下所示。现在的界面看起来和最开始的写3个 RelativeLayout 布局并没有什么变化,但是我们的处理方式已经完全不一样了,如果有很多这样的条目,那么后续使用将非常方便,而且布局文件的条理也会非常清晰。
然后运行起来效果就出来了:
作者原创文章,转载请注明出处,谢谢