Android进阶之路 - EditText输入字体自适应

遇到这么一个需求:“控件宽度有限,随着输入内容,动态修改字体大小”,如果是你,只如何来实现?又有几种方式?

嗯,就是这么一个简单的需求,让我记录了俩篇blog
在这里插入图片描述

  • Android进阶之路 - 去除EditText内边距
  • Android进阶之路 - EditText输入字体自适应

起初我曾尝试通过监听TextChanged + 字体自适应 的方式,来实现 输入字体自适应 ,但是效果并不理想 ,所以最终换了别的方式

    • 简单、直接、有点low
    • AutoAdjustSizeEditText
    • AutoAdaptSizeEditText

该篇通过我所使用的几种方式,看看能否帮助大家,具体采用了以下几种方式,先简单介绍一下

  • 监听TextChanged,在一定规则内直接设置字体大小(字体过度不自然)
  • AutoAdjustSizeEditText 自定义控件(基本满足场景,不过单行可支持无线输入,可无限滑动)
  • AutoAdaptSizeEditText 控件借鉴于前者,稍加修改,用于满足某一场景(设置单行场景,超过固定宽度,则不可继续输入)

AutoAdjustSizeEditText、AutoAdaptSizeEditText 效果与布局引入

效果

请添加图片描述

布局引入

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><com.example.edittextdemo.AutoAdjustSizeEditTextandroid:layout_width="230dp"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:hint="AutoAdjustSizeEditText"android:textSize="20sp"app:maxTextSize="30sp"app:minTextSize="15sp" /><com.example.edittextdemo.AutoAdaptSizeEditTextandroid:layout_width="230dp"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="10dp"android:hint="AutoAdaptSizeEditText"android:singleLine="true"android:textSize="20sp"app:maxSize="30sp"app:minSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>

简单、直接、有点low

这种方式就想我说的使用起来很简单,唯一不足可能在于首先需要了解输入规则的要求,同时字体适应时会生硬一些(目前因为框架原因,我先使用了该方式)

因为框架原因,我直接提供伪代码用于各位借鉴吧

EditText - addTextChangedListener

在这里插入图片描述

通过规则,自行定义字体大小

在这里插入图片描述

splitties框架EditText.setTextIfDifferent扩展函数,内部会自行设置焦点位置

在这里插入图片描述


AutoAdjustSizeEditText

我看了很多篇关于 EditText 输入字体自适应 Blog,大多好像都脱胎于早期这款 AutoAdjustSizeEditText 自定义控件,我直接将源码跑完后发现基本可以适用于大部分场景,其中有优点有不足(仅个人认为),但依旧不可否认可以从前辈的代码中学习和成长(为表尊重,源码不做任何修改)

适用大部分场景,如果对单行显示长度有限定或许不太满足

自定义属性(之前一直没记录过自定义属性的相关blog,等有时间我必须补充一篇)

    <!-- 文本自动调整大小显示自定义属性 --><declare-styleable name="AutoAdjustTextSize"><attr name="minTextSize" format="dimension" /><attr name="maxTextSize" format="dimension" /></declare-styleable>

AutoAdjustSizeEditText

