热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android巧用二分法自动调整字体大小

开篇  不BB,直奔主题。场景  固定宽度的TextView,在不同尺寸的手机上显示效果不一样:小屏上会显示成两行,大屏上显示一行。  在遇到这种情况时,我们该如何应对呢?我们的第

开篇

  不BB, 直奔主题。

场景

  固定宽度的TextView,在不同尺寸的手机上显示效果不一样:小屏上会显示成两行,大屏上显示一行。
  在遇到这种情况时,我们该如何应对呢?我们的第一想法当然是自定义一个自动适配字体大小的TextView。

效果截屏

我们看到,在TextView宽度不变的情况下,它会根据文本长度自动调整字体大小。当然,在字符串不变的情况下,它同样会根据TextView宽度自动调整字体大小。

《Android 巧用二分法自动调整字体大小》
《Android 巧用二分法自动调整字体大小》

立即体验

扫描以下二维码下载体验App(从0.2.3版本开始,体验App内嵌版本更新检测功能):

《Android 巧用二分法自动调整字体大小》

JSCKit库传送门:https://github.com/JustinRoom/JSCKit

简析源码

AutoTextSizeView.java

public class AutoTextSizeView extends AppCompatTextView implements IViewAttrDelegate{
public AutoTextSizeView(Context context) {
super(context);
initAttr(context, null, 0);
}
public AutoTextSizeView(Context context, AttributeSet attrs) {
super(context, attrs);
initAttr(context, attrs, 0);
}
public AutoTextSizeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttr(context, attrs, defStyleAttr);
}
@Override
public void initAttr(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
setGravity(Gravity.CENTER);
setMaxLines(1);
}

  • 1、我们在监听到View宽度发生变化时,自动调整字体大小:

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//do nothing if it's width was not changed
if (oldw == w){
return;
}
resetTextSizeIfNecessary();
}

  • 2、因为自动适配字体大小的过程是一个不断循环去匹配的一个过程,所以我们开启一个线程去干这件事。

private void resetTextSizeIfNecessary() {
removeCallbacks(r);
postDelayed(r, 20);
}
private Runnable r = new Runnable() {
@Override
public void run() {
loop();
}
};

  • 3、匹配字体大小的核心算法:当前字体大小float textSize = getPaint().getTextSize();

A、字符宽度 > TextView的宽度,说明textSize大了,调整字体大小:textSize = (textSize + textSize / 2) / 2;
B、字符宽度 <TextView的宽度 &#8211; 一个字符宽度,说明textSize小了,调整字体大小:textSize = (textSize + textSize * 2) / 2;
通过递归反复匹配字体大小,直到匹配到相对合适的字体大小为止。这个过程往往经过1次或者几次就能匹配到,利用二分法的思想匹配效率很高。

private void loop() {
CharSequence text = getText();
if (text == null || text.length() == 0)
return;
int maxTextWidth = getWidth() - getPaddingLeft() - getPaddingRight();
float textWidth = getPaint().measureText(text, 0, text.length());
float textSize = getPaint().getTextSize();
float alphaWidth = getPaint().measureText("a");
if (textWidth >= (maxTextWidth - alphaWidth * 2) && textWidth <= maxTextWidth) {
//匹配到合适的字体大小了
//这里我试图直接调用invalidate()刷新视图,但是并没有达到想要的结果
//我们必须重新setText(...)
//reset text
//call it's onMeasure(int, int) and onDraw(Canvas)
//增加这个方法,只是为了区分是自动适配字体大小后setText(...)还是我们手动调用setText(...)
setAutoSizeText(text, false);
return;
}
//字体大了
//here is the idea of binary search
if (textWidth > maxTextWidth) {
textSize = textSize + textSize / 2;
getPaint().setTextSize(textSize / 2);
}
//字体小了
if (textWidth textSize = textSize + textSize * 2;
getPaint().setTextSize(textSize / 2);
}
loop();
}
public void setAutoSizeText(CharSequence text, boolean resizeImmediately){
setText(text);
if (resizeImmediately)
resetTextSizeIfNecessary();
}

《Android 巧用二分法自动调整字体大小》

从26.0匹配到87.75,之经历过了4次匹配,匹配效率是真的很高。&#x1f60a;
童鞋们,如果你们觉得不错的话给我点个&#x1f497;吧,谢谢!!!

篇尾

  Wechat:eoy9527

在人生的道路上,当你的希望一个个落空的时候,你也要坚定,要沉着。 —— 朗费罗


推荐阅读
author-avatar
爱走了我来了two_537
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有