Java tutorial
//package com.java2s; //License from project: Open Source License import android.content.Context; import android.content.res.Resources; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.widget.TextView; public class Main { private static final String TAG = "AutoFitTextHelper"; private static final boolean SPEW = false; private TextView mTextView; /** * Original textSize of the TextView. */ private float mTextSize; private boolean mIsAutofitting; /** * Recursive binary search to find the best size for the text. */ private static float getAutofitTextSize(CharSequence text, TextPaint paint, float targetWidth, int maxLines, float low, float high, float precision, DisplayMetrics displayMetrics) { float mid = (low + high) / 2.0f; int lineCount = 1; StaticLayout layout = null; paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, mid, displayMetrics)); if (maxLines != 1) { layout = new StaticLayout(text, paint, (int) targetWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); lineCount = layout.getLineCount(); } if (SPEW) Log.d(TAG, "low=" + low + " high=" + high + " mid=" + mid + " target=" + targetWidth + " maxLines=" + maxLines + " lineCount=" + lineCount); if (lineCount > maxLines) { // For the case that `text` has more newline characters than `maxLines`. if ((high - low) < precision) { return low; } return getAutofitTextSize(text, paint, targetWidth, maxLines, low, mid, precision, displayMetrics); } else if (lineCount < maxLines) { return getAutofitTextSize(text, paint, targetWidth, maxLines, mid, high, precision, displayMetrics); } else { float maxLineWidth = 0; if (maxLines == 1) { maxLineWidth = paint.measureText(text, 0, text.length()); } else { for (int i = 0; i < lineCount; i++) { if (layout.getLineWidth(i) > maxLineWidth) { maxLineWidth = layout.getLineWidth(i); } } } if ((high - low) < precision) { return low; } else if (maxLineWidth > targetWidth) { return getAutofitTextSize(text, paint, targetWidth, maxLines, low, mid, precision, displayMetrics); } else if (maxLineWidth < targetWidth) { return getAutofitTextSize(text, paint, targetWidth, maxLines, mid, high, precision, displayMetrics); } else { return mid; } } } /** * Set the original text size of the View. * * @see TextView#setTextSize(float) */ public void setTextSize(float size) { setTextSize(TypedValue.COMPLEX_UNIT_SP, size); } /** * Set the original text size of the View. * * @see TextView#setTextSize(int, float) */ public void setTextSize(int unit, float size) { if (mIsAutofitting) { // We don't want to update the TextView's actual textSize while we're autofitting // since it'd get set to the autofitTextSize return; } Context context = mTextView.getContext(); Resources r = Resources.getSystem(); if (context != null) { r = context.getResources(); } setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics())); } private static int getLineCount(CharSequence text, TextPaint paint, float size, float width, DisplayMetrics displayMetrics) { paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, size, displayMetrics)); StaticLayout layout = new StaticLayout(text, paint, (int) width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); return layout.getLineCount(); } private void setRawTextSize(float size) { if (mTextSize != size) { mTextSize = size; } } }