直接上代码
AutofitTextView.Java
public class AutofitTextView extends TextView implements AutofitHelper.OnTextSizeChangeListener {
private AutofitHelper mHelper;
public AutofitTextView(Context context) {
super(context);
init(context,
null,
0);
}
public AutofitTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs,
0);
}
public AutofitTextView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs,
int defStyle) {
mHelper = AutofitHelper.create(
this, attrs, defStyle)
.addOnTextSizeChangeListener(
this);
}
/**
* {@inheritDoc}
*/
@Override
public void setTextSize(
int unit,
float size) {
super.setTextSize(unit, size);
if (mHelper !=
null) {
mHelper.setTextSize(unit, size);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setLines(
int lines) {
super.setLines(lines);
if (mHelper !=
null) {
mHelper.setMaxLines(lines);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setMaxLines(
int maxLines) {
super.setMaxLines(maxLines);
if (mHelper !=
null) {
mHelper.setMaxLines(maxLines);
}
}
/**
* Returns the {@link AutofitHelper} for this View.
*/
public AutofitHelper
getAutofitHelper() {
return mHelper;
}
/**
* Returns whether or not the text will be automatically re-sized to fit its constraints.
*/
public boolean isSizeToFit() {
return mHelper.isEnabled();
}
/**
* Sets the property of this field (sizeToFit), to automatically resize the text to fit its
* constraints.
*/
public void setSizeToFit() {
setSizeToFit(
true);
}
/**
* If true, the text will automatically be re-sized to fit its constraints; if false, it will
* act like a normal TextView.
*
* @param sizeToFit
*/
public void setSizeToFit(
boolean sizeToFit) {
mHelper.setEnabled(sizeToFit);
}
/**
* Returns the maximum size (in pixels) of the text in this View.
*/
public float getMaxTextSize() {
return mHelper.getMaxTextSize();
}
/**
* Set the maximum text size to the given value, interpreted as "scaled pixel" units. This size
* is adjusted based on the current density and user font size preference.
*
* @param size The scaled pixel size.
*
* @attr ref android.R.styleable#TextView_textSize
*/
public void setMaxTextSize(
float size) {
mHelper.setMaxTextSize(size);
}
/**
* Set the maximum text size to a given unit and value. See TypedValue for the possible
* dimension units.
*
* @param unit The desired dimension unit.
* @param size The desired size in the given units.
*
* @attr ref android.R.styleable#TextView_textSize
*/
public void setMaxTextSize(
int unit,
float size) {
mHelper.setMaxTextSize(unit, size);
}
/**
* Returns the minimum size (in pixels) of the text in this View.
*/
public float getMinTextSize() {
return mHelper.getMinTextSize();
}
/**
* Set the minimum text size to the given value, interpreted as "scaled pixel" units. This size
* is adjusted based on the current density and user font size preference.
*
* @param minSize The scaled pixel size.
*
* @attr ref me.grantland.R.styleable#AutofitTextView_minTextSize
*/
public void setMinTextSize(
int minSize) {
mHelper.setMinTextSize(TypedValue.COMPLEX_UNIT_SP, minSize);
}
/**
* Set the minimum text size to a given unit and value. See TypedValue for the possible
* dimension units.
*
* @param unit The desired dimension unit.
* @param minSize The desired size in the given units.
*
* @attr ref me.grantland.R.styleable#AutofitTextView_minTextSize
*/
public void setMinTextSize(
int unit,
float minSize) {
mHelper.setMinTextSize(unit, minSize);
}
/**
* Returns the amount of precision used to calculate the correct text size to fit within its
* bounds.
*/
public float getPrecision() {
return mHelper.getPrecision();
}
/**
* Set the amount of precision used to calculate the correct text size to fit within its
* bounds. Lower precision is more precise and takes more time.
*
* @param precision The amount of precision.
*/
public void setPrecision(
float precision) {
mHelper.setPrecision(precision);
}
@Override
public void onTextSizeChange(
float textSize,
float oldTextSize) {
}
}
AutofitHelper.java
public class AutofitHelper {
private static final String TAG =
"AutoFitTextHelper";
private static final boolean SPEW =
false;
private static final int DEFAULT_MIN_TEXT_SIZE =
8;
private static final float DEFAULT_PRECISION =
0.5f;
/**
* Creates a new instance of {@code AutofitHelper} that wraps a {@link TextView} and enables
* automatically sizing the text to fit.
*/
public static AutofitHelper
create(TextView view) {
return create(view,
null,
0);
}
/**
* Creates a new instance of {@code AutofitHelper} that wraps a {@link TextView} and enables
* automatically sizing the text to fit.
*/
public static AutofitHelper
create(TextView view, AttributeSet attrs) {
return create(view, attrs,
0);
}
/**
* Creates a new instance of {@code AutofitHelper} that wraps a {@link TextView} and enables
* automatically sizing the text to fit.
*/
public static AutofitHelper
create(TextView view, AttributeSet attrs,
int defStyle) {
AutofitHelper helper =
new AutofitHelper(view);
boolean sizeToFit =
true;
if (attrs !=
null) {
Context context = view.getContext();
int minTextSize = (
int) helper.getMinTextSize();
float precision = helper.getPrecision();
TypedArray ta = context.obtainStyledAttributes(
attrs,
R.styleable.AutofitTextView,
defStyle,
0);
sizeToFit = ta.getBoolean(R.styleable.AutofitTextView_sizeToFit, sizeToFit);
minTextSize = ta.getDimensionPixelSize(R.styleable.AutofitTextView_minTextSize,
minTextSize);
precision = ta.getFloat(R.styleable.AutofitTextView_precision, precision);
ta.recycle();
helper.setMinTextSize(TypedValue.COMPLEX_UNIT_PX, minTextSize)
.setPrecision(precision);
}
helper.setEnabled(sizeToFit);
return helper;
}
/**
* Re-sizes the textSize of the TextView so that the text fits within the bounds of the View.
*/
private static void autofit(TextView view, TextPaint paint,
float minTextSize,
float maxTextSize,
int maxLines,
float precision) {
if (maxLines <=
0 || maxLines == Integer.MAX_VALUE) {
return;
}
int targetWidth = view.getWidth() - view.getPaddingLeft() - view.getPaddingRight();
if (targetWidth <=
0) {
return;
}
CharSequence text = view.getText();
TransformationMethod method = view.getTransformationMethod();
if (method !=
null) {
text = method.getTransformation(text, view);
}
Context context = view.getContext();
Resources r = Resources.getSystem();
DisplayMetrics displayMetrics;
float size = maxTextSize;
float high = size;
float low =
0;
if (context !=
null) {
r = context.getResources();
}
displayMetrics = r.getDisplayMetrics();
paint.set(view.getPaint());
paint.setTextSize(size);
if ((maxLines ==
1 && paint.measureText(text,
0, text.length()) > targetWidth)
|| getLineCount(text, paint, size, targetWidth, displayMetrics) > maxLines) {
size = getAutofitTextSize(text, paint, targetWidth, maxLines, low, high, precision,
displayMetrics);
}
if (size < minTextSize) {
size = minTextSize;
}
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
}
/**
* 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) {
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;
}
}
}
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 static int getMaxLines(TextView view) {
int maxLines = -
1;
TransformationMethod method = view.getTransformationMethod();
if (method !=
null && method
instanceof SingleLineTransformationMethod) {
maxLines =
1;
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
maxLines = view.getMaxLines();
}
return maxLines;
}
private TextView mTextView;
private TextPaint mPaint;
/**
* Original textSize of the TextView.
*/
private float mTextSize;
private int mMaxLines;
private float mMinTextSize;
private float mMaxTextSize;
private float mPrecision;
private boolean mEnabled;
private boolean mIsAutofitting;
private ArrayList<OnTextSizeChangeListener> mListeners;
private TextWatcher mTextWatcher =
new AutofitTextWatcher();
private View.OnLayoutChangeListener mOnLayoutChangeListener =
new AutofitOnLayoutChangeListener();
private AutofitHelper(TextView view) {
final Context context = view.getContext();
float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
mTextView = view;
mPaint =
new TextPaint();
setRawTextSize(view.getTextSize());
mMaxLines = getMaxLines(view);
mMinTextSize = scaledDensity * DEFAULT_MIN_TEXT_SIZE;
mMaxTextSize = mTextSize;
mPrecision = DEFAULT_PRECISION;
}
/**
* Adds an {@link OnTextSizeChangeListener} to the list of those whose methods are called
* whenever the {@link TextView}'s {@code textSize} changes.
*/
public AutofitHelper
addOnTextSizeChangeListener(OnTextSizeChangeListener listener) {
if (mListeners ==
null) {
mListeners =
new ArrayList<OnTextSizeChangeListener>();
}
mListeners.add(listener);
return this;
}
/**
* Removes the specified {@link OnTextSizeChangeListener} from the list of those whose methods
* are called whenever the {@link TextView}'s {@code textSize} changes.
*/
public AutofitHelper
removeOnTextSizeChangeListener(OnTextSizeChangeListener listener) {
if (mListeners !=
null) {
mListeners.remove(listener);
}
return this;
}
/**
* Returns the amount of precision used to calculate the correct text size to fit within its
* bounds.
*/
public float getPrecision() {
return mPrecision;
}
/**
* Set the amount of precision used to calculate the correct text size to fit within its
* bounds. Lower precision is more precise and takes more time.
*
* @param precision The amount of precision.
*/
public AutofitHelper
setPrecision(
float precision) {
if (mPrecision != precision) {
mPrecision = precision;
autofit();
}
return this;
}
/**
* Returns the minimum size (in pixels) of the text.
*/
public float getMinTextSize() {
return mMinTextSize;
}
/**
* Set the minimum text size to the given value, interpreted as "scaled pixel" units. This size
* is adjusted based on the current density and user font size preference.
*
* @param size The scaled pixel size.
*
* @attr ref me.grantland.R.styleable#AutofitTextView_minTextSize
*/
public AutofitHelper
setMinTextSize(
float size) {
return setMinTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}
/**
* Set the minimum text size to a given unit and value. See TypedValue for the possible
* dimension units.
*
* @param unit The desired dimension unit.
* @param size The desired size in the given units.
*
* @attr ref me.grantland.R.styleable#AutofitTextView_minTextSize
*/
public AutofitHelper
setMinTextSize(
int unit,
float size) {
Context context = mTextView.getContext();
Resources r = Resources.getSystem();
if (context !=
null) {
r = context.getResources();
}
setRawMinTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()));
return this;
}
private void setRawMinTextSize(
float size) {
if (size != mMinTextSize) {
mMinTextSize = size;
autofit();
}
}
/**
* Returns the maximum size (in pixels) of the text.
*/
public float getMaxTextSize() {
return mMaxTextSize;
}
/**
* Set the maximum text size to the given value, interpreted as "scaled pixel" units. This size
* is adjusted based on the current density and user font size preference.
*
* @param size The scaled pixel size.
*
* @attr ref android.R.styleable#TextView_textSize
*/
public AutofitHelper
setMaxTextSize(
float size) {
return setMaxTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}
/**
* Set the maximum text size to a given unit and value. See TypedValue for the possible
* dimension units.
*
* @param unit The desired dimension unit.
* @param size The desired size in the given units.
*
* @attr ref android.R.styleable#TextView_textSize
*/
public AutofitHelper
setMaxTextSize(
int unit,
float size) {
Context context = mTextView.getContext();
Resources r = Resources.getSystem();
if (context !=
null) {
r = context.getResources();
}
setRawMaxTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()));
return this;
}
private void setRawMaxTextSize(
float size) {
if (size != mMaxTextSize) {
mMaxTextSize = size;
autofit();
}
}
/**
* @see TextView#getMaxLines()
*/
public int getMaxLines() {
return mMaxLines;
}
/**
* @see TextView#setMaxLines(int)
*/
public AutofitHelper
setMaxLines(
int lines) {
if (mMaxLines != lines) {
mMaxLines = lines;
autofit();
}
return this;
}
/**
* Returns whether or not automatically resizing text is enabled.
*/
public boolean isEnabled() {
return mEnabled;
}
/**
* Set the enabled state of automatically resizing text.
*/
public AutofitHelper
setEnabled(
boolean enabled) {
if (mEnabled != enabled) {
mEnabled = enabled;
if (enabled) {
mTextView.addTextChangedListener(mTextWatcher);
mTextView.addOnLayoutChangeListener(mOnLayoutChangeListener);
autofit();
}
else {
mTextView.removeTextChangedListener(mTextWatcher);
mTextView.removeOnLayoutChangeListener(mOnLayoutChangeListener);
mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
}
}
return this;
}
/**
* Returns the original text size of the View.
*
* @see TextView#getTextSize()
*/
public float getTextSize() {
return mTextSize;
}
/**
* 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) {
return;
}
Context context = mTextView.getContext();
Resources r = Resources.getSystem();
if (context !=
null) {
r = context.getResources();
}
setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()));
}
private void setRawTextSize(
float size) {
if (mTextSize != size) {
mTextSize = size;
}
}
private void autofit() {
float oldTextSize = mTextView.getTextSize();
float textSize;
mIsAutofitting =
true;
autofit(mTextView, mPaint, mMinTextSize, mMaxTextSize, mMaxLines, mPrecision);
mIsAutofitting =
false;
textSize = mTextView.getTextSize();
if (textSize != oldTextSize) {
sendTextSizeChange(textSize, oldTextSize);
}
}
private void sendTextSizeChange(
float textSize,
float oldTextSize) {
if (mListeners ==
null) {
return;
}
for (OnTextSizeChangeListener listener : mListeners) {
listener.onTextSizeChange(textSize, oldTextSize);
}
}
private class AutofitTextWatcher implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence charSequence,
int start,
int count,
int after) {
}
@Override
public void onTextChanged(CharSequence charSequence,
int start,
int before,
int count) {
autofit();
}
@Override
public void afterTextChanged(Editable editable) {
}
}
private class AutofitOnLayoutChangeListener implements View.OnLayoutChangeListener {
@Override
public void onLayoutChange(View view,
int left,
int top,
int right,
int bottom,
int oldLeft,
int oldTop,
int oldRight,
int oldBottom) {
autofit();
}
}
/**
* When an object of a type is attached to an {@code AutofitHelper}, its methods will be called
* when the {@code textSize} is changed.
*/
public interface OnTextSizeChangeListener {
/**
* This method is called to notify you that the size of the text has changed to
* {@code textSize} from {@code oldTextSize}.
*/
public void onTextSizeChange(
float textSize,
float oldTextSize);
}
}
.xml中使用
<
***.***.***.AutofitTextView
android:id=
"@+id/tv_reachedSalesAmount"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"15dp"
android:layout_marginRight=
"5dp"
android:layout_marginTop=
"20dp"
android:layout_toLeftOf=
"@+id/tv_percentAmount"
android:
gravity=
"bottom"
android:singleLine=
"true"
android:
text=
"0"
android:textColor=
"@color/white"
android:textSize=
"30sp"
app:sizeToFit=
"true" />
这里设置app:sizeToFit= “true”和初始字体大小就行了 Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性
void setRealText(
String doneCount,
String anountUnit,TextView textView, int
tag) {
if (doneCount
== null || "".equals(doneCount))
doneCount
= "0";
String amountDone
= "0";
if (
tag == 1) {
amountDone
= StringUtils
.formatAmount(doneCount);
}
else if (
tag == 2) {
amountDone
= StringUtils
.formatCount(doneCount);
}
String amountStr
= amountDone
+ anountUnit;
textView
.setText(amountStr);
float amountTxtPxSize
= textView
.getTextSize();
SpannableString spannableString
= new SpannableString(amountStr);
spannableString
.setSpan(
new AbsoluteSizeSpan((int) (amountTxtPxSize
/ 1.8)), amountDone
.length(), spannableString
.length(), Spanned
.SPAN_EXCLUSIVE_INCLUSIVE);
textView
.setText(spannableString);
}
此文章为转载,感觉很好,主要目的方便自己用