自定义组合控件

本文介绍了一种自定义ItemView组件的方法,该组件适用于Android应用中的列表项展示。通过XML自定义属性简化布局配置,提高了开发效率并保持良好的可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上效果图:


首先说明下,实现这种效果有很多种方式,就是用Linearlayout来写,完全可以做到这种效果,但是,后期维护起来,那真是谁接手谁知道。如果是固定项,并条数不多,可以不用费这么多精力,当然,并不是说这样做不方便,其他不多说,谁用谁知道。

先讲下思路:

1、每一条左边是个icon,中间是一个text,右边是一个向右箭头

2、每一条之间用一条线隔开

3、最外层用一个垂直的LinearLayout来包着,Linearlayout背景选用带弧角的矩形


我这里采用组合控件,即用布局来写自定义控件,命名为ItemView

布局非常简单,就一个水平LinearLayout,再加ImageView+TextView+ImageView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/item_height"
    android:minHeight="@dimen/item_height"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="@dimen/item_height"
        android:layout_height="@dimen/item_height"
        android:padding="5dp"
        android:scaleType="fitCenter"
        android:src="@drawable/app_loading0" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="10dp"
        android:layout_weight="1.0"
        android:gravity="center_vertical"
        android:text="@string/app_name"
        android:textColor="@color/black_90"
        android:textSize="@dimen/text_size_normal" />

    <ImageView
        android:layout_width="@dimen/item_height"
        android:layout_height="@dimen/item_height"
        android:scaleType="center"
        android:src="@drawable/arrow_right" />

</LinearLayout>

接下来,我们希望在用这个ItemView可以直接在布局时引用drawable和string,在res目录的value目录下,建立一个xml的资源文件attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- item style -->
    <declare-styleable name="item_view">
        <attr name="item_icon" format="reference" />
        <attr name="item_title" format="reference|string" />
    </declare-styleable>

</resources>

attrs.xml里声明了一个item_view的自定义属性,在写xml布局时,可以直接引用的

<attr name="item_icon" format="reference" /> item_icon是一个引用类型,即 item_view:item_icon="@drawable/abc"
<pre name="code" class="html"><attr name="item_title" format="reference|string" />  item_title是一个引用类型,也可以直接用字符串,即 item_view:item_title="@string/app_name" 或 "测试"

 

声明了这些之后,开始写代码ItemView.java:

package com.ytmfdw.item;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

public class ItemView extends FrameLayout {

	View view;
	Context mContext;

	public ItemView(Context context) {
		super(context);
		init(context);
	}

	public ItemView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
		TypedArray localTypedArray = context.obtainStyledAttributes(attrs,
				R.styleable.item_view);
		Drawable drawable = localTypedArray.getDrawable(0);
		String title = localTypedArray.getString(1);
		setData(drawable, title);
		localTypedArray.recycle();
	}

	private void init(Context context) {
		mContext = context;
		view = LayoutInflater.from(mContext).inflate(R.layout.item_tool, this,
				true);
	}

	public void setData(Drawable drawable, String str) {
		((ImageView) (view.findViewById(R.id.iv_icon)))
				.setImageDrawable(drawable);
		((TextView) (view.findViewById(R.id.tv_content))).setText(str);
	}

}

代码非常少,只有一个要点:

public ItemView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
		TypedArray localTypedArray = context.obtainStyledAttributes(attrs,
				R.styleable.item_view);
		Drawable drawable = localTypedArray.getDrawable(0);
		String title = localTypedArray.getString(1);
		setData(drawable, title);
		localTypedArray.recycle();
	}

在这个构造方法里,要对属性进行设置,

TypedArray localTypedArray = context.obtainStyledAttributes(attrs,
                R.styleable.item_view);//这行代码的意思,就是读取xml布局文件中的item_view的属性


//这两行代码的意思是把读取出来的属性数组取出来,并分别赋值给对应的变量,需要注意的是

Drawable drawable = localTypedArray.getDrawable(0);
        String title = localTypedArray.getString(1);

或许这样写更明了些:

Drawable drawable = localTypedArray
                .getDrawable(R.styleable.item_view_item_icon);
        String title = localTypedArray
                .getString(R.styleable.item_view_item_title);

//获取到了值后,就给ItemView设置值

setData(drawable, title);

//完事后,记得把localTypedArray释放掉:

localTypedArray.recycle();

完了

使用也很方便,在activity_main.xml布局中这样写:

需要注意一点: 要加上一条:xmlns:item="http://schemas.android.com/apk/res-auto",这句的作用就是声明item属性来自于自定义的

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:item="http://schemas.android.com/apk/res-auto"
    android:id="@+id/sv_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/wheat" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/bg_tool_content"
            android:orientation="vertical"
            android:padding="1dp" >

            <com.ytmfdw.item.ItemView
                android:id="@+id/item_qrcode"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_top_selector"
                android:clickable="true"
                item:item_icon="@drawable/qrcode_icon"
                item:item_title="@string/item_qrcode" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/red" />

            <com.ytmfdw.item.ItemView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_normal_selector"
                android:clickable="true"
                item:item_icon="@drawable/app_loading0"
                item:item_title="充数一" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/red" />

            <com.ytmfdw.item.ItemView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_normal_selector"
                android:clickable="true"
                item:item_icon="@drawable/app_loading0"
                item:item_title="充数一" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/red" />

            <com.ytmfdw.item.ItemView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_normal_selector"
                android:clickable="true"
                item:item_icon="@drawable/app_loading0"
                item:item_title="充数一" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/red" />

            <com.ytmfdw.item.ItemView
                android:id="@+id/item_barcode"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_bottom_selector"
                android:clickable="true"
                item:item_icon="@drawable/barcode_icon"
                item:item_title="@string/item_barcode" />
        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="5dp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/bg_tool_content"
            android:orientation="vertical"
            android:padding="1dp" >

            <com.ytmfdw.item.ItemView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_top_selector"
                android:clickable="true"
                item:item_icon="@drawable/qrcode_icon"
                item:item_title="@string/item_qrcode" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/red" />

            <com.ytmfdw.item.ItemView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_normal_selector"
                android:clickable="true"
                item:item_icon="@drawable/app_loading0"
                item:item_title="充数一" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/red" />

            <com.ytmfdw.item.ItemView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_normal_selector"
                android:clickable="true"
                item:item_icon="@drawable/app_loading0"
                item:item_title="充数一" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/red" />

            <com.ytmfdw.item.ItemView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_normal_selector"
                android:clickable="true"
                item:item_icon="@drawable/app_loading0"
                item:item_title="充数一" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/red" />

            <com.ytmfdw.item.ItemView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/button_item_bg_bottom_selector"
                android:clickable="true"
                item:item_icon="@drawable/barcode_icon"
                item:item_title="@string/item_barcode" />
        </LinearLayout>
    </LinearLayout>

</ScrollView>

另外讲些题外话,像这样的布局,Linearlayout背景是个带弧的矩形,完全可以用xml的shap来写 bg_tool_content.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

    <corners android:radius="@dimen/item_arc" />

    <solid android:color="#00000000" />

    <stroke
        android:width="1dp"
        android:color="@color/red" />

</shape>

 <corners android:radius="@dimen/item_arc" /> 表示弧角
<pre name="code" class="html"> <solid android:color="#00000000" />     表示填空颜色,这里写的是透明的

<pre name="code" class="html">     <stroke
        android:width="1dp"
        android:color="@color/red" />     这表示的是描边颜色

 
 

像这样写,不会有屏幕适配问题,怎么放大缩小都不会有问题,但会有另外一个问题:里面的item如果是方角,就会把外面的弧角给遮住,就不会有上图那样的效果了,我的解决方法是:

第一个item采用左上角右上角为弧角形,弧度与LinearLayout的四个弧度一致(这里还加了点击效果)  button_item_bg_normal_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
            <corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:topLeftRadius="@dimen/item_arc" android:topRightRadius="@dimen/item_arc" />

            <solid android:color="@color/bisque" />
        </shape></item>
    <item><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
            <corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:topLeftRadius="@dimen/item_arc" android:topRightRadius="@dimen/item_arc" />

            <solid android:color="@color/beige" />
        </shape></item>

</selector>


最后一个item采用左下角右下角为弧角形,弧度与LinearLayout的四个弧度一致  button_item_bg_bottom_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
            <corners android:bottomLeftRadius="@dimen/item_arc" android:bottomRightRadius="@dimen/item_arc" android:topLeftRadius="0dp" android:topRightRadius="0dp" />

            <solid android:color="@color/bisque" />
        </shape></item>
    <item><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
            <corners android:bottomLeftRadius="@dimen/item_arc" android:bottomRightRadius="@dimen/item_arc" android:topLeftRadius="0dp" android:topRightRadius="0dp" />

            <solid android:color="@color/beige" />
        </shape></item>

</selector>

中间的项,就不用弧角形:button_item_bg_normal_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
            <solid android:color="@color/bisque" />
        </shape></item>
    <item><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
            <solid android:color="@color/beige" />
        </shape></item>

</selector>

好了,基本完成,源码下载: 请点击



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ytmfdw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值