Android入门06 -- 自定义控件

自定义组合控件

  • 将几个子控件组合在一起,形成一个可复用的新的组合控件,自定义组合控件一般继承自RelativeLayout或者LinearLayout,其实现步骤如下:
    • 第一步:创建组合控件类继承自RelativeLayout或者LinearLayout
    • 第二步:创建layout布局文件,在组合控件的构造方法中,加载布局文件;
    • 第三步:为组合控件创建属性文件attrs.xml,在组合控件的构造方法中,加载属性文件,并给组合控件设置属性值;
    • 第四步:新的组合控件,供外界使用;
  • 现在我们来实现一个自定义组合控件,命名为SFCommonCell,实现的效果图如下所示:
image.png
  • 第一步:首先自定义组合控件类SFCommonCell,继承自RelativeLayout,代码如下:
package com.example.yyshop.general.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.example.yyshop.R;

public class SFCommonCell extends RelativeLayout {

    private ImageView iv_left;
    private TextView tv_text;
    private ImageView iv_right;

    private String text;
    private int textColor;
    private float textSize;
    private int leftIcon;
    private int rightIcon;

    public SFCommonCell(Context context) {
        this(context,null);
    }

    public SFCommonCell(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public SFCommonCell(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context,attrs);
    }

    private void initView(Context context,AttributeSet attrs) {
        //从XML中加载布局
        LayoutInflater.from(context).inflate(R.layout.sf_common_cell,this,true);
        iv_left = findViewById(R.id.sf_common_cell_iv_left);
        tv_text = findViewById(R.id.sf_common_cell_tv);
        iv_right = findViewById(R.id.sf_common_cell_iv_right);

        //从Attrs.xml中加载自定义属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.SFCommonCell);
        text = typedArray.getString(R.styleable.SFCommonCell_text);
        textColor = typedArray.getColor(R.styleable.SFCommonCell_textColor, Color.BLACK);
        textSize = typedArray.getDimension(R.styleable.SFCommonCell_textSize,20f);
        leftIcon = typedArray.getResourceId(R.styleable.SFCommonCell_leftIcon,0);
        rightIcon = typedArray.getResourceId(R.styleable.SFCommonCell_rightIcon,0);

        //将Attrs.xml中属性值 赋值给目标控件
        setText(text);
        setTextColor(textColor);
        setTextSize(textSize);
        setLeftIcon(leftIcon);
        setRightIcon(rightIcon);

        //typedArray必须回收
        typedArray.recycle();
    }

    //设置属性
    public void setText(String text) {
        tv_text.setText(text);
    }

    public void setTextColor(int color) {
        tv_text.setTextColor(color);
    }

    public void setTextSize(float size) {
        tv_text.setTextSize(size);
    }

    public void setLeftIcon(int resourceId) {
        iv_left.setImageResource(resourceId);
    }

    public void setRightIcon(int resourceId) {
        iv_right.setImageResource(resourceId);
    }
}
  • 第二步:组合控件的布局文件为sf_common_cell.xml,实现如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="match_parent"
    android:layout_height="75dp"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:id="@+id/sf_common_cell_iv_left"
        android:layout_centerVertical="true"
        android:layout_marginLeft="15dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/sf_common_cell_tv"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/sf_common_cell_iv_left"
        android:layout_marginLeft="15dp"/>

    <ImageView
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:id="@+id/sf_common_cell_iv_right"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="15dp"/>

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

</RelativeLayout>
  • 在组合控件的构造方法中,通过LayoutInflater去加载布局文件,实现如下:
image.png
  • 第三步:为组合控件提供自定义属性,可通过创建属性文件的方式,现创建属性文件attrs.xml,代码实现如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- SFCommonCell的自定义属性 -->
    <declare-styleable name="SFCommonCell">
        <!-- 标题 -->
        <attr name="text" format="string"/>
        <!-- 标题颜色 -->
        <attr name="textColor" format="color"/>
        <!-- 标题文字大小 -->
        <attr name="textSize" format="dimension"/>
        <!-- 左侧图片 -->
        <attr name="leftIcon" format="reference"/>
        <!-- 右侧图片 -->
        <attr name="rightIcon" format="reference"/>
    </declare-styleable>
</resources>
  • 在组合控件的构造方法中,加载属性文件,并将属性赋值给目标子控件,实现如下:
image.png
  • 注意⚠️:获取的属性typedArray,必须调用recycle进行回收,防止内存泄漏;
  • 第四步:外界使用自定义组合控件SFCommonCell,如下所示:
image.png
  • 在创建属性文件attrs.xml时,内部定义属性时,用到的format其类型有如下几种:
image.png
  • reference:参考某一资源ID,用于图片资源;
<attr name="leftIcon" format="reference"/>
app:leftIcon="@drawable/add_select"
  • color:颜色值;
<attr name="textColor" format="color"/>
app:textColor="@color/black"
  • string:字符串值;
<attr name="text" format="string"/>
app:text="中国工商银行"
  • dimension:尺寸值;
<attr name="textSize" format="dimension"/>
app:textSize="8sp"

推荐阅读更多精彩内容