自定义控件ImageText

在开发的时候,经常会用到这样一个控件:上面是图片,下面是文字,有同学就问了,TextView本身不就可以同时显示图片和文字吗?但是,公司的需求往往不是那么简单,比如:按下的时候,图片要发生改变,文字颜色要发生改变,整个控件的背景颜色也要相应加深。这个时候,如果定义一大堆的监听事件,会让代码凌乱,而且效率低下,是时候自定义一个控件了。

  1. 定义styleable,文件名为attrs.xml,放在values文件夹下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ImageText">
        <attr name="width" format="dimension" />
        <attr name="height" format="dimension" />

        <attr name="image_width" format="dimension" />
        <attr name="image_height" format="dimension" />
        <attr name="image_normal" format="reference|color" />
        <attr name="image_pressed" format="reference|color" />

        <attr name="padding_top" format="dimension" />
        <attr name="padding_right" format="dimension" />
        <attr name="padding_bottom" format="dimension" />
        <attr name="padding_left" format="dimension" />

        <attr name="bg_normal_color" format="reference|color" />
        <attr name="bg_pressed_color" format="reference|color" />

        <attr name="text_margin_top" format="dimension" />
        <attr name="text_normal_color" format="reference|color" />
        <attr name="text_pressed_color" format="reference|color" />
        <attr name="text_size" format="dimension" />
        <attr name="text" format="string" />
    </declare-styleable>
</resources>
  1. 组成控件的UI view_image_text.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:id="@+id/ll_frame"
    android:descendantFocusability="blocksDescendants">

    <View
        android:id="@+id/view_space"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:visibility="gone"/>

    <ImageView
        android:id="@+id/iv_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <View
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <TextView
        android:id="@+id/tv_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:ellipsize="end"
        android:gravity="center"/>

</LinearLayout>
  1. 自定义View:
package com.pax.supercashier.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.pax.supercashier.R;
import com.pax.supercashier.utils.UIUtils;

/**
 * 2017-12-25
 * @author Jason Zhan
 */
public class ImageText extends LinearLayout {
    private LinearLayout ll_frame;
    private ImageView iv_image;
    private View view_space;
    private TextView tv_text;

    private int image_normal;
    private int image_pressed;

    private int bg_normal_color;
    private int bg_pressed_color;

    private int text_normal_color;
    private int text_pressed_color;

    public ImageText(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.view_image_text, this);

        ll_frame = findViewById(R.id.ll_frame);
        iv_image = findViewById(R.id.iv_image);
        view_space = findViewById(R.id.view_space);
        tv_text = findViewById(R.id.tv_text);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ImageText);
        final int width = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_width, 0));
        final int height = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_height, 0));

        final int image_width = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_image_width, 0));
        final int image_height = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_image_height, 0));

        image_normal = typedArray.getResourceId(R.styleable.ImageText_image_normal, R.mipmap.ic_launcher);
        image_pressed = typedArray.getResourceId(R.styleable.ImageText_image_pressed, R.mipmap.ic_launcher);

        final int padding_left = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_padding_left, 0));
        final int padding_top = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_padding_top, 0));
        final int padding_right = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_padding_right, 0));
        final int padding_bottom = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_padding_bottom, 0));

        bg_normal_color = typedArray.getColor(R.styleable.ImageText_bg_normal_color, 0);
        bg_pressed_color = typedArray.getColor(R.styleable.ImageText_bg_pressed_color, 0);

        final int text_margin_top = UIUtils.dip2px(context, typedArray.getDimension(R.styleable.ImageText_text_margin_top, 0));
        text_normal_color = typedArray.getColor(R.styleable.ImageText_text_normal_color, 0);
        text_pressed_color = typedArray.getColor(R.styleable.ImageText_text_pressed_color, 0);
        final int text_size = UIUtils.sp2px(context, typedArray.getDimension(R.styleable.ImageText_text_size, UIUtils.sp2px(context, 16)));
        String text = typedArray.getString(R.styleable.ImageText_text);

        typedArray.recycle();

        LayoutParams params = new LayoutParams(width, height);
        if (width == 0 || height == 0) {
            params.width = LayoutParams.MATCH_PARENT;
            params.height = LayoutParams.MATCH_PARENT;
        }
        ll_frame.setLayoutParams(params);
        ll_frame.setPadding(padding_left, padding_top, padding_right, padding_bottom);
        ll_frame.setBackgroundColor(bg_normal_color);

        if (TextUtils.isEmpty(text)) {
            tv_text.setVisibility(View.GONE);
            view_space.setVisibility(View.VISIBLE);
        } else {
            tv_text.setVisibility(View.VISIBLE);
            view_space.setVisibility(View.GONE);
            tv_text.setText(text);
            tv_text.setTextSize(text_size);
            tv_text.setTextColor(text_normal_color);
        }


        ViewTreeObserver vto = tv_text.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                tv_text.getViewTreeObserver().removeGlobalOnLayoutListener(this);

                if (image_width == 0 || image_height == 0) {
                    int imageTempHeight = height - padding_top - padding_bottom - text_margin_top - tv_text.getHeight();
                    int imageTempWidth = width - padding_left - padding_right;
                    int imageWidth = imageTempWidth < imageTempHeight ? imageTempWidth : imageTempHeight;

                    iv_image.setLayoutParams(new LayoutParams(imageWidth, imageWidth));
                    iv_image.setScaleType(ImageView.ScaleType.FIT_XY);
                    iv_image.setBackgroundResource(image_normal);
                } else {
                    iv_image.setLayoutParams(new LayoutParams(image_width, image_height));
                    iv_image.setScaleType(ImageView.ScaleType.FIT_XY);
                    iv_image.setBackgroundResource(image_normal);
                }
            }
        });
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                tv_text.setTextColor(text_pressed_color);
                iv_image.setBackgroundResource(image_pressed);
                ll_frame.setBackgroundColor(bg_pressed_color);
                break;
            case MotionEvent.ACTION_UP:
                tv_text.setTextColor(text_normal_color);
                iv_image.setBackgroundResource(image_normal);
                ll_frame.setBackgroundColor(bg_normal_color);
                break;

            default:
                break;
        }


        return true;
    }
}
  1. 使用:
    先在根布局添加
xmlns:it="http://schemas.android.com/apk/res-auto"

再使用:

<com.pax.supercashier.view.ImageText
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            it:image_width="@dimen/size_top_menu_width"
            it:image_height="@dimen/size_top_menu_height"
            it:bg_normal_color="@color/blue_dark"
            it:bg_pressed_color="@color/blue_dark_pressed"
            it:padding_top="@dimen/padding_frame"
            it:padding_bottom="@dimen/padding_frame"
            it:padding_right="0dp"
            it:padding_left="0dp"
            it:text_margin_top="@dimen/margin_menu_top"
            it:text="Staff"
            it:text_size="@dimen/text_size_menu"
            it:text_normal_color="@color/white"
            it:text_pressed_color="@color/white"
            it:image_normal="@drawable/staff_normal"
            it:image_pressed="@drawable/staff_pressed"
            android:layout_centerInParent="true"/>

好了,一个框架就搭起来了,剩下的工作就是默认值的配置,wrap_content的支持,方向的支持,UI适配等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ithouse

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

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

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

打赏作者

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

抵扣说明:

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

余额充值