package com.example.edittextdemo;import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.EditText;
import android.widget.TextView;/*** 自动调整字体文本输入框* * @author 蒋庆意* @date 2015-11-4* @time 上午11:02:32*/
@SuppressLint("AppCompatCustomView")
public class AutoAdjustSizeEditText extends EditText {/*** 默认文字字体大小最小值(单位:像素)*/private static final float DEFAULT_TEXT_SIZE_MIN = 20;/*** 默认文字字体大小最大值(单位:像素)(貌似用不上)*/@SuppressWarnings("unused")private static final float DEFAULT_TEXT_SIZE_MAX = 60;/*** 画笔(用来测量已输入文字的长度)*/private Paint paint;/*** 文字字体大小最小值*/private float minTextSize = 0;/*** 文字字体大小最大值*/private float maxTextSize = 0;/*** 判断输入文本字体是否变小过*/private boolean hasScaleSmall = false;public AutoAdjustSizeEditTextBefore(Context context) {super(context);paint = new Paint();}public AutoAdjustSizeEditTextBefore(Context context, AttributeSet attrs) {super(context, attrs);paint = new Paint();//读取自定义属性, 获取设置的字体大小范围if (null != attrs) {TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.AutoAdjustTextSize);if (null != array) {minTextSize = array.getDimension(R.styleable.AutoAdjustTextSize_minTextSize, DEFAULT_TEXT_SIZE_MIN);//如果未设置字体最大值,则使用当前字体大小作为最大值maxTextSize = array.getDimension(R.styleable.AutoAdjustTextSize_maxTextSize, this.getTextSize());//回收 TypedArrayarray.recycle();}}//未设置字体最小值,则使用默认最小值if (0 == minTextSize) {minTextSize = DEFAULT_TEXT_SIZE_MIN;}//未设置字体最大值,则使用当前字体大小作为最大值if (0 == maxTextSize) {//            maxTextSize = DEFAULT_TEXT_SIZE_MAX;maxTextSize = this.getTextSize();}//如果设置的值不正确(例如minTextSize>maxTextSize),则互换if (minTextSize > maxTextSize) {float minSize = maxTextSize;maxTextSize = minTextSize;minTextSize = minSize;}Log.d("AutoScaleSizeEditText","minTextSize=" + String.valueOf(minTextSize));Log.d("AutoScaleSizeEditText","maxTextSize=" + String.valueOf(maxTextSize));}@Overrideprotected void onTextChanged(CharSequence text, int start,int lengthBefore, int lengthAfter) {// 根据需要调整字体大小adjustTextSize(this);super.onTextChanged(text, start, lengthBefore, lengthAfter);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {// 根据需要调整字体大小if (w != oldw) {adjustTextSize(this);}super.onSizeChanged(w, h, oldw, oldh);}/*** 调整文本的显示*/private void adjustTextSize(TextView textView) {if (null == textView) {//参数错误,不与处理return;}//已输入文本String text = textView.getText().toString();//已输入文本长度int textWidth = textView.getWidth();if (null == text || text.isEmpty() || textWidth <= 0) {return;}//获取输入框总的可输入的文本长度float maxInputWidth = textView.getWidth() - textView.getPaddingLeft() - textView.getPaddingRight();//获取当前文本字体大小float currentTextSize = textView.getTextSize();Log.d("AutoScaleSizeEditText","currentTextSize=" + String.valueOf(currentTextSize));//设置画笔的字体大小paint.setTextSize(currentTextSize);/** 循环减小字体大小* 当  1、文本字体小于最大值*     2、可输入文本长度小于已输入文本长度* 时*/while ((currentTextSize > minTextSize) && (maxInputWidth < paint.measureText(text))) {hasScaleSmall = true;Log.d("AutoScaleSizeEditText","TextSizeChange=" + String.valueOf(currentTextSize));--currentTextSize;if (currentTextSize < minTextSize) {currentTextSize = minTextSize;break;}//设置画笔字体大小paint.setTextSize(currentTextSize);}/** 循环增大字体大小* 当  1、文本字体小于默认值*     2、可输入文本长度大于已输入文本长度* 时*/while (hasScaleSmall && (currentTextSize < maxTextSize)&& (maxInputWidth > paint.measureText(text))) {Log.d("AutoScaleSizeEditText","TextSizeChangeSmall=" + String.valueOf(currentTextSize));++currentTextSize;if (currentTextSize > maxTextSize) {currentTextSize = maxTextSize;break;}//设置画笔字体大小paint.setTextSize(currentTextSize);}//设置文本字体(单位为像素px)textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, currentTextSize);Log.d("AutoScaleSizeEditText","currentTextSize2=" + String.valueOf(currentTextSize));}
}

AutoAdaptSizeEditText

之所以修改原始 AutoAdjustSizeEditText 控件,主要是考虑到我当前场景为单行场景,且宽度固定,如果一直对输入内容不做限制,用户体验上可能不太好(感觉部分朋友应该也会遇到类似场景)

自定义属性(因为我Demo中这俩款自定义控件都用到了自定义属性;而自定义属性不可重复,所以这里命名稍有改变)

    <!-- 文本自动调整大小显示自定义属性 --><declare-styleable name="AutoAdaptTextSize"><attr name="minSize" format="dimension" /><attr name="maxSize" format="dimension" /></declare-styleable>

AutoAdaptSizeEditText (感觉改的还行,不过还能优化一些写法,有时间再说吧)

package com.example.edittextdemo;import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.EditText;
import android.widget.TextView;/*** 自动调整字体文本输入框,限制单行输入宽度** @author ly* @date 2023*/
@SuppressLint("AppCompatCustomView")
public class AutoAdaptSizeEditText extends EditText {/*** 默认文字字体大小最小值(单位:像素)*/private static final float DEFAULT_TEXT_SIZE_MIN = 20;/*** 默认文字字体大小最大值(单位:像素)(貌似用不上)*/@SuppressWarnings("unused")private static final float DEFAULT_TEXT_SIZE_MAX = 60;/*** 画笔(用来测量已输入文字的长度)*/private Paint paint;/*** 文字字体大小最小值*/private float minTextSize = 0;/*** 文字字体大小最大值*/private float maxTextSize = 0;/*** 判断输入文本字体是否变小过*/private boolean hasScaleSmall = false;/*** 可输出文本的最大长度*/private int length = 0;/*** 可编辑状态*/private boolean editState = false;public AutoAdaptTextSize(Context context) {super(context);paint = new Paint();}public AutoAdaptTextSize(Context context, AttributeSet attrs) {super(context, attrs);init(context, attrs);}public void init(Context context, AttributeSet attrs) {paint = new Paint();editState = true;//读取自定义属性, 获取设置的字体大小范围if (null != attrs) {TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.AutoAdaptTextSize);if (null != array) {minTextSize = array.getDimension(R.styleable.AutoAdaptTextSize_minSize, DEFAULT_TEXT_SIZE_MIN);//如果未设置字体最大值,则使用当前字体大小作为最大值maxTextSize = array.getDimension(R.styleable.AutoAdaptTextSize_maxSize, this.getTextSize());//回收 TypedArrayarray.recycle();}}//未设置字体最小值,则使用默认最小值if (0 == minTextSize) {minTextSize = DEFAULT_TEXT_SIZE_MIN;}//未设置字体最大值,则使用当前字体大小作为最大值if (0 == maxTextSize) {//            maxTextSize = DEFAULT_TEXT_SIZE_MAX;maxTextSize = this.getTextSize();}//如果设置的值不正确(例如minTextSize>maxTextSize),则互换if (minTextSize > maxTextSize) {float minSize = maxTextSize;maxTextSize = minTextSize;minTextSize = minSize;}}@Overrideprotected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {// 根据需要调整字体大小autoAdaptTextSize(this);super.onTextChanged(text, start, lengthBefore, lengthAfter);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {// 对比前后输入前后字体大小if (w != oldw) {autoAdaptTextSize(this);}super.onSizeChanged(w, h, oldw, oldh);}/*** 调整文本的显示*/private void autoAdaptTextSize(TextView textView) {if (null == textView) {//参数错误,不与处理return;}//已输入文本String text = textView.getText().toString();//已输入文本长度int textWidth = textView.getWidth();if (text.isEmpty() || textWidth <= 0) {return;}//获取输入框总的可输入的文本长度float maxInputWidth = textView.getWidth() - textView.getPaddingLeft() - textView.getPaddingRight();//获取当前文本字体大小float currentTextSize = textView.getTextSize();Log.d("AutoScaleSizeEditText", "currentTextSize=" + String.valueOf(currentTextSize));//设置画笔的字体大小paint.setTextSize(currentTextSize);/** 循环减小字体大小,条件如下* 1、文本字体小于最大值* 2、可输入文本长度小于已输入文本长度*/while ((currentTextSize > minTextSize) && (paint.measureText(text) > maxInputWidth)) {Log.e("tag", "paint.measureText(text)=" + paint.measureText(text) + "maxInputWidth:" + maxInputWidth);hasScaleSmall = true;--currentTextSize;if (currentTextSize < minTextSize) {currentTextSize = minTextSize;break;}//设置画笔字体大小paint.setTextSize(currentTextSize);}/** 循环增大字体大小,条件如下* 1、文本字体小于默认值* 2、可输入文本长度大于已输入文本长度*/while (hasScaleSmall && (currentTextSize < maxTextSize) && (maxInputWidth > paint.measureText(text))) {++currentTextSize;if (currentTextSize > maxTextSize) {currentTextSize = maxTextSize;break;}//设置画笔字体大小paint.setTextSize(currentTextSize);}/** 限制输入,条件如下* 1、当前字体大小已经为我们设置的最小字体(兼容最小值)* 2、所有字体的宽度对比控件的最大宽度*/Log.e("tag", "当前字体Size=" + currentTextSize + "最小字体Size:" + minTextSize);Log.e("tag", "字体宽度=" + paint.measureText(text) + "控件宽度:" + maxInputWidth);if (currentTextSize <= minTextSize && paint.measureText(text) > maxInputWidth) {Log.e("tag", "超过预设值,不支持继续输入");if (editState) {editState = false;length = text.length();}if (text.length() > length) {this.setText(text.substring(0, length));this.setSelection(length); //光标位于尾部}//最大可输出入字符数,限制输入的关键点this.setEms(length);} else {editState = true;}//设置文本字体(单位为像素px)textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, currentTextSize);}}

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

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

相关文章

用docker-compose搭建LNMP

docker-compose搭建LNMP 一、compose 的部署1.Docker Compose 环境安装 二、编写Docker Compose1.准备依赖文件,配置nginx2.配置mysql3.配置php4.编写docker-compose.yml5.执行6.查看 一、compose 的部署 &#xff08;1&#xff09;公司在实际的生产环境中&#xff0c;需要使用…

商品搜索网:连接您与各类商品的桥梁

导语&#xff1a;在如今信息爆炸的时代&#xff0c;购物已经不再是传统的实体店购买&#xff0c;而是通过互联网实现的线上购物方式。而要实现高效的线上购物&#xff0c;商品搜索引擎则成为我们的得力助手。作为国内垂直的商品搜索之一&#xff0c;为中国用户提供全面的数码电…

【Qt专栏】实现单例程序,禁止程序多开的几种方式

目录 一&#xff0c;简要介绍 二&#xff0c;实现示例&#xff08;Windows&#xff09; 1.使用系统级别的互斥机制 2.通过共享内存&#xff08;进程间通信-IPC&#xff09; 3.使用命名互斥锁&#xff08;不推荐&#xff09; 4.使用文件锁 5.通过网络端口检测 一&#xf…

Linux 下 Mysql 的使用(Ubuntu20.04)

文章目录 一、安装二、使用2.1 登录2.2 数据库操作2.2.1 创建数据库2.2.2 删除数据库2.2.3 创建数据表 参考文档 一、安装 Linux 下 Mysql 的安装非常简单&#xff0c;一个命令即可&#xff1a; sudo apt install mysql-server检查安装是否成功&#xff0c;输入&#xff1a; …

使用kubeadm方式快速部署一个K8S集群

目录 一、环境准备 二、环境初始化 三、在所有主机上安装相关软件 1、安装docker 2、配置k8s的yum源 3、安装kubelet、kubeadm、kubectl 四、部署Kubernetes Master 五、加入Kubernets Node 六、部署CNI网络插件 七、测试k8s集群 一、环境准备 我的是CentOS7系统&am…

iOS App签名与重签名:从开发者证书到重新安装运行

前文回顾&#xff1a; iOS脱壳技术&#xff08;二&#xff09;&#xff1a;深入探讨dumpdecrypted工具的高级使用方法 iOS逆向&#xff1a;越狱及相关概念的介绍 在本文中&#xff0c;我们将详细介绍iOS应用的签名过程&#xff0c;包括开发者证书的种类、证书与App ID、Provisi…

利用 Apifox 的 Mock 功能模拟常见业务数据的最佳方法

Apifox 拥有强大的 Mock 功能&#xff0c;兼容 Mock.js 语法的同时还提供 Nunjucks 和自定义脚本支持&#xff0c;能够满足不同场景需求。 今天给大家分享一些常见业务场景的 Mock 使用技巧&#xff0c;当然&#xff0c;实现的方法不唯一。在开始之前&#xff0c;你需要将 Api…

【C++】list

list 1. 简单了解list2. list的常见接口3. 简单实现list4. vector和list比较 1. 简单了解list list的底层是带头双向循环列表。因此list支持任意位置的插入和删除&#xff0c;且效率较高。但其缺陷也很明显&#xff0c;由于各节点在物理空间是不连续的&#xff0c;所以不支持对…

Python项目开发案例————学生信息管理系统(附源码)

一、学生信息管理系统 本文使用Python语言开发了一个学生信息管理系统&#xff0c;该系统可以帮助教师快速录入学生的信息&#xff0c;并且对学生的信息进行基本的增、删、改、查操作&#xff1b;还可以实时地将学生的信息保存到磁盘文件中。 1.1 需求分析 为了顺应互联网时代…

软件测试及数据分析处理实训室建设方案

一 、系统概述 软件测试及数据分析处理是软件开发过程中的一项重要测试活动&#xff0c;旨在验证不同软件模块或组件之间的集成与交互是否正常。综合测试确保各个模块按照设计要求正确地协同工作&#xff0c;以实现整个软件系统的功能和性能。以下是软件测试及数据分析处理的一…

SpringMVC程序开发

前言&#xff1a; &#x1f4d5;作者简介&#xff1a;热爱编程的小七&#xff0c;致力于C、Java、Python等多编程语言&#xff0c;热爱编程和长板的运动少年&#xff01; &#x1f4d8;相关专栏Java基础语法&#xff0c;JavaEE初阶&#xff0c;数据库&#xff0c;数据结构和算法…

【位运算】算法实战

文章目录 一、算法原理常见的位运算总结 二、算法实战1. leetcode面试题01.01. 判断字符是否唯一2. leetcode268 丢失的数字3. leetcode371 两整数之和4. leetcode004 只出现一次的数字II5. leetcode面试题17.19. 消失的两个数字 三、总结 一、算法原理 计算机中的数据都以二进…

香港服务器怎么打开SSH

​  SSH是一种远程登录协议&#xff0c;可以通过加密方式在网络上安全地传输数据。它允许用户在远程服务器上执行命令&#xff0c;管理文件和目录&#xff0c;并进行其他系统管理任务。 如何打开SSH服务? 1.确认已安装OpenSSH服务器&#xff1a; 你可以通过命令sudoapt-geti…

开发一款AR导览导航小程序多少钱?ar地图微信小程序 ar导航 源码

随着科技的不断发展&#xff0c;增强现实&#xff08;AR&#xff09;技术在不同领域展现出了巨大的潜力。AR导览小程序作为其中的一种应用形式&#xff0c;为用户提供了全新的观赏和学习体验。然而&#xff0c;开发一款高质量的AR导览小程序需要投入大量的时间、人力和技术资源…

Sql Server导出数据库到另一个数据库

1.打开sql server数据库&#xff0c;连接到服务器后&#xff0c;找到需要导出的数据库&#xff0c;右击后选择 任务->导出数据。 2.点击 下一步。 3.身份验证可以使用SQL Server身份验证&#xff0c;就是当时建立连接时的用户名和密码&#xff0c;数据库名称使用默认的&…

Kafka生产者原理 kafka生产者发送流程 kafka消息发送到集群步骤 kafka如何发送消息 kafka详解

kafka尚硅谷视频&#xff1a; 10_尚硅谷_Kafka_生产者_原理_哔哩哔哩_bilibili ​ 1. producer初始化&#xff1a;加载默认配置&#xff0c;以及配置的参数&#xff0c;开启网络线程 2. 拦截器拦截 3. 序列化器进行消息key, value序列化 4. 进行分区 5. kafka broker集群 获取…

数据库为什么使用B+树而不是B树做索引

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…

华为质量管理:从产品质量到用户体验,Kano模型成为新方向

目录 前言 华为质量管理的四个阶段 基于 IPD 如何做质量管理呢&#xff1f; CSDN相关课程 作者简介 前言 今天继续来谈谈华为流程体系中的质量管理过程。 通常来说质量具体是指产品的质量&#xff0c;也就是产品的使用价值及其属性。 产品再细分的话可以分为三个层次&a…

Python 数据分析——matplotlib 快速绘图

matplotlib采用面向对象的技术来实现&#xff0c;因此组成图表的各个元素都是对象&#xff0c;在编写较大的应用程序时通过面向对象的方式使用matplotlib将更加有效。但是使用这种面向对象的调用接口进行绘图比较烦琐&#xff0c;因此matplotlib还提供了快速绘图的pyplot模块。…

《vue3实战》在created生命周期中运用slice()方法结合element plus组件实现电影评价系统的分页

目录 前言 电影评价系统的分页是什么&#xff1f;它具体的作用体现在哪些方面&#xff1f; 一、slice的含义、语法和作用以及created的作用 slice是什么&#xff1f;slice有什么语法&#xff1f;slice的作用体现在哪些方面&#xff1f; created生命周期的作用&#xff1a;…