自带搜索和清除按钮的EditText

本文介绍了如何在Android开发中创建一个自定义的SearchEditText组件,该组件在编辑框有内容时显示删除按钮,无内容时可进行搜索操作。通过继承EditText,设置自定义属性,以及监听文本变化来动态显示或隐藏清除图标。

低功耗蓝牙项目,需要一块懂省电的板

思澈 SF32LB52 芯片,BLE 协议栈深度优化,上手即开发

项目中需要用到一个功能,需要在编辑框有内容时显示删除按钮,在没有内容的时候也能点击搜索

常用的做法有两种:

1、通过组合布局方式:LinearLayout + EditText+ImageView

2、继承EditText,初始化的时候填充右侧drawable

本次采用第二种,少套用一层布局

操作如下:

1、在value/attrs.xml 文件下     添加自定义属性

  <declare-styleable name="SearchEditText">
        <attr name="rightWidth" format="dimension" />
        <attr name="rightHeight" format="dimension" />
    </declare-styleable>

2、继承EditText

@SuppressLint("AppCompatCustomView")
class SearchEditText @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = android.R.attr.editTextStyle
)  : EditText(context, attrs, defStyleAttr), TextWatcher {

    private var rightDrawableWidth: Int = 10
    private var rightDrawableHeight: Int = 10
    private var mClearDrawable: Drawable? = null
    private var mSearchDrawable: Drawable? = null

    init {
        //扩展属性
        val typedArray =
            context.obtainStyledAttributes(
                attrs,
                R.styleable.SearchEditText,
                android.R.attr.editTextStyle,
                0
            )
        rightDrawableHeight = typedArray.getDimensionPixelSize(
            R.styleable.SearchEditText_rightHeight,
            TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                20f,
                resources.displayMetrics
            ).toInt()
        )
        rightDrawableWidth = typedArray.getDimensionPixelSize(
            R.styleable.SearchEditText_rightWidth,
            TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                20f,
                resources.displayMetrics
            ).toInt()
        )

        typedArray.recycle()

        //获取图片
        if (mClearDrawable == null) {
            mClearDrawable = resources.getDrawable(
                R.drawable.clear_help, null
            )
        }

        if (mSearchDrawable == null) {
            mSearchDrawable = resources.getDrawable(
                R.drawable.icon_serach, null
            )
        }
        setDrawableSize(mClearDrawable)
        setDrawableSize(mSearchDrawable)
        showClean(false)

        // 设置输入框里面内容发生改变的监听
        addTextChangedListener(this)

//        setSelectAllOnFocus(true)
    }

    //设置图片的高度和宽度
    private fun setDrawableSize(
        drawable: Drawable?
    ) {
        if (drawable == null) {
            return
        }
        //左上右下
        var width = 0
        var height = 0
        width = rightDrawableWidth
        height = rightDrawableHeight

        //如果没有设置图片的高度和宽度具使用默认的图片高度和宽度
        if (width < 0) {
            width = UIUtils.dip2Px(20f)
        }
        if (height < 0) {
            height = UIUtils.dip2Px(20f)
        }
        drawable.setBounds(0, 0, width, height)
    }

    fun setRightView(cleanResId: Int = 0, searchResId: Int = 0) {
        if (cleanResId != 0) {
            mClearDrawable = resources.getDrawable(
                cleanResId, null
            )
            setDrawableSize(mClearDrawable)
        }

        if (searchResId != 0) {
            mSearchDrawable = resources.getDrawable(
                searchResId, null
            )
            setDrawableSize(mSearchDrawable)
        }

        showClean(text.toString().isNotEmpty())
    }

    private fun showClean(show: Boolean) {
        val drawable = if (show) mClearDrawable else mSearchDrawable
        //放置图片
        setCompoundDrawables(
            null,
            null,
            drawable,
            null
        )
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            if (compoundDrawables[2] != null) {
                val x = event.x.toInt()
//                val y = event.y.toInt()
//                val rect = compoundDrawables[2].bounds
//                val height = rect.height()
//                val distance = (getHeight() - height) / 2
                //判断点击的区域 右侧区域的最小范围 = 误差在5px  这个操作是为了避免区域太小而手指太差导致不能精准点击区域
                val isInnerWidth = x >= width - totalPaddingRight - 5 && x <= width - paddingRight - 5
//                val isInnerHeight = y > distance && y < distance + height
                if (isInnerWidth /*&& isInnerHeight*/) {
                    val str = text.toString().trim()
                    if (str.isNotEmpty()) {
                        this.setText("")
                        mOnSearchListener?.onClean()
                    } else {
                        //搜索
                        mOnSearchListener?.onSearch(str)
                    }
                    return true
                }
            }
        }
        return super.onTouchEvent(event)
    }

    override fun onTextChanged(
        text: CharSequence,
        start: Int,
        lengthBefore: Int,
        lengthAfter: Int
    ) {
        val str = text.toString().trim()
        showClean(str.isNotEmpty())
    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

    }

    override fun afterTextChanged(s: Editable?) {
    }

    var mOnSearchListener: OnSearchListener? = null
    fun setOnSearchListener(onSearchListener: OnSearchListener) {
        mOnSearchListener = onSearchListener
    }

    interface OnSearchListener {
        fun onClean()
        fun onSearch(text: String)
    }
}

3、具体使用

 <com.****.SearchEditText
                    android:id="@+id/etSearchKeyword"
                    style="@style/item_edit"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@null"
                    android:hint="品名/货号/条码"
                    android:imeOptions="actionSearch"
                    android:minWidth="120dp"
                    android:paddingHorizontal="5dp"
                    custom:rightHeight="20dp"
                    custom:rightWidth="20dp" />

共用编辑属性操作,可根据需要是否添加 

    <style name="item_edit">
        <item name="android:layout_width">0dp</item>
        <item name="android:layout_height">match_parent</item>
        <item name="android:textColor">@color/color_text_333333</item>
        <item name="android:textSize">18sp</item>
        <item name="android:gravity">center_vertical</item>
        <item name="android:maxLines">1</item>
        <item name="android:layout_weight">3</item>
        <item name="android:singleLine">true</item>
        <item name="android:textColorHighlight">@color/colorGreenV2</item>
        <item name="android:background">@drawable/gray_stroke_radius5_bg</item>
        <item name="android:selectAllOnFocus">true</item>
<!--        光标颜色-->
        <item name="android:textCursorDrawable">@drawable/shape_edit_cursor_bg</item>
    </sty

 光标颜色:shape_edit_cursor_bg.xml

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

    <size android:width="2dp"/>
    <solid android:color="@color/colorGreenV2"/>
</shape>

 4、代码中接收事件处理逻辑

 etSearchKeyword.setOnSearchListener(object :SearchEditText.OnSearchListener{
            override fun onClean() {
                searchKeyword("")
            }

            override fun onSearch(text: String) {
                searchKeyword(text)
            }
        })

低功耗蓝牙项目,需要一块懂省电的板

思澈 SF32LB52 芯片,BLE 协议栈深度优化,上手即开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值