Android根据文字长度自动调整字号的TextView

原创 2016年08月31日 12:51:55

概述

在项目中遇到需求就是,标题根据文字的长度自动适配字号大小和换行显示,因为标题可能很长然后显示不完全。

实现

根据需求,很容易想到根据TextView的宽高和文字长度计算字号,然后重新设置TextView字号。


/**
* @author  Wastrel
* @date 创建时间:2016年8月19日 上午9:12:01
* TODO
*/

import android.content.Context;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.TextView;

public class AutoFitTextView extends TextView {
    //unit px
    private static float DEFAULT_MIN_TEXT_SIZE = 15;
    private static float DEFAULT_MAX_TEXT_SIZE = 50;
    // Attributes
    private TextPaint testPaint;
    private float minTextSize;
    private float maxTextSize;

    public AutoFitTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialise();
    }

    private void initialise() {
        testPaint = new TextPaint();
        testPaint.set(this.getPaint());
        // max size defaults to the intially specified text size unless it is too small
        maxTextSize = this.getTextSize();
        if (maxTextSize <= DEFAULT_MIN_TEXT_SIZE) {
            maxTextSize = DEFAULT_MAX_TEXT_SIZE;
        }
        minTextSize = DEFAULT_MIN_TEXT_SIZE;
    }

    /**
     * Re size the font so the specified text fits in the text box * assuming the text box is the specified width.
     */
    private void refitText(String text, int textWidth, int textHeight) {
        if (textWidth > 0&&textHeight>0) {
            //allow diplay rect
            int availableWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight();
            int availableHeight = textHeight - this.getPaddingBottom() - this.getPaddingTop();
            //by the line calculate allow displayWidth
            int autoWidth = availableWidth;
            float mult=1f;
            float add=0;
            if (Build.VERSION.SDK_INT>16)
            {
                mult=getLineSpacingMultiplier();
                add=getLineSpacingExtra();
            }else{
                //the mult default is 1.0f,if you need change ,you can reflect invoke this field;
            }
            float trySize = maxTextSize;
            testPaint.setTextSize(trySize);
            int oldline=1,newline=1;
            while ((trySize > minTextSize)) {
                //calculate text singleline width。
                int displayW = (int) testPaint.measureText(text);
                //calculate text singleline height。
                int displaH=round(testPaint.getFontMetricsInt(null)*mult+add);
                if (displayW < autoWidth) {
                    break;
                }
                //calculate maxLines
                newline = availableHeight / displaH;
                //if line change ,calculate new autoWidth
                if (newline > oldline) {
                    oldline=newline;
                    autoWidth = availableWidth * newline;
                    continue;
                }
                //try more small TextSize
                trySize -= 1;
                if (trySize <= minTextSize) {
                    trySize = minTextSize;
                    break;
                }

                testPaint.setTextSize(trySize);
            }
            //setMultiLine
            if (newline>=2)
            {
                this.setSingleLine(false);
                this.setMaxLines(newline);
            }
            this.setTextSize(TypedValue.COMPLEX_UNIT_PX, trySize);
        }
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int before, int after) {
        super.onTextChanged(text, start, before, after);
        refitText(text.toString(), this.getWidth(), this.getHeight());
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        Log.e("TagSizeChange","new("+w+","+h+") old("+oldw+""+oldh+")");
        if (w != oldw || h != oldh) {
            refitText(this.getText().toString(), w, h);
        }
    }
    //FastMath.round()
     public static int round(float value) {
                long lx = (long) (value * (65536 * 256f));
                return (int) ((lx + 0x800000) >> 24);
            }
}

代码注释很详细,具体的请看代码。

效果

布局文件使用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.autofittext.MainActivity">

    <com.example.autofittext.AutoFitTextView
        android:background="#80808080"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:textSize="30sp"
        android:gravity="center"
        android:text="@string/str10" />
    <com.example.autofittext.AutoFitTextView
        android:layout_marginTop="15dp"
        android:background="#80808080"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:textSize="30sp"
        android:text="@string/str20"/>


    <com.example.autofittext.AutoFitTextView
        android:layout_marginTop="15dp"
        android:background="#80808080"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:textSize="30sp"
        android:text="@string/str30"/>

    <com.example.autofittext.AutoFitTextView
        android:layout_marginTop="15dp"
        android:background="#80808080"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:textSize="30sp"
        android:gravity="center"
        android:text="@string/str40"/>
    <com.example.autofittext.AutoFitTextView
        android:layout_marginTop="15dp"
        android:background="#80808080"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:textSize="30sp"
        android:text="@string/str50"/>
    <com.example.autofittext.AutoFitTextView
        android:layout_marginTop="15dp"
        android:background="#80808080"
        android:gravity="center"
        android:textSize="30sp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="@string/str60"/>
    <com.example.autofittext.AutoFitTextView
        android:layout_marginTop="15dp"
        android:background="#80808080"
        android:gravity="center"
        android:textSize="30sp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="@string/str70"/>
</LinearLayout>

效果图

后记

  • 使用的时候尽量对TextView的宽高限制。wrap_content 可能达不到想要的效果。
  • 如果想多行的时候左对齐,那么可以在设置多行的时候对Gravity 属性进行设置。
版权声明:本文为博主原创文章,转载请标明来自于http://blog.csdn.net/venusic。

相关文章推荐

Android 自定义TextView实现文本内容自动调整字体大小以适应TextView的大小

/** * 自定义TextView,文本内容自动调整字体大小以适应TextView的大小 * @author yzp */ public class AutoFitTextView e...

Android Paint的使用详解

尊重原创,转载请标明出处    http://blog.csdn.net/abcdef314159 自定义控件具有很强的灵活性,可以根据你的想法画出各种各样的图案,在Android中如果是自定义控件的...

Android根据所设置的textSize获取字体高度和设置行高

From:http://qiaoweishu.iteye.com/blog/780526 网络中好多资料介绍获取字体高度的方法如下:  Java代码   public i...

Android控件TextView中ellipsize属性(设置当文字长度超过textview宽度时的显示方式)

TextView中可以设置一个ellipsize属性,作用是当文字长度超过textview宽度时的显示方式: 例如,字符串"abcedfg" 的各种现实效果: android:ellipsize=”...

[Android]TextView设置字体大小时应该知道的事-同样的textSize不同的效果

在学helloworld的时候就第一个接触的控件就是TextView,这个是非常常用的一个文本控件,现在我们要说的就是关于设置大小时应该清楚的一两个问题.下面这个案例来说明. 先看xml中的案例: ...

限制TextView文字现实的长度以及超长显示的方式

有时在开发中,TextView如果设置了android:ellipsize="end",显示的文字超长是最后超出的部分为以“...”(3个点结束) 碰到一些变态的产品经理他就会闲3个点不好看,非得改...

AutoFitTextView(Android textview根据字体长度调整字体大小)

一丶效果图 二丶概述 测试提了一个bug(极端情况下文字重合): iOS那边由于字体大小可以根据text长度自动调整,无此bug,产品希望做成iOS类似效果 三丶找控件 gitHub链接:htt...

Github项目解析(四)-->动态更改TextView的字体大小

最近app开发产品提出了一个需求是,需要动态更改TextView内容字体的大小,比如设定TextView只有一行,宽度只有200dp,内容超过这个之后就缩小字体显示,只能能将字体都显示完全;好吧,其实...

安卓AutoFitTextView实例Dmeo分享自适应

一、首先看看运行效果图: 二、主要核心类: 1、AutofitHelper.java 2、AutofitLayout.java 3、AutofitTextView.java 以上为主要...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)