美文网首页Android 进阶技术篇专题我爱编程
Android 巧用二分法自动调整字体大小

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

作者: SwitchLife | 来源:发表于2018-09-09 17:42 被阅读1次

    开篇

      不BB, 直奔主题。

    场景

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

    效果截屏

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

    立即体验

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


    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的宽度 - 一个字符宽度,说明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 < maxTextWidth - alphaWidth * 2) {
                textSize = textSize + textSize * 2;
                getPaint().setTextSize(textSize / 2);
            }
            loop();
        }
    
        public void setAutoSizeText(CharSequence text, boolean resizeImmediately){
            setText(text);
            if (resizeImmediately)
                resetTextSizeIfNecessary();
        }
    

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

    篇尾

      Wechat:eoy9527

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

    相关文章

      网友评论

        本文标题:Android 巧用二分法自动调整字体大小

        本文链接:https://www.haomeiwen.com/subject/yekdgftx.html