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

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

相关文章

ChatGPT提示与技巧分享:如何作出更好的提示2023年8月

​对ChatGPT的一些酷炫技巧感兴趣吗?这里提供了一些可以帮助你充分利用ChatGPT&#xff0c;成为AI工具专家的技巧。 毫无疑问&#xff0c;ChatGPT是目前最广泛使用的人工智能工具之一。它不仅毫不留情地取代了一些特定领域常用的软件小工具&#xff08;如智能对联、经典语录生…

ESP32应用教程(1)— VL53L3CX距离传感器

文章目录 前言 1 产品概述 1.1 技术规格 1.2 系统框图 1.3 设备引脚分布 2 工作流程 2.1 系统功能描述 2.2 状态机描述 2.3 测距模式说明 3 控制接口 3.1 设备地址 3.2 IC写1个字节数据 3.3 IC读1个字节数据 3.4 IC写多个字节数据 3.5 IC读多个字节数据 3.6 IC…

Nacos配置管理、Feign远程调用、Gateway服务网关

1.Nacos配置管理 1.1.将配置交给Nacos管理的步骤 1.在Nacos中添加配置 Data Id服务名称-环境名称.yaml eg&#xff1a;userservice-dev.yaml 2.引入nacos-config依赖 在user-service服务中&#xff0c;引入nacos-config的客户端依赖 <!--nacos配置管理依赖--> <dep…

Flink、Yarn架构,以Flink on Yarn部署原理详解

Flink、Yarn架构&#xff0c;以Flink on Yarn部署原理详解 Flink 架构概览 Apache Flink是一个开源的分布式流处理框架&#xff0c;它可以处理实时数据流和批处理数据。Flink的架构原理是其实现的基础&#xff0c;架构原理可以分为以下四个部分&#xff1a;JobManager、TaskM…

Linux:LAMP架构与论坛搭建

目录 一、动态资源与语言 二、LAMP 架构的组成 三、CGI和astcgi 3.1CGI​​​​​​ 3.2fastcgi 3.3CGI和fastcgi比较 3.4 PHP 配置 3.5 Opcode语言 四、编译安装Apache http 服务 五、安装论坛 一、动态资源与语言 WEB 资源类型&#xff1a; 静态资源&#xff1a;原…

Qt串口通信学习文档

这是官方文档&#xff0c;我也在学习。 QSerialPort Class | Qt Serial Port 5.15.14https://doc.qt.io/qt-5/qserialport.html

如何将下载的安装包导入PyCharm

1. 下载安装包 这里以pyke为例。下载好之后解压缩&#xff0c;然后放入/Lib/site-packages/pyke-1.1.1 2. 打开PyCharm的终端进行安装 python setup.py install 3. 安装好之后导入即可使用 import pyke

用户端Web自动化测试_L3

目录&#xff1a; 浏览器复用Cookie 复用pageobject设计模式异常自动截图测试用例流程设计电子商务产品实战 1.浏览器复用 复用浏览器简介 为什么要学习复用浏览器&#xff1f; 自动化测试过程中&#xff0c;存在人为介入场景提高调试UI自动化测试脚本效率 复用已有浏览…

牛客网Verilog刷题 | 入门特别版本

文章目录 1、 VL1 输出12、VL2 wire连线3、 VL3 多wire连接4、VL4 反相器5、VL5 与门6、VL6 NOR 门7、VL7 XOR 门8、VL8 逻辑运算10、VL10 逻辑运算211、VL11 多位信号12、VL12 信号顺序调整13、VL13 位运算与逻辑运算14、VL14 对信号按位操作15、VL15 信号级联合并16、VL16 信…

Qt 自定义提示框 右下角冒泡

网页右下角上经常会出现一些提示性的信息&#xff0c;B/S有的东西&#xff0c;C/S当然也可以有&#xff0c;就像QQ的消息提示一样&#xff01; 实现一个类似的东西并不困难&#xff0c;只要想明白原理实现起来就很简单了&#xff01; 实现原理&#xff1a; &#xff08;1&#…

在百度地图中添加自定义全屏控件

百度地图中添加全屏控件 前置知识&#xff1a; 进入整个页面的全屏模式 &#xff1a;document.documentElement.requestFullscreen() 进入特定元素的全屏模式 &#xff1a; document.getElementById("ID").requestFullscreen() 退出全屏&#xff1a;document.exitFu…

免费PPT素材网站,我推荐这6个

找PPT素材、模板&#xff0c;就上这6个网站&#xff0c;免费下载&#xff0c;建议收藏~ 菜鸟图库 https://www.sucai999.com/search/ppt/0_0_0_1.html?vNTYwNDUx 菜鸟图库网有非常丰富的免费素材&#xff0c;像设计类、办公类、自媒体类等素材都很丰富。PPT模板种类很多&…

leetcode76. 最小覆盖子串(滑动窗口-java)

滑动窗口 最小覆盖子串滑动窗口代码 上期经典 最小覆盖子串 难度 - 困难 原题链接 - 最小覆盖字串 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 “” 。 注意&#xff1a; 对于 t…

金额千位符自定义指令

自定义指令文件 moneyFormat.js /*** v-money 金额千分位转换*/export default {inserted: inputFormatter({// 格式化函数formatter(num, util) {if(num null || num || num undefined || typeof(num) undefined){return }if(util 万元 || util 万){return formatMone…

客户案例:高性能、大规模、高可靠的AIGC承载网络

客户是一家AIGC领域的公司&#xff0c;他们通过构建一套完整的内容生产系统&#xff0c;革新内容创作过程&#xff0c;让用户以更低成本完成内容创作。 客户网络需求汇总 RoCE的计算网络RoCE存储网络1.不少于600端口200G以太网接入端口&#xff0c;未来可扩容至至少1280端口1.…

cuda面试准备(一),架构调试

1 cuda架构 硬件方面 SP (streaming Process) ,SM (streaming multiprocessor) 是硬件(GPUhardware) 概念。而thread,block,grid,warp是软件上的(CUDA) 概念 SP:最基本的处理单元,streaming processor,也称为CUDA core,最后具体的指令和任务都是在SP上处理的。GPU进行并行…

实验七 Linux 内核移植

【实验目的】 掌握 Linux 内核配置和编译的基本方法 【实验环境】 ubuntu 14.04 发行版FS4412 实验平台交叉编译工具&#xff1a;arm-none-linux-gnueabi- 【注意事项】 实验步骤中以“$”开头的命令表示在 ubuntu 环境下执行&#xff0c;以“#”开头的命令表 示在开发板下…

Docker常用操作命令(二)

Docker常用操作命令(二) 11、进入容器 docker exec -it 容器名称or容器ID /bin/bash [rootzch01 ~]# docker exec -it 973ff3caff19 /bin/bash 退出容器 root973ff3caff19:/# exit 12、查看容器中的进程 docker top 容器名称or容器ID [rootzch01 ~]# docker top 973ff3c…

centos7安装JDK

centos7安装JDK 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.安装 我这有包&#xff0c;需要了可以私发 #创建/data/jdkmkdir -p /data/jdk#jdk的安装包放到/data/jdk里#进入/data/jdkcd /data/jdk #解压tar -zxvf jdk-8u181-linux-x64.tar.gz #编辑环境变量vim /…

vue3 基础知识 ( webpack 基础知识)05

你好 文章目录 一、组件二、如何支持SFC三、webpack 打包工具四、webpack 依赖图五、webpack 代码分包 一、组件 使用组件中我们可以获得非常多的特性&#xff1a; 代码的高亮&#xff1b;ES6、CommonJS的模块化能力&#xff1b;组件作用域的CSS&#xff1b;可以使用预处理器来…