Android-自定义控件-带头部和尾部的文本显示框

769 阅读3分钟

前言

​ 路过的看看就好,本文章目的是记录一下业务控件,产品的需求,你永远想不到他们的下一步需求。

简介

  1. 带头部文字。
  2. 带尾部图标。
  3. 中间显示所需文本。
  4. 支持xml控制头部文字样式。
  5. 支持xml控制中间文本样式。
  6. 支持xml控制尾部图标

效果图

带头部和尾部的文本显示框.jpg

使用方法

<!--  实名认证  -->
<com.momin.common.widget.SelectTextView
    android:id="@+id/stv_certification_detail_car_sim"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    app:headerText="@string/certification_detail_car_sim_tips"
    android:text="@string/certification_detail_car_sim_false"
    android:textColor="@color/c_5D82A6"/>

源码在这

业务控件,注释很详细,不再额外说明了。

attrs.xml 属性定义

<!--  公共属性  -->
<!--  前置文字内容  -->
<attr name="headerText" format="string"/>
<!--  前置文字大小  -->
<attr name="headerTextSize" format="dimension"/>
<!--  前置文字大小  -->
<attr name="headerTextStyle">
    <flag name="normal" value="0" />
    <flag name="bold" value="1" />
    <flag name="italic" value="2" />
</attr>
<!--  前置文字颜色  -->
<attr name="headerTextColor" format="reference|color"/>
<!--  前置文字左边间距  -->
<attr name="headerPaddingStart" format="dimension"/>
<!--  前置文字右边间距  -->
<attr name="headerPaddingEnd" format="dimension"/>
<!--  前置文字顶部间距  -->
<attr name="headerPaddingTop" format="dimension"/>
<!--  前置文字底部间距  -->
<attr name="headerPaddingBottom" format="dimension"/>
<!--  公共属性  -->

<!--  带前置文字以及后置图标的文本显示框  -->
<declare-styleable name="SelectTextView">
    <!--  文字内容  -->
    <attr name="android:text"/>
    <!--  文字大小  -->
    <attr name="android:textSize"/>
    <!--  文字颜色  -->
    <attr name="android:textColor"/>
    <!--  对齐方式  -->
    <attr name="android:gravity"/>
    <!--  文字开始边距  -->
    <attr name="textMarginStart" format="dimension"/>
    <!--  文字结束边距  -->
    <attr name="textMarginEnd" format="dimension"/>
    <!--  文字顶部边距  -->
    <attr name="textMarginTop" format="dimension"/>
    <!--  文字底部边距  -->
    <attr name="textMarginBottom" format="dimension"/>
    <!--  文字开始间距  -->
    <attr name="textPaddingStart" format="dimension"/>
    <!--  文字结束间距  -->
    <attr name="textPaddingEnd" format="dimension"/>
    <!--  文字顶部间距  -->
    <attr name="textPaddingTop" format="dimension"/>
    <!--  文字底部间距  -->
    <attr name="textPaddingBottom" format="dimension"/>
    <!--  提示文字  -->
    <attr name="android:hint"/>
    <!--  提示文字颜色  -->
    <attr name="android:textColorHint"/>
    <!--  前置文字内容  -->
    <attr name="headerText"/>
    <!--  前置文字大小  -->
    <attr name="headerTextSize"/>
    <!--  前置文字大小  -->
    <attr name="headerTextStyle"/>
    <!--  前置文字颜色  -->
    <attr name="headerTextColor"/>
    <!--  前置文字左边间距  -->
    <attr name="headerPaddingStart"/>
    <!--  前置文字右边间距  -->
    <attr name="headerPaddingEnd"/>
    <!--  前置文字顶部间距  -->
    <attr name="headerPaddingTop"/>
    <!--  前置文字底部间距  -->
    <attr name="headerPaddingBottom"/>
    <!--  后置图标  -->
    <attr name="endIcon" format="reference" />
    <!--  后置图标是否显示  -->
    <attr name="endIconVisible" format="boolean" />
</declare-styleable>

