Android 自定义控件 ClearEditText Kotlin

1. 效果图

带清除按钮的输入框

2. 代码

class ClearEditText @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
) : AppCompatEditText(context, attributeSet) {

    init {
        // 添加文本改变监听器
        addTextChangedListener {
            val end = if (text.toString().isEmpty()) null else ResourcesCompat.getDrawable(
                resources, R.drawable.baseui_ic_edit_delete, null
            )
            end?.setBounds(0, 0, 42, 42)
            setCompoundDrawables(null, null, end, null) 
            setPadding(20, 0, 20, 0)
        }
        // 设置点击关闭按钮
        setOnTouchListener { v, event ->
            performClick()
            var completed = false
            if (v is EditText && event.x >= width - v.totalPaddingRight && event.action == MotionEvent.ACTION_UP) {
                setText("")
                completed = true
            }
            completed
        }
    }
}

3. 增加SetText后光标移动到最后的逻辑

class ClearEditText @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
) : AppCompatEditText(context, attributeSet) {

    init {
        // 添加文本改变监听器
        addTextChangedListener {
            // 当内容为空后,就不要再显示图标了
            if (text.toString().isEmpty()) {
                hideClearIcon()
            } else {
                // 就算有内容,也要获取到焦点后才能显示
                if (isFocused) {
                    showClearIcon()
                }
            }
        }
        // 设置点击关闭按钮
        setOnTouchListener { v, event ->
            performClick()
            var completed = false
            if (v is EditText && event.x >= width - v.totalPaddingRight
                && event.action == MotionEvent.ACTION_UP
            ) {
                setText("")
                completed = true
            }
            completed
        }
        // 设置监听焦点状态改变事件
        setOnFocusChangeListener { view, b ->
            if (text != null && !text.toString().isEmpty()) {
                if (b) {
                    showClearIcon()
                    val len = text.toString().length
                    if (len > 0) {
                        setSelection(len)
                    }
                } else {
                    hideClearIcon()
                }
            }
        }
    }

    /**
     * 显示清除图标
     */
    private fun showClearIcon() {
        val end = ResourcesCompat.getDrawable(resources, R.drawable.baseui_ic_edit_delete, null)
        end?.setBounds(0, 0, 42, 42)
        setCompoundDrawables(null, null, end, null)
        // 使用原来的内边距
        setPadding(paddingLeft, 0, 20, 0)
    }

    /**
     * 隐藏清除图标
     */
    private fun hideClearIcon() {
        setCompoundDrawables(null, null, null, null)
    }
}

4. 图标大小适配

/**
 * 显示清除图标
 */
private fun showClearIcon(context: Context) {
    val end = ResourcesCompat.getDrawable(resources, R.drawable.baseui_ic_edit_delete, null)
    end?.setBounds(0, 0, DensityUtil.px2dip(context, 20.0f), DensityUtil.px2dip(context, 20.0f))
    setCompoundDrawables(null, null, end, null)
    // 使用原来的内边距
    setPadding(paddingLeft, 0, DensityUtil.px2dip(context, 10.0f), 0);
}
// Java
/**
 * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
 */
public static int px2dip(Context context, float pxValue) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (pxValue / scale + 0.5f);
}

5. 参考文章

  1. https://zhuanlan.zhihu.com/p/541155880
  2. https://zinyan.com/?p=205

你可能感兴趣的:(Android 自定义控件 ClearEditText Kotlin)