Android AutoWrapTextView中英文排版问题的解决方法
发布时间 - 2026-01-11 01:14:31 点击率:次前言

最近项目有新需求,UED给了个卡券密码的UI样式,如图:
我一看很简单啊,一个TextView解决问题,然后做好以后在模拟器里一看.....
纳尼,这个时候才想起来,TextView 中英文在一起会有排版问题,那怎么解决呢......
思路
刚开始的想法是一个字符一个字符的去绘制,绘制到最右边的临界点就换行绘制,结果实践以后发现不同的字符之间的间距不一样,显示会非常凌乱,又没有什么好的方案解决这个间距问题,所以这个方案pass;单个字符绘制不行那就一行一行绘制,根据View的长度把文本拆分成N行,然后一行一行的绘制。
实现
首先创建一个继承自View的AutoWrapTextView
public class AutoWrapTextView extends View {
}
来看看它的构造方法
public AutoWrapTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
initStyle(context, attrs);
initPaint();
}
init方法里分别调用了initStyle方法和initPaint方法;
initStyle方法主要解析自定义的属性
private void initStyle(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AutoWrapTextViewStyle);
mPaddingLeft = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_paddingLeft, 0);
mPaddingRight = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_paddingRight, 0);
mPaddingTop = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_paddingTop, 0);
mPaddingBottom = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_paddingBottom, 0);
mTextColor = typedArray.getColor(R.styleable.AutoWrapTextViewStyle_textColor, Color.BLACK);
mTextSize = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_textSize, 50);
mLineSpacingExtra = typedArray.getInteger(R.styleable.AutoWrapTextViewStyle_lineSpacingExtra, 7);
typedArray.recycle();
}
属性名含义都很明显不用过多解释,initPaint方法就是初始化一个文本画笔
private void initPaint() {
mTextPaint = new TextPaint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(mTextColor);
mTextPaint.setTextAlign(Paint.Align.LEFT);
}
接下来我们看看设置文本的方法setText方法
public void setText(String text) {
if (TextUtils.isEmpty(text)) return;
//把文本转换成Char数组
mTextCharArray = text.toCharArray();
requestLayout();
}
首先把文本转换成Char数组,然后循环数组把整个文本拆分成N行文本,下面来看看核心方法splitText方法
private void splitText(int heightMode) {
if (mTextCharArray == null) return;
mSplitTextList = new ArrayList<>();
mSingleTextWidth = getMeasuredWidth() - mPaddingLeft - mPaddingRight;
int currentSingleTextWidth = 0;
StringBuffer lineStringBuffer = new StringBuffer();
for (int i = 0, length = mTextCharArray.length; i < length; i++) {
char textChar = mTextCharArray[i];
currentSingleTextWidth += getSingleCharWidth(textChar);
if (currentSingleTextWidth > mSingleTextWidth) {
mSplitTextList.add(lineStringBuffer.toString());
lineStringBuffer = new StringBuffer();
currentSingleTextWidth = 0;
i--;
} else {
lineStringBuffer.append(textChar);
if (i == length - 1) mSplitTextList.add(lineStringBuffer.toString());
}
}
int textHeight = 0;
mSplitTextRectArray = new Rect[mSplitTextList.size()];
for (int m = 0, length = mSplitTextList.size(); m < length; m++) {
String lineText = mSplitTextList.get(m);
Rect lineTextRect = new Rect();
mTextPaint.getTextBounds(lineText, 0, lineText.length(), lineTextRect);
if (heightMode == MeasureSpec.AT_MOST) {
textHeight += (lineTextRect.height() + mLineSpacingExtra);
if (m == length - 1) {
textHeight = textHeight + mPaddingBottom + mPaddingTop;
}
} else {
if (textHeight == 0)
textHeight = getMeasuredHeight();
}
mSplitTextRectArray[m] = lineTextRect;
}
setMeasuredDimension(getMeasuredWidth(), textHeight);
}
首先创建一个属性名为mSplitTextList的List集合用来存放拆分的文本;
mSingleTextWidth 为单行文本显示的宽度;
currentSingleTextWidth 为当前一行累计计算的宽度;
然后开始循环Char数组,getSingleCharWidth方法就是计算单个Char的宽度;
如果currentSingleTextWidth 小于 mSingleTextWidth 就把Char添加到lineStringBuffer 当中,如果是最后一个Char就直接把lineStringBuffer添加到mSplitTextList集合当中
如果currentSingleTextWidth 大于 mSingleTextWidth,就把lineStringBuffer添加到mSplitTextList集合当中,重新给lineStringBuffer赋值,currentSingleTextWidth 归0;
循环结束以后拆分好的文本就都添加到mSplitTextList集合当中了。
拆分完成以后循环mSplitTextList集合,得到每一行文本的Rect值,绘制文本的时候会用到,然后设置View的宽高。
接下来就是绘制方法drawText
public void drawText(Canvas canvas) {
if (mSplitTextList == null || mSplitTextList.size() == 0) return;
int marginTop = getTopTextMarginTop();
for (int m = 0, length = mSplitTextList.size(); m < length; m++) {
String lineText = mSplitTextList.get(m);
canvas.drawText(lineText, mPaddingLeft, marginTop, mTextPaint);
marginTop += (mSplitTextRectArray[m].height() + mLineSpacingExtra);
}
}
首先得到第一行文本距离顶部的高度marginTop,然后循环文本绘制每一行文本内容。
效果图
我们来看下最后的效果
结束语
至此整个类的逻辑分析就结束了,想看完整源码的可以移步:https://github.com/chenpengfei88/AutoWrapTextView或者通过本地进行下载:http://xiazai./201705/yuanma/AutoWrapTextView().rar
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# autowraptextview
# android
# 中英文混排
# 中英文排序
# Android用户输入自动提示控件AutoCompleteTextView使用方法
# Android自动获取输入短信验证码库AutoVerifyCode详解
# Android中使用 AutoCompleteTextView 实现手机号格式化附带清空历史的操作
# Android自动编辑文本框(AutoCompleteTextView)使用方法详解
# Android中AutoCompleteTextView自动提示
# Android仿新浪微博oauth2.0授权界面实现代码(2)
# android中AutoCompleteTextView的简单用法(实现搜索历史)
# Android仿百度谷歌搜索自动提示框AutoCompleteTextView简单应用示例
# 关于Android HTML5 audio autoplay无效问题的解决方案
# Android AutoCompleteTextView自动提示文本框实例代码
# Android App开发的自动化测试框架UI Automator使用教程
# Android中AutoCompleteTextView与TextWatcher结合小实例
# Android AutoValue使用和扩展库
# 就把
# 来看看
# 转换成
# 创建一个
# 是一个
# 有什么
# 会有
# 好了
# 那就
# 给了
# 都很
# 很简单
# 这个时候
# 自定义
# 解决问题
# 中了
# 刚开始
# 想看
# 如图
# 这篇文章
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
高性能网站服务器部署指南:稳定运行与安全配置优化方案
文字头像制作网站推荐软件,醒图能自动配文字吗?
如何用5美元大硬盘VPS安全高效搭建个人网站?
1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤
Android实现代码画虚线边框背景效果
Laravel怎么发送邮件_Laravel Mail类SMTP配置教程
悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】
Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】
Laravel如何实现文件上传和存储?(本地与S3配置)
Laravel如何集成第三方登录_Laravel Socialite实现微信QQ微博登录
Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件
网站建设整体流程解析,建站其实很容易!
Laravel如何构建RESTful API_Laravel标准化API接口开发指南
javascript基于原型链的继承及call和apply函数用法分析
Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道
如何自定义建站之星网站的导航菜单样式?
php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】
微信小程序 wx.uploadFile无法上传解决办法
如何打造高效商业网站?建站目的决定转化率
PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)
Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权
VIVO手机上del键无效OnKeyListener不响应的原因及解决方法
Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
怎么用AI帮你设计一套个性化的手机App图标?
使用豆包 AI 辅助进行简单网页 HTML 结构设计
Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】
Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】
,怎么在广州志愿者网站注册?
Laravel如何使用Blade模板引擎?(完整语法和示例)
Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)
手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?
Laravel的辅助函数有哪些_Laravel常用Helpers函数提高开发效率
如何快速完成中国万网建站详细流程?
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
如何在搬瓦工VPS快速搭建网站?
如何确保FTP站点访问权限与数据传输安全?
如何在万网利用已有域名快速建站?
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
如何快速搭建支持数据库操作的智能建站平台?
香港服务器租用费用高吗?如何避免常见误区?
Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
LinuxCD持续部署教程_自动发布与回滚机制
如何快速搭建自助建站会员专属系统?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
Mybatis 中的insertOrUpdate操作
Laravel如何实现一对一模型关联?(Eloquent示例)
中山网站推广排名,中山信息港登录入口?