common_textview_select.xml UI布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!--  头部文字  -->
    <TextView
        android:id="@+id/tv_text_select_header"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <!--  中间内容  -->
    <TextView
        android:id="@+id/tv_text_select_content"
        app:layout_constraintStart_toEndOf="@id/tv_text_select_header"
        app:layout_constraintEnd_toStartOf="@id/tv_text_select_icon"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:singleLine="true"
        android:ellipsize="end"/>
    <!--  尾部图标  -->
    <ImageView
        android:id="@+id/tv_text_select_icon"
        android:layout_marginStart="2dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/common_arrow_right_gray"/>
</androidx.constraintlayout.widget.ConstraintLayout>

SelectTextView.java 自定义控件源码

package com.momin.common.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;

import com.momin.common.R;

/**
 * <p>Title: SelectTextView</p>
 * <p>Description: 带头部文字以及尾部图标的文本显示框 </p>
 * <p>Copyright: </p>
 * <p>Company: </p>
 *
 * @author Momin
 * @version 1.0
 * @date 2021/3/17 9:45
 */

public class SelectTextView extends RelativeLayout {

    private TextView tvHead;
    private TextView tvContent;
    private ImageView ivEndIcon;

    public SelectTextView(Context context) {
        super(context);
        init(context, null);
    }

    public SelectTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public SelectTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    /**
     * 初始化
     *
     * @param context   上下文
     * @param attrs     资源对象
     */
    private void init(Context context, AttributeSet attrs) {
        initView(context);

        // 获取资源对象
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SelectTextView);

        // 初始化头部文字
        CharSequence headText = typedArray.getText(R.styleable.SelectTextView_headerText);
        if (!TextUtils.isEmpty(headText)) {
            // 头部不为空时
            initHeaderText(context, typedArray, headText);
        }

        // 初始化尾部图标
        initEndIcon(typedArray);

        // 初始化中间内容
        initContentText(context, typedArray);

        // 回收资源对象
        typedArray.recycle();
    }

    /**
     * 初始化视图
     *
     * @param context   上下文
     */
    private void initView(Context context) {
        LayoutInflater.from(context).inflate(R.layout.common_textview_select, this);
        tvHead = findViewById(R.id.tv_text_select_header);
        tvContent = findViewById(R.id.tv_text_select_content);
        ivEndIcon = findViewById(R.id.tv_text_select_icon);
    }

    /**
     * 初始化头部文字
     *
     * @param context       上下文
     * @param typedArray    资源对象
     * @param text          头部内容
     */
    private void initHeaderText(Context context, TypedArray typedArray, CharSequence text) {
        // 头部字体颜色
        setViewTextColor(context, tvHead, R.styleable.SelectTextView_headerTextColor, typedArray);
        // 头部字体大小
        setViewTextSize(tvHead, R.styleable.SelectTextView_headerTextSize, typedArray);
        // 头部开始间距
        int paddingStart = (int)typedArray.getDimension(R.styleable.SelectTextView_headerPaddingStart, 0);
        // 头部结束间距
        int paddingEnd = (int)typedArray.getDimension(R.styleable.SelectTextView_headerPaddingEnd, 0);
        // 头部顶部间距
        int paddingTop = (int)typedArray.getDimension(R.styleable.SelectTextView_headerPaddingTop, 0);
        // 头部底部间距
        int paddingBottom = (int)typedArray.getDimension(R.styleable.SelectTextView_headerPaddingBottom, 0);

        tvHead.setText(text);
        tvHead.setPadding(paddingStart, paddingTop, paddingEnd, paddingBottom);
    }

    /**
     * 初始化尾部图标
     *
     * @param typedArray    资源对象
     */
    private void initEndIcon(TypedArray typedArray) {
        boolean flag = typedArray.getBoolean(R.styleable.SelectTextView_endIconVisible, true);
        if (flag) {
            ivEndIcon.setVisibility(VISIBLE);
            ivEndIcon.setImageResource(typedArray.getResourceId(R.styleable.SelectTextView_endIcon,
                    R.mipmap.common_arrow_right_gray));
        } else {
            ivEndIcon.setVisibility(GONE);
        }
    }

    /**
     * 初始化中间文本
     *
     * @param context       上下文
     * @param typedArray    资源对象
     */
    private void initContentText(Context context, TypedArray typedArray) {
        // 初始内容
        CharSequence text = typedArray.getText(R.styleable.SelectTextView_android_text);
        if (!TextUtils.isEmpty(text)) {
            tvContent.setText(text);
        }
        // 字体大小
        setViewTextSize(tvContent, R.styleable.SelectTextView_android_textSize, typedArray);
        // 字体颜色
        setViewTextColor(context, tvContent, R.styleable.SelectTextView_android_textColor, typedArray);
        // 设置间距
        setContentPadding(typedArray);
        // 设置边距
        setContentMargin(typedArray);
        // 设置对其方式
        setContentGravity(typedArray);
        // 设置提示样式
        initContentHint(context, typedArray);
    }

    /**
     * 设置文本间距
     *
     * @param typedArray 资源对象
     */
    private void setContentPadding(TypedArray typedArray) {
        // 开始间距
        int paddingStart = (int)typedArray.getDimension(R.styleable.SelectTextView_textPaddingStart, 0);
        // 结束间距
        int paddingEnd = (int)typedArray.getDimension(R.styleable.SelectTextView_textPaddingEnd, 0);
        // 顶部间距
        int paddingTop = (int)typedArray.getDimension(R.styleable.SelectTextView_textPaddingTop, 0);
        // 底部间距
        int paddingBottom = (int)typedArray.getDimension(R.styleable.SelectTextView_textPaddingBottom, 0);
        tvContent.setPadding(paddingStart, paddingTop, paddingEnd, paddingBottom);
    }

    /**
     * 设置文本边距
     *
     * @param typedArray 资源对象
     */
    private void setContentMargin(TypedArray typedArray) {
        // 开始边距
        int marginStart = (int)typedArray.getDimension(R.styleable.SelectTextView_textMarginStart, 0);
        // 结束边距
        int marginEnd = (int)typedArray.getDimension(R.styleable.SelectTextView_textMarginEnd, 0);
        // 顶部边距
        int marginTop = (int)typedArray.getDimension(R.styleable.SelectTextView_textMarginTop, 0);
        // 底部边距
        int marginBottom = (int)typedArray.getDimension(R.styleable.SelectTextView_textMarginBottom, 0);
        ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams)tvContent.getLayoutParams();
        layoutParams.setMargins(marginStart, marginTop, marginEnd, marginBottom);
        tvContent.setLayoutParams(layoutParams);
    }

    /**
     * 设置对其方式
     *
     * @param typedArray 资源对象
     */
    private void setContentGravity(TypedArray typedArray) {
        tvContent.setGravity(typedArray.getInt(R.styleable.SelectTextView_android_gravity,
                Gravity.END|Gravity.CENTER_VERTICAL));
    }

    /**
     * 初始化文本提示文字
     *
     * @param context       上上下文
     * @param typedArray    资源对象
     */
    private void initContentHint(Context context, TypedArray typedArray) {
        // 提示文字颜色
        int color = typedArray.getColor(R.styleable.SelectTextView_android_textColorHint,
                ContextCompat.getColor(context, R.color.c_D2D0DC));
        tvContent.setHintTextColor(color);
        CharSequence hintText = typedArray.getText(R.styleable.SelectTextView_android_hint);
        if (!TextUtils.isEmpty(hintText)) {
            // 提示文字不为空
            // 提示内容
            tvContent.setHint(hintText);
        }
    }

    /**
     * 设置字体大小
     *
     * @param view          被设置对象
     * @param attrId        属性Id
     * @param typedArray    资源对象
     */
    private void setViewTextSize(TextView view, int attrId, TypedArray typedArray) {
        float size = typedArray.getDimension(attrId, 14 * view.getPaint().density);
        view.getPaint().setTextSize(size);
    }

    /**
     * 设置字体颜色
     *
     * @param context       上下文
     * @param view          被设置对象
     * @param attrId        属性Id
     * @param typedArray    资源对象
     */
    private void setViewTextColor(Context context, TextView view, int attrId, TypedArray typedArray) {
        int color = typedArray.getColor(attrId,
                ContextCompat.getColor(context, R.color.c_2B303C));
        view.setTextColor(color);
    }

    /**
     * 获取内容
     *
     * @return 内容
     */
    public CharSequence getText() {
        if (tvContent == null) {
            return null;
        } else {
            return tvContent.getText();
        }
    }

    /**
     * 设置内容
     *
     * @param text 被设置内容
     */
    public void setText(CharSequence text) {
        if (tvContent != null) {
            tvContent.setText(text);
        }
    }
}