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。

安卓AutoFitTextView实例Dmeo分享自适应

一、首先看看运行效果图: 二、主要核心类: 1、AutofitHelper.java 2、AutofitLayout.java 3、AutofitTextView.java 以上为主要...

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

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

android-autofittextview自适应字体大小源码分析。

https://github.com/grantland/android-autofittextview。 用法: AutofitTextView android:id="@+id/o...

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

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

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

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

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Android自定义TextView根据控件高度和宽度,解决字体适配问题

出现原因:项目需要的设备广,设计到了手机,平板,大电视,无数的分辨率,无数的尺寸造成的屏幕密度;这就很伤了;如果还是使用资源文件values来适配的话,那烧香都怕香不够,所以引发了一下的连环事故; ...

Android 自动适应字体大小的EditText

Android 中 EditText 单行显示时,如果字体过多,自动缩小字体,在字号小于指定字号时,显示"..." ,具体请参考如下代码:...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

设置Textview最大长度,超出显示省略号

内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android根据文字长度自动调整字号的TextView
举报原因:
原因补充:

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