自動調節字型大小的TextView
今天項目中遇見一個需求,在此記錄。
需求描述:TextView中text過長的時候,優先縮小字型,如果縮小字型依舊過長,再換行。
Google原生自動縮放是以高度作為标準的,隻有高度不夠時才會進行縮放。與我們需要以寬度為标準不同,故自定義View
自定義TextView代碼如下:
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.TextView;
public class AutoTextView extends TextView {
private float mTextSize;
private float mMinSize;
private float mSizeStep;
private StaticLayout mStaticLayout;
private TextPaint mTextPaint;
public AutoTextView(Context context) {
this(context, null);
}
public AutoTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AutoTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialise(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
autoText(parentWidth, parentHeight);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void initialise(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.AuTotextView, defStyleAttr, 0);
mMinSize = attr.getDimension(R.styleable.AuTotextView_autoSizeMinTextSize, 0);
mSizeStep = attr.getDimension(R.styleable.AuTotextView_autoSizeStepGranularity, 0);
attr.recycle();
if (mMinSize == 0 && mSizeStep == 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mMinSize = getAutoSizeMinTextSize();
mSizeStep = getAutoSizeStepGranularity();
setAutoSizeTextTypeWithDefaults(AUTO_SIZE_TEXT_TYPE_NONE);
}
}
mTextPaint = new TextPaint();
mTextPaint.set(this.getPaint());
mTextSize = getTextSize();
}
/**
* auto text size.
*
* @param parentWidth parant layout can give the max width;
* @param parentHeight parant layout can give the max height;
*/
private void autoText(int parentWidth, int parentHeight) {
int maxWidth = getMaxWidth();
int maxHeight = getMaxHeight();
if (maxWidth != -1 && maxWidth < parentWidth) {
parentWidth = maxWidth;
}
if (maxHeight != -1 && maxHeight < parentHeight) {
parentHeight = maxHeight;
}
int viewWidth = parentWidth - getTotalPaddingLeft()
- getTotalPaddingRight();
if (viewWidth < 0) {
return;
}
if (mTextPaint == null) {
mTextPaint = new TextPaint();
}
mTextPaint.set(getPaint());
if (mMinSize > 0 && mSizeStep > 0) {
float currentSize = mTextSize;
CharSequence text = getText();
mTextPaint.setTextSize(currentSize);
float textWidth = mTextPaint.measureText(text.toString());
while (textWidth > viewWidth && currentSize > mMinSize) {
currentSize -= mSizeStep;
mTextPaint.setTextSize(currentSize);
textWidth = mTextPaint.measureText(text.toString());
}
setTextSize(TypedValue.COMPLEX_UNIT_PX, currentSize);
measureHeight(parentHeight, parentWidth);
}
}
private void measureHeight(int parentHeight, int parentWidth) {
int maxLines = getMaxLines();
if (maxLines > 1) {
int viewWidth = parentWidth - getTotalPaddingLeft()
- getTotalPaddingRight();
int extendedPaddingBottom = 0;
int extendedPaddingTop = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
extendedPaddingBottom = getExtendedPaddingBottom();
extendedPaddingTop = getExtendedPaddingTop();
}
int availedHeight = parentHeight - extendedPaddingBottom - extendedPaddingTop;
if (availedHeight <= 0) {
return;
}
mStaticLayout = new StaticLayout(getText(), getPaint(),
viewWidth, Layout.Alignment.ALIGN_NORMAL,
getLineSpacingMultiplier(), getLineSpacingExtra(), false);
int lineCount = mStaticLayout.getLineCount();
if (mStaticLayout.getHeight() > availedHeight && lineCount > 1
&& lineCount <= maxLines + 1) {
setMaxLines(lineCount - 1);
}
}
}
}