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.mzph.cn/news/782005.shtml

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

相关文章

WebViz可视化

WebViz可视化 Webviz是一个基于Web的可视化工具&#xff0c;意味着您可以通过浏览器/APP访问它&#xff0c;而不需要安装额外的软件。这对于远程访问和团队协作非常方便。 Foxglove是一个开源的工具包&#xff0c;包括线上和线下版。旨在简化机器人系统的开发和调试。它提供了…

Gitea 的详细介绍

什么是 Gitea&#xff1f; Gitea 是一个开源、轻量级的自托管 Git 服务&#xff0c;它允许用户搭建类似于 GitHub 或 GitLab 的代码托管平台。由于采用 Go 语言开发&#xff0c;Gitea 具有高效的性能和跨平台特性&#xff0c;适合个人开发者或小团队使用。 Gitea 的特点 轻量…

蓝桥杯第十三届电子类单片机组程序设计

目录 前言 单片机资源数据包_2023 一、第十三届比赛省赛 1.比赛题目 2.赛题解读 二、部分功能实现 1.继电器的开启与关闭 2.长按切换显示状态功能的实现 3.对于温度传感器小数部分的处理 4.其他处理 1&#xff09;关于数码管显示小数的处理 2&#xff09;关于5s后继…

结构体类型,结构体变量的创建和初始化 以及结构中存在的内存对齐

一般结构体类型的声明 struct 结构体类型名 { member-list; //成员表列 }variable-list; //变量表列 例如描述⼀个学⽣&#xff1a; struct Stu { char name[20]; //名字 int age; //年龄 char sex[5]; //性别 }&#xff1b; //结构体变量的初始化 int main() { S…

牛客NC30 缺失的第一个正整数【simple map Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/50ec6a5b0e4e45348544348278cdcee5 核心 Map参考答案Java import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可…

Modelsim手动仿真实例

目录 1. 软件链接 2. 为什么要使用Modelsim 3. Modelsim仿真工程由几部分组成&#xff1f; 4. 上手实例 4.1. 新建文件夹 4.2. 指定目录 4.3. 新建工程 4.4. 新建设计文件&#xff08;Design Files&#xff09; 4.5. 新建测试平台文件&#xff08;Testbench Files&…

企业数据被新型.rmallox勒索病毒加密,应该如何还原?

.rmallox勒索病毒为什么难以解密&#xff1f; .rmallox勒索病毒难以解密的主要原因在于其采用了高强度的加密算法&#xff0c;并且这些算法被有效地实施在了病毒程序中。具体来说&#xff0c;.rmallox勒索病毒使用了RSA和AES这两种非常成熟的加密算法。RSA是一种非对称加密算法…

3D汽车模型线上三维互动展示提供视觉盛宴

VR全景虚拟看车软件正在引领汽车展览行业迈向一个全新的时代&#xff0c;它不仅颠覆了传统展览的局限&#xff0c;还为参展者提供了前所未有的高效、便捷和互动体验。借助于尖端的vr虚拟现实技术、逼真的web3d开发、先进的云计算能力以及强大的大数据处理&#xff0c;这一在线展…

瑞吉外卖实战学习--6、通过try和catch进行异常处理

try和catch进行异常处理 效果图前言1、公共拦截器进行异常处理1.1、创建公共报错处理的方法1.2、@ControllerAdvice中设置要拦截的类1.3、@ExceptionHandler中写处理的异常类2、完善错误拦截器2.1、效果效果图 前言 当用户名重复数据库会报错,此时就需要捕获异常操作 1、公共…

Spring: 在SpringBoot项目中解决前端跨域问题

这里写目录标题 一、什么是跨域问题二、浏览器的同源策略三、SpringBoot项目中解决跨域问题的5种方式&#xff1a;使用CORS1、自定 web filter 实现跨域(全局跨域)2、重写 WebMvcConfigurer(全局跨域)3、 CorsFilter(全局跨域)4、使用CrossOrigin注解 (局部跨域) 一、什么是跨域…

社交网络的未来:Facebook如何塑造数字社交的下一章

引言 社交网络已成为我们生活中不可或缺的一部分&#xff0c;而Facebook作为其领军者&#xff0c;一直在塑造着数字社交的未来。本文将深入探讨Facebook在未来如何塑造数字社交的下一章&#xff0c;并对社交网络的发展趋势进行展望和分析。 1. 引领虚拟社交的潮流 Facebook将…

小白从0学习ctf(web安全)

文章目录 前言一、baby lfi&#xff08;bugku-CTF&#xff09;1、简介2、解题思路1、解题前置知识点2、漏洞利用 二、baby lfi 2&#xff08;bugku-CTF&#xff09;1.解题思路1、漏洞利用 三、lfi&#xff08;bugku CTF&#xff09;1、解题思路1、漏洞利用 总结 前言 此文章是…

Java复习第十二天学习笔记(JDBC),附有道云笔记链接

【有道云笔记】十二 3.28 JDBC https://note.youdao.com/s/HsgmqRMw 一、JDBC简介 面向接口编程 在JDBC里面Java这个公司只是提供了一套接口Connection、Statement、ResultSet&#xff0c;每个数据库厂商实现了这套接口&#xff0c;例如MySql公司实现了&#xff1a;MySql驱动…

手把手在K210上部署自己在线训练的YOLO模型

小白花了两天时间学习了一下K210&#xff0c;将在线训练的模型部署在K210&#xff08;代码后面给出&#xff09;上&#xff0c;能够识别卡皮巴拉水杯&#xff08;没错&#xff0c;卡皮巴拉&#xff0c;情绪稳定&#xff0c;真的可爱&#xff01;&#xff09;。数据集是用K210拍…

linux下minio部署和nginx配置

1 下载minio wget https://dl.min.io/server/minio/release/linux-amd64/minio chmod x minio #启动minio&#xff0c;文件数据存放在/data目录 ./minio server /data2 部署minio 下载minio后赋予可执行权限就可以运行了&#xff0c;这里我整理了遇到的坑和解决问题的最终配置…

算法打卡day21(开始回溯)

今日任务&#xff1a; 1&#xff09;77.组合 77.组合 题目链接&#xff1a;77. 组合 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;带你学透回溯算法-组合问题&#xff08;对应力扣题目&#xff1a;77…

HeidiSQL导出SQL文件

目前开发阶段的数据库可视化工具逐渐转为了HeidiSQL&#xff0c;本文讲一讲导出到sql文件的小细节&#xff0c;给自己做个记录补充。 安装或数据库可视化工具比较可参考&#xff1a; windows下全免费手动搭建php8mysql8开发环境及可视化工具安装 导出 原来用Navicat的时候&am…

接口测试vs功能测试

接口测试和功能测试的区别&#xff1a; 本文主要分为两个部分&#xff1a; 第一部分&#xff1a;主要从问题出发&#xff0c;引入接口测试的相关内容并与前端测试进行简单对比&#xff0c;总结两者之前的区别与联系。但该部分只交代了怎么做和如何做&#xff1f;并没有解释为什…

[2023] 14届

1.日期统计 题意 1.日期统计 - 蓝桥云课 (lanqiao.cn) 思路 用dfs扫 对每一个位进行限制 花了一个小时 注意把答案枚举出来 对应一下看到底对不对 code #include<iostream> #include<cstdio> #include<stack> #include<vector> #include<al…

鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

随后迎来了不少互联网公司与华为鸿蒙原生应用达成了合作&#xff0c;像我们常见的阿里、京东、小红书、得物……等公司&#xff0c;还有一些银行也都与华为鸿蒙达成了合作。使得一时之间市场紧缺鸿蒙开发人才&#xff0c;不少公司不惜重金争抢人才。 据智联招聘的最新数据显示…