自定义组合控件相对于自定义控件简单很多,也是我们在实际开发中经常使用的。比如下面这张图,就可以用组合控件来实现。
自定义组合控件的步骤
- 在values->attrs.xml中自定义控件的属性
- 创建自定义View类并继承已有的控件(如:RelativeLayout、LinearLayout等)
- 在布局文件layout中添加自定义控件
- 在自定义View的构造方法中获取我们自定义的属性
实践
第一步:在values->attrs.xml中定义控件的属性
<declare-styleable name="MyItemView">
<attr name="iv_left" format="reference"/>
<attr name="name" format="string"/>
</declare-styleable>
定义了左边的图标和中间的文字内容,右边的箭头可以在自定义控件内的布局中写死,因为每个条目都有且不需要变
第二步:创建自定义View类并继承已有的控件(如:RelativeLayout、LinearLayout等)
public class MyItemView extends RelativeLayout {
private TextView mContent;
private ImageView mIvLeft;
public MyItemView(Context context) {
this(context, null);
}
public MyItemView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyItemView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context, attrs);
}
private void initView(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyItemView);
//从布局文件中获取到设置内容
int ivLeft = typedArray.getResourceId(R.styleable.MyItemView_iv_left, R.drawable.icon_lock);
String name = typedArray.getString(R.styleable.MyItemView_name);
//回收
typedArray.recycle();
LayoutInflater.from(context).inflate(R.layout.view_myitem, this);
//获取控件ID
mIvLeft = (ImageView) findViewById(R.id.iv_left);
mContent = (TextView) findViewById(R.id.name);
//设置获取到的内容
mIvLeft.setImageResource(ivLeft);
mContent.setText(name);
}
/**
* 设置左边图片
*/
public void setLeftIcon(int resourceId) {
mIvLeft.setImageResource(resourceId);
}
/**
* 设置内容
*/
public void setContent(String name) {
mContent.setText(name);
}
}
重写三个构造方法,传一个参数的通过在代码中创建View会调用,传两个参数的通过在xml中定义View会调用,传三个参数的是不调用的,要由View显式调用,比如我们在两个参数中使用this(context, attrs, 0),调用第三参数。
也可以像上面代码那样,在第一个参数里调用第二个,在第二个参数里调用第三个,这样就可以直接在第三个参数里设置获取我们需要的东西了。
view_myitem布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/item_root"
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="#fff">
<ImageView
android:id="@+id/iv_left"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
tools:background="@drawable/icon_download"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/iv_left"
android:textColor="#888"
android:textSize="20sp"
tools:text="测试"/>
<ImageView
android:layout_width="10dp"
android:layout_height="18dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="16dp"
android:background="@drawable/icon_next"/>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_alignParentBottom="true"
android:background="#999"/>
</RelativeLayout>
第三步:在布局文件layout中加入自定义控件
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.cn.liuyz.customviewdemo.MainActivity">
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="点击1"/>
<com.cn.liuyz.customviewdemo.MyItemView
android:id="@+id/item_view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:iv_left="@drawable/icon_lock"
custom:name="密码重置"/>
<com.cn.liuyz.customviewdemo.MyItemView
android:id="@+id/item_view2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:iv_left="@drawable/icon_download"
custom:name="关于App"/>
</LinearLayout>
在布局文件中添加 xmlns:custom=”http://schemas.android.com/apk/res-auto” custom名字可以随便定义,然后在布局文件中设置我们需要的资源
第四步:在自定义View的构造方法中获取我们自定义的属性
private void initView(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyItemView);
//从布局文件中获取到设置内容
int ivLeft = typedArray.getResourceId(R.styleable.MyItemView_iv_left, R.drawable.icon_lock);
String name = typedArray.getString(R.styleable.MyItemView_name);
//回收
typedArray.recycle();
LayoutInflater.from(context).inflate(R.layout.view_myitem, this);
//获取控件ID
mIvLeft = (ImageView) findViewById(R.id.iv_left);
mContent = (TextView) findViewById(R.id.name);
//设置获取到的内容
mIvLeft.setImageResource(ivLeft);
mContent.setText(name);
}
自定义组合控件就是这么简单
其他
也可以在自定义View中预留方法,单独设置左边图标和中间内容
/**
* 设置左边图片
*/
public void setLeftIcon(int resourceId) {
mIvLeft.setImageResource(resourceId);
}
/**
* 设置内容
*/
public void setContent(String name) {
mContent.setText(name);
}
再通过在布局中的获取自定义控件,在代码中进行设置
private void initView() {
MyItemView itemView1 = (MyItemView) findViewById(R.id.item_view1);
MyItemView itemView2 = (MyItemView) findViewById(R.id.item_view2);
itemView1.setLeftIcon(R.drawable.icon_lock);
itemView1.setContent("密码重置");
itemView2.setLeftIcon(R.drawable.icon_download);
itemView2.setContent("关于App");
}