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

来源:互联网 发布:知美整形是正规医院吗? 编辑:程序博客网 时间:2024/05/18 01:09

概述

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

实现

根据需求,很容易想到根据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 属性进行设置。
1 0