android字体颜色自适应,AutoFitTextView(Android textview根据字体长度调整字体大小)...

public classAutofitHelper {

private static finalString TAG= "AutoFitTextHelper";private static final booleanSPEW= false;// Minimum size of the text in pixelsprivate static final intDEFAULT_MIN_TEXT_SIZE= 8;//sp// How precise we want to be when reaching the target textWidth sizeprivate static final floatDEFAULT_PRECISION= 0.5f;/*** Creates a new instance of {@codeAutofitHelper} that wraps a {@linkTextView} and enables* automatically sizing the text to fit.*/public staticAutofitHelper create(TextView view) {

returncreate(view, null,0);}

/*** Creates a new instance of {@codeAutofitHelper} that wraps a {@linkTextView} and enables* automatically sizing the text to fit.*/public staticAutofitHelper create(TextView view,AttributeSet attrs) {

returncreate(view,attrs,0);}

/*** Creates a new instance of {@codeAutofitHelper} that wraps a {@linkTextView} and enables* automatically sizing the text to fit.*/public staticAutofitHelper create(TextView view,AttributeSet attrs, intdefStyle) {

AutofitHelper helper = newAutofitHelper(view);booleansizeToFit = true;if(attrs != null) {

Context context = view.getContext();intminTextSize = (int) helper.getMinTextSize();floatprecision = 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);returnhelper;}

/*** Re-sizes the textSize of the TextView so that the text fits within the bounds of the View.*/private static voidautofit(TextView view,TextPaint paint, floatminTextSize, floatmaxTextSize,intmaxLines, floatprecision) {

if(maxLines <= 0|| maxLines == Integer.MAX_VALUE) {

// Don't auto-size since there's no limit on lines.return;}

inttargetWidth = 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;floatsize = maxTextSize;floathigh = size;floatlow = 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 floatgetAutofitTextSize(CharSequence text,TextPaint paint,floattargetWidth, intmaxLines, floatlow, floathigh, floatprecision,DisplayMetrics displayMetrics) {

floatmid = (low + high) / 2.0f;intlineCount = 1;StaticLayout layout = null;paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,mid,displayMetrics));if(maxLines != 1) {

layout = newStaticLayout(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) {

returnlow;}

returngetAutofitTextSize(text,paint,targetWidth,maxLines,low,mid,precision,displayMetrics);}

else if(lineCount < maxLines) {

returngetAutofitTextSize(text,paint,targetWidth,maxLines,mid,high,precision,displayMetrics);}

else{

floatmaxLineWidth = 0;if(maxLines == 1) {

maxLineWidth = paint.measureText(text,0,text.length());} else{

for(inti = 0;i < lineCount;i++) {

if(layout.getLineWidth(i) > maxLineWidth) {

maxLineWidth = layout.getLineWidth(i);}

}

}

if((high - low) < precision) {

returnlow;} else if(maxLineWidth > targetWidth) {

returngetAutofitTextSize(text,paint,targetWidth,maxLines,low,mid,precision,displayMetrics);} else if(maxLineWidth < targetWidth) {

returngetAutofitTextSize(text,paint,targetWidth,maxLines,mid,high,precision,displayMetrics);} else{

returnmid;}

}

}

private static intgetLineCount(CharSequence text,TextPaint paint, floatsize, floatwidth,DisplayMetrics displayMetrics) {

paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,size,displayMetrics));StaticLayout layout = newStaticLayout(text,paint,(int)width,Layout.Alignment.ALIGN_NORMAL,1.0f,0.0f, true);returnlayout.getLineCount();}

private static intgetMaxLines(TextView view) {

intmaxLines = -1;// No limit (Integer.MAX_VALUE also means no limit)TransformationMethod method = view.getTransformationMethod();if(method != null&& method instanceofSingleLineTransformationMethod) {

maxLines = 1;}

else if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.JELLY_BEAN) {

// setMaxLines() and getMaxLines() are only available on android-16+maxLines = view.getMaxLines();}

returnmaxLines;}

// AttributesprivateTextView mTextView;privateTextPaint mPaint;/*** Original textSize of the TextView.*/private floatmTextSize;private intmMaxLines;private floatmMinTextSize;private floatmMaxTextSize;private floatmPrecision;private booleanmEnabled;private booleanmIsAutofitting;privateArrayList mListeners;privateTextWatcher mTextWatcher= newAutofitTextWatcher();privateView.OnLayoutChangeListener mOnLayoutChangeListener=

newAutofitOnLayoutChangeListener();privateAutofitHelper(TextView view) {

finalContext context = view.getContext();floatscaledDensity = context.getResources().getDisplayMetrics().scaledDensity;mTextView= view;mPaint= newTextPaint();setRawTextSize(view.getTextSize());mMaxLines= getMaxLines(view);mMinTextSize= scaledDensity * DEFAULT_MIN_TEXT_SIZE;mMaxTextSize= mTextSize;mPrecision= DEFAULT_PRECISION;}

/*** Adds an {@linkOnTextSizeChangeListener} to the list of those whose methods are called* whenever the {@linkTextView}'s {@codetextSize} changes.*/publicAutofitHelper addOnTextSizeChangeListener(OnTextSizeChangeListener listener) {

if(mListeners== null) {

mListeners= newArrayList();}

mListeners.add(listener);return this;}

/*** Removes the specified {@linkOnTextSizeChangeListener} from the list of those whose methods* are called whenever the {@linkTextView}'s {@codetextSize} changes.*/publicAutofitHelper 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 floatgetPrecision() {

returnmPrecision;}

/*** 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.**@paramprecisionThe amount of precision.*/publicAutofitHelper setPrecision(floatprecision) {

if(mPrecision!= precision) {

mPrecision= precision;autofit();}

return this;}

/*** Returns the minimum size (in pixels) of the text.*/public floatgetMinTextSize() {

returnmMinTextSize;}

/*** 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.**@paramsizeThe scaled pixel size.**@attrref me.grantland.R.styleable#AutofitTextView_minTextSize*/publicAutofitHelper setMinTextSize(floatsize) {

returnsetMinTextSize(TypedValue.COMPLEX_UNIT_SP,size);}

/*** Set the minimum text size to a given unit and value. See TypedValue for the possible* dimension units.**@paramunitThe desired dimension unit.*@paramsizeThe desired size in the given units.**@attrref me.grantland.R.styleable#AutofitTextView_minTextSize*/publicAutofitHelper setMinTextSize(intunit, floatsize) {

Context context = mTextView.getContext();Resources r = Resources.getSystem();if(context != null) {

r = context.getResources();}

setRawMinTextSize(TypedValue.applyDimension(unit,size,r.getDisplayMetrics()));return this;}

private voidsetRawMinTextSize(floatsize) {

if(size != mMinTextSize) {

mMinTextSize= size;autofit();}

}

/*** Returns the maximum size (in pixels) of the text.*/public floatgetMaxTextSize() {

returnmMaxTextSize;}

/*** 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.**@paramsizeThe scaled pixel size.**@attrref android.R.styleable#TextView_textSize*/publicAutofitHelper setMaxTextSize(floatsize) {

returnsetMaxTextSize(TypedValue.COMPLEX_UNIT_SP,size);}

/*** Set the maximum text size to a given unit and value. See TypedValue for the possible* dimension units.**@paramunitThe desired dimension unit.*@paramsizeThe desired size in the given units.**@attrref android.R.styleable#TextView_textSize*/publicAutofitHelper setMaxTextSize(intunit, floatsize) {

Context context = mTextView.getContext();Resources r = Resources.getSystem();if(context != null) {

r = context.getResources();}

setRawMaxTextSize(TypedValue.applyDimension(unit,size,r.getDisplayMetrics()));return this;}

private voidsetRawMaxTextSize(floatsize) {

if(size != mMaxTextSize) {

mMaxTextSize= size;autofit();}

}

/***@seeTextView#getMaxLines()*/public intgetMaxLines() {

returnmMaxLines;}

/***@seeTextView#setMaxLines(int)*/publicAutofitHelper setMaxLines(intlines) {

if(mMaxLines!= lines) {

mMaxLines= lines;autofit();}

return this;}

/*** Returns whether or not automatically resizing text is enabled.*/public booleanisEnabled() {

returnmEnabled;}

/*** Set the enabled state of automatically resizing text.*/publicAutofitHelper setEnabled(booleanenabled) {

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.**@seeTextView#getTextSize()*/public floatgetTextSize() {

returnmTextSize;}

/*** Set the original text size of the View.**@seeTextView#setTextSize(float)*/public voidsetTextSize(floatsize) {

setTextSize(TypedValue.COMPLEX_UNIT_SP,size);}

/*** Set the original text size of the View.**@seeTextView#setTextSize(int, float)*/public voidsetTextSize(intunit, floatsize) {

if(mIsAutofitting) {

// We don't want to update the TextView's actual textSize while we're autofitting// since it'd get set to the autofitTextSizereturn;}

Context context = mTextView.getContext();Resources r = Resources.getSystem();if(context != null) {

r = context.getResources();}

setRawTextSize(TypedValue.applyDimension(unit,size,r.getDisplayMetrics()));}

private voidsetRawTextSize(floatsize) {

if(mTextSize!= size) {

mTextSize= size;}

}

private voidautofit() {

floatoldTextSize = mTextView.getTextSize();floattextSize;mIsAutofitting= true;autofit(mTextView,mPaint,mMinTextSize,mMaxTextSize,mMaxLines,mPrecision);mIsAutofitting= false;textSize = mTextView.getTextSize();if(textSize != oldTextSize) {

sendTextSizeChange(textSize,oldTextSize);}

}

private voidsendTextSizeChange(floattextSize, floatoldTextSize) {

if(mListeners== null) {

return;}

for(OnTextSizeChangeListener listener : mListeners) {

listener.onTextSizeChange(textSize,oldTextSize);}

}

private classAutofitTextWatcher implementsTextWatcher {

@Overridepublic voidbeforeTextChanged(CharSequence charSequence, intstart, intcount, intafter) {

// do nothing}

@Overridepublic voidonTextChanged(CharSequence charSequence, intstart, intbefore, intcount) {

autofit();}

@Overridepublic voidafterTextChanged(Editable editable) {

// do nothing}

}

private classAutofitOnLayoutChangeListener implementsView.OnLayoutChangeListener {

@Overridepublic voidonLayoutChange(View view, intleft, inttop, intright, intbottom,intoldLeft, intoldTop, intoldRight, intoldBottom) {

autofit();}

}

/*** When an object of a type is attached to an {@codeAutofitHelper}, its methods will be called* when the {@codetextSize} is changed.*/public interfaceOnTextSizeChangeListener {

/*** This method is called to notify you that the size of the text has changed to* {@codetextSize} from {@codeoldTextSize}.*/public voidonTextSizeChange(floattextSize, floatoldTextSize);}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值