Android 自定义EditText

文章目录

  • Android 自定义EditText
    • 概述
    • 源码
      • 可清空内容的EditText
      • 可显示密码的EditText
    • 使用
    • 源码下载

Android 自定义EditText

概述

定义一款可清空内容的 ClearEditText 和可显示密码的 PasswordEditText,支持修改提示图标和大小、背景图片等。

在这里插入图片描述

源码

基类:

open class BaseEditText @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = android.R.attr.editTextStyle
) : androidx.appcompat.widget.AppCompatEditText(context, attrs, defStyleAttr) {companion object {@JvmStaticprotected val DEFAULT_DRAWABLE = ColorDrawable(0xFFFFFFFF.toInt())}init {gravity = Gravity.CENTER_VERTICALbackground = DEFAULT_DRAWABLE}override fun setLayoutParams(params: ViewGroup.LayoutParams) {if (params.width == ViewGroup.LayoutParams.WRAP_CONTENT) {params.width = ViewGroup.LayoutParams.MATCH_PARENT}super.setLayoutParams(params)}
}

可清空内容的EditText

定义属性:

<declare-styleable name="ClearEditText"><attr name="cet_deleteIcon" format="reference" /><attr name="cet_deleteIconSize" format="dimension" /><attr name="cet_tipDefaultIcon" format="reference" /><attr name="cet_tipSelectedIcon" format="reference" /><attr name="cet_tipIconSize" format="dimension" /><attr name="cet_defaultBg" format="color|reference" /><attr name="cet_selectedBg" format="color|reference" />
</declare-styleable>

定义ClearEditText:

class ClearEditText @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null
) : BaseEditText(context, attrs) {private val deleteIconDrawable: Drawable?private val tipIconDefaultDrawable: Drawable?private val tipIconSelectedDrawable: Drawable?private val bgDefaultDrawable: Drawable?private val bgSelectedDrawable: Drawable?init {val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.ClearEditText)val deleteIconSize =a.getDimensionPixelSize(R.styleable.ClearEditText_cet_deleteIconSize, 0)deleteIconDrawable = a.getDrawable(R.styleable.ClearEditText_cet_deleteIcon)deleteIconDrawable?.let { it ->if (deleteIconSize > 0) {it.setBounds(0, 0, deleteIconSize, deleteIconSize)} else {it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)}}val tipIconSize = a.getDimensionPixelSize(R.styleable.ClearEditText_cet_tipIconSize, 0)tipIconDefaultDrawable = a.getDrawable(R.styleable.ClearEditText_cet_tipDefaultIcon)tipIconDefaultDrawable?.let { it ->if (tipIconSize > 0) {it.setBounds(0, 0, tipIconSize, tipIconSize)} else {it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)}}tipIconSelectedDrawable = a.getDrawable(R.styleable.ClearEditText_cet_tipSelectedIcon)tipIconSelectedDrawable?.let { it ->if (tipIconSize > 0) {it.setBounds(0, 0, tipIconSize, tipIconSize)} else {it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)}}bgDefaultDrawable = a.getDrawable(R.styleable.ClearEditText_cet_defaultBg)bgSelectedDrawable = a.getDrawable(R.styleable.ClearEditText_cet_selectedBg)a.recycle()setup()}private fun setup() {setIconVisible(false, false)bgDefaultDrawable?.let {background = it}}override fun onTextChanged(text: CharSequence,start: Int,lengthBefore: Int,lengthAfter: Int) {super.onTextChanged(text, start, lengthBefore, lengthAfter)setIconVisible(hasFocus() && text.length > 0, hasFocus())}override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {super.onFocusChanged(focused, direction, previouslyFocusedRect)setIconVisible(focused && length() > 0, focused)}private fun setIconVisible(deleteIconVisible: Boolean, focused: Boolean) {setCompoundDrawablesRelative(if (focused) tipIconSelectedDrawable else tipIconDefaultDrawable,null,if (deleteIconVisible) deleteIconDrawable else null,null)if (bgDefaultDrawable != null && bgSelectedDrawable != null) {background = if (focused) bgSelectedDrawable else bgDefaultDrawable}}override fun onTouchEvent(event: MotionEvent): Boolean {if (event.action == MotionEvent.ACTION_UP) {val drawable = deleteIconDrawableif (drawable != null) {if (event.x <= width - paddingRight && event.x >= width - paddingRight - drawable.bounds.width()) {text = null}}}return super.onTouchEvent(event)}
}

可显示密码的EditText

定义属性:

<declare-styleable name="PasswordEditText"><attr name="pet_eyeIconSize" format="dimension" /><attr name="pet_tipDefaultIcon" format="reference" /><attr name="pet_tipSelectedIcon" format="reference" /><attr name="pet_tipIconSize" format="dimension" /><attr name="pet_defaultBg" format="color|reference" /><attr name="pet_selectedBg" format="color|reference" />
</declare-styleable>

定义PasswordEditText:

class PasswordEditText @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null
) : BaseEditText(context, attrs) {private val eyeOpenDrawable: Drawable?private val eyeCloseDrawable: Drawable?private var currentEyeDrawable: Drawable? = nullprivate var tipIconDefaultDrawable: Drawable?private var tipIconSelectedDrawable: Drawable?private var bgDefaultDrawable: Drawable?private var bgSelectedDrawable: Drawable?init {val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText)val eyeIconSize = a.getDimensionPixelSize(R.styleable.PasswordEditText_pet_eyeIconSize, 0)eyeOpenDrawable = ContextCompat.getDrawable(context, R.drawable.eye_open)eyeOpenDrawable?.let {if (eyeIconSize > 0) {it.setBounds(0, 0, eyeIconSize, eyeIconSize)} else {it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)}}eyeCloseDrawable = ContextCompat.getDrawable(context, R.drawable.eye_close)eyeCloseDrawable?.let {if (eyeIconSize > 0) {it.setBounds(0, 0, eyeIconSize, eyeIconSize)} else {it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)}}val tipIconSize = a.getDimensionPixelSize(R.styleable.PasswordEditText_pet_tipIconSize, 0)tipIconDefaultDrawable = a.getDrawable(R.styleable.PasswordEditText_pet_tipDefaultIcon)tipIconDefaultDrawable?.let { it ->if (tipIconSize > 0) {it.setBounds(0, 0, tipIconSize, tipIconSize)} else {it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)}}tipIconSelectedDrawable = a.getDrawable(R.styleable.PasswordEditText_pet_tipSelectedIcon)tipIconSelectedDrawable?.let { it ->if (tipIconSize > 0) {it.setBounds(0, 0, tipIconSize, tipIconSize)} else {it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)}}bgDefaultDrawable = a.getDrawable(R.styleable.PasswordEditText_pet_defaultBg)bgSelectedDrawable = a.getDrawable(R.styleable.PasswordEditText_pet_selectedBg)a.recycle()setup()}private fun setup() {setIconVisible(false, false)currentEyeDrawable = eyeCloseDrawablebgDefaultDrawable?.let {background = it}inputType = InputType.TYPE_TEXT_VARIATION_PASSWORDtransformationMethod = PasswordTransformationMethod.getInstance()}override fun onTextChanged(text: CharSequence,start: Int,lengthBefore: Int,lengthAfter: Int) {super.onTextChanged(text, start, lengthBefore, lengthAfter)setIconVisible(hasFocus() && text.length > 0, hasFocus())}override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {super.onFocusChanged(focused, direction, previouslyFocusedRect)setIconVisible(focused && length() > 0, focused)}private fun setIconVisible(pwdIconVisible: Boolean, focused: Boolean) {setCompoundDrawablesRelative(if (focused) tipIconSelectedDrawable else tipIconDefaultDrawable,null,if (pwdIconVisible) currentEyeDrawable else null,null)if (bgDefaultDrawable != null && bgSelectedDrawable != null) {background = if (focused) bgSelectedDrawable else bgDefaultDrawable}}override fun onTouchEvent(event: MotionEvent): Boolean {if (event.action == MotionEvent.ACTION_UP) {val drawable = currentEyeDrawableif (drawable != null) {if (event.x <= width - paddingRight && event.x >= width - paddingRight - drawable.bounds.width()) {if (drawable == eyeOpenDrawable) {// 密码不可见currentEyeDrawable = eyeCloseDrawabletransformationMethod = PasswordTransformationMethod.getInstance()refreshDrawables()} else if (drawable == eyeCloseDrawable) {// 密码可见currentEyeDrawable = eyeOpenDrawabletransformationMethod = HideReturnsTransformationMethod.getInstance()refreshDrawables()}}}}return super.onTouchEvent(event)}private fun refreshDrawables() {val drawables = compoundDrawablesRelativesetCompoundDrawablesRelative(drawables[0], drawables[1], currentEyeDrawable, drawables[3])}
}

使用

<com.example.widgets.custom_edittext.ClearEditTextandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginHorizontal="30dp"android:layout_marginTop="60dp"android:hint="请输入用户名"android:padding="10dp"android:singleLine="true"android:textSize="20sp"app:cet_defaultBg="@drawable/shape_border_gray"app:cet_deleteIcon="@drawable/ic_delete_x"app:cet_deleteIconSize="30dp"app:cet_selectedBg="@drawable/shape_border_blue"app:cet_tipDefaultIcon="@drawable/ic_user_gray"app:cet_tipIconSize="30dp"app:cet_tipSelectedIcon="@drawable/ic_user_blue" /><com.example.widgets.custom_edittext.ClearEditTextandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginHorizontal="30dp"android:layout_marginTop="30dp"android:hint="请输入手机号"android:inputType="phone"android:padding="10dp"android:textSize="20sp"app:cet_defaultBg="@drawable/shape_border_gray"app:cet_deleteIcon="@drawable/ic_delete_x"app:cet_deleteIconSize="30dp"app:cet_selectedBg="@drawable/shape_border_blue"app:cet_tipDefaultIcon="@drawable/ic_user_gray"app:cet_tipIconSize="30dp"app:cet_tipSelectedIcon="@drawable/ic_user_blue" /><com.example.widgets.custom_edittext.PasswordEditTextandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginHorizontal="30dp"android:layout_marginTop="30dp"android:hint="请输入密码"android:padding="10dp"android:textSize="20sp"app:pet_defaultBg="@drawable/shape_border_gray"app:pet_selectedBg="@drawable/shape_border_blue"app:pet_tipDefaultIcon="@drawable/ic_lock_gray"app:pet_tipIconSize="30dp"app:pet_tipSelectedIcon="@drawable/ic_lock_blue" />

源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/288722.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现商铺和缓存与数据库双写一致

2.4 实现商铺和缓存与数据库双写一致 核心思路如下&#xff1a; 修改ShopController中的业务逻辑&#xff0c;满足下面的需求&#xff1a; 根据id查询店铺时&#xff0c;如果缓存未命中&#xff0c;则查询数据库&#xff0c;将数据库结果写入缓存&#xff0c;并设置超时时间…

ssm小区车库停车系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 ssm小区车库停车系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模…

如何在家中使用手机平板电脑 公司iStoreOS软路由实现远程桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…

HCIA-Datacom实验_03_实验一:华为VRP系统基本操作

1.运行eNSP&#xff0c;设置-界面设置-自定义界面-设备标签&#xff0c;“总显示接口标签” 打钩。 2.按照实验拓扑添加设备 注&#xff1a;如果是真实环境&#xff0c;需要接两条线&#xff1a; &#xff08;1&#xff09;串口线&#xff1a;电脑USB口到网络设备Console口&am…

Windows下载使用nc(netcat)命令

‘nc’ 不是内部或外部命令&#xff0c;也不是可运行的程序&#xff1f; 点击链接地址&#xff0c;下载压缩包。 完成后解压 使用方式&#xff08;三种&#xff09;&#xff1a; 1、直接双击exe使用 2、把这个exe放到cmd启动的默认路径下 放到默认路径下&#xff0c;使用nc&a…

MySQL高级语句(二)

一、前期准备工作 1.1 登陆mysql&#xff0c;查看数据表 1.2 显示所有表 1.3 创建guigui表并插入数据 1.4 创建ky35表格并插入数据 二、子连接 子查询也被称作内查询或者嵌套查询&#xff0c;是指在一个查询语句里面还嵌套着另一个查询语句。子查询语句是先于主查询语句被执行的…

自动生成测试位置吸附脚本设计思路

前言 计算一个异质结需要测试对比不同吸附位置之间的能量差异&#xff0c;可以直接手动建模&#xff0c;但是人太懒了&#xff0c;能交给机器的自己就别动手 问题描述 如图上所示是我计算吸附用的衬底&#xff0c;当原子在上面吸附时我考虑了25个&#xff08;可以随便取&…

Tensorflow2.0笔记 - 使用compile,fit,evaluate,predict简化流程

本笔记主要用compile, fit, evalutate和predict来简化整体代码&#xff0c;使用这些高层API可以减少很多重复代码。具体内容请自行百度&#xff0c;本笔记基于FashionMnist的训练笔记&#xff0c;原始笔记如下&#xff1a; Tensorflow2.0笔记 - FashionMnist数据集训练-CSDN博…

OSPF-区域间路由计算

一、概述 前面学习了我们学习了Router-LSA和Network-LSA&#xff0c;它们都只能在区域内进行泛洪&#xff0c;而且我们之前一直主要是单区域学习。OSPF的核心是骨干区域Area 0&#xff0c;其它都为非骨干区域。但是在大型网络中&#xff0c;单区域OSPF会存在一定的问题&#xf…

[BT]BUUCTF刷题第9天(3.27)

第9天&#xff08;共2题&#xff09; [护网杯 2018]easy_tornado 打开网站就是三个txt文件 /flag.txt flag in /fllllllllllllag/welcome.txt render/hints.txt md5(cookie_secretmd5(filename))当点进flag.txt时&#xff0c;url变为 http://b9e52e06-e591-46ad-953e-7e8c5f…

gopher伪协议

基础知识 基本格式 基本格式&#xff1a;URL:gopher://<host>:<port>/<gopher-path>web也需要加端口号80gophert协议默认端口为70gopheri请求不转发第一个字符 get请求 问号&#xff08;&#xff1f;)需要转码为URL编码&#xff0c;也就是%3f回车换行要变…

【Linux】信号的处理{信号处理的时机/了解寄存器/内核态与用户态/信号操作函数}

文章目录 0.对于信号捕捉的理解1.信号处理的时机1.1 何时处理信号&#xff1f;1.2 内核态和用户态1.3 内核态和用户态的切换 2.了解寄存器3.信号捕捉的原理4.信号操作函数4.1sighandler_t signal(int signum, sighandler_t handler);4.2int sigaction(int signum, const struct…

IP如何异地共享文件?

【天联】 组网由于操作简单、跨平台应用、无网络要求、独创的安全加速方案等原因&#xff0c;被几十万用户广泛应用&#xff0c;解决了各行业客户的远程连接需求。采用穿透技术&#xff0c;简单易用&#xff0c;不需要在硬件设备中端口映射即可实现远程访问。 异地共享文件 在…

基于SpringBoot和Vue的校园管理系统的设计与实现

今天要和大家聊的是一款基于SpringBoot和Vue的校园管理系统的设计与实现 &#xff01;&#xff01;&#xff01; 有需要的小伙伴可以通过文章末尾名片咨询我哦&#xff01;&#xff01;&#xff01; &#x1f495;&#x1f495;作者&#xff1a;李同学 &#x1f495;&#x1f…

vscode上编辑vba

安装xvba插件更换vscode的工作目录启动扩展服务器在config.json中添加目标工作簿的名称加载excel文件&#xff08;必须带宏的xlsm&#xff09;这个扩展就会自动提取出Excel文件中的代码Export VBA&#xff08;编辑完成的VBA代码保存到 Excel文件 &#xff09;再打开excel文件可…

【LVGL-键盘部件,实体按键控制】

LVGL-二维码库 ■ LVGL-键盘部件■ 示例一&#xff1a;键盘弹窗提示■ 示例二&#xff1a;设置键盘模式■ 综合示例&#xff1a; ■ LVGL-实体按键控制■ 简介 ■ LVGL-键盘部件 ■ 示例一&#xff1a;键盘弹窗提示 lv_keyboard_set_popovers(kb,true);■ 示例二&#xff1a;设…

基于Givens旋转完成QR分解进而求解实矩阵的逆矩阵

基于Givens旋转完成QR分解进而求解实矩阵的逆矩阵 目录 前言 一、Givens旋转简介 二、Givens旋转解释 三、Givens旋转进行QR分解 四、Givens旋转进行QR分解数值计算例子 五、求逆矩阵 六、MATLAB仿真 七、参考资料 总结 前言 在进行QR分解时&#xff0c;HouseHolder变换…

开源AI引擎|企业合同管理:自然语言处理与OCR技术深度融合

一、企业应用&#xff1a;合同智能管理 结合NLP和OCR技术&#xff0c;企业可以构建智能化的合同管理系统&#xff0c;实现合同的自动化审查、风险评估和知识抽取。这样的系统不仅能够提高合同处理的效率&#xff0c;还能够降低人为错误&#xff0c;加强风险控制。 例如&#x…

【React】vite + react 项目,进行配置 eslint

安装与配置 eslint 1 安装 eslint babel/eslint-parser2 初始化配置 eslint3 安装 vite-plugin-eslint4 配置 vite.config.js 文件5 修改 eslint 默认配置 1 安装 eslint babel/eslint-parser npm i -D eslint babel/eslint-parser2 初始化配置 eslint npx eslint --init相关…

iOS - Runtime-消息机制-objc_msgSend()

iOS - Runtime-消息机制-objc_msgSend() 前言 本章主要介绍消息机制-objc_msgSend的执行流程&#xff0c;分为消息发送、动态方法解析、消息转发三个阶段&#xff0c;每个阶段可以做什么。还介绍了super的本质是什么&#xff0c;如何调用的 1. objc_msgSend执行流程 OC中的…