Skip to content

Instantly share code, notes, and snippets.

@fhur
Last active August 29, 2015 14:06
Show Gist options
  • Save fhur/d048e325aee76216c096 to your computer and use it in GitHub Desktop.
Save fhur/d048e325aee76216c096 to your computer and use it in GitHub Desktop.
TextView that automatically adjusts it's size to fit the container.
/**
* @author fernandohur but credit goes to <a href="http://stackoverflow.com/questions/2617266/how-to-adjust-text-font-size-to-fit-textview">speedplane</a>
*/
public class FontFitTextView extends TextView {
private Paint mTestPaint;
/**
* The minimum font size in pixels
*/
private float minFontSize;
public FontFitTextView(Context context) {
super(context);
initialise();
}
public FontFitTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initialise();
}
/**
* Sets the minimum allowed font size
* @param fontSizeDp the font size in dp
*/
public void setMinFontSize(int fontSizeDp){
minFontSize = UIHelper.getPixelsFromDp(getContext().getResources(), fontSizeDp);
}
private void initialise() {
mTestPaint = new Paint();
mTestPaint.set(this.getPaint());
//max size defaults to the initially specified text size unless it is too small
minFontSize = 0;
}
/* 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 parentHeight) {
if (textWidth <= 0)
return;
int targetWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight();
float hi = 100;
float lo = 2;
final float threshold = 0.5f; // How close we have to be
mTestPaint.set(this.getPaint());
while ((hi - lo) > threshold) {
float size = (hi + lo) / 2;
mTestPaint.setTextSize(size);
if (mTestPaint.measureText(text) >= targetWidth)
hi = size; // too big
else
lo = size; // too small
}
// Use lo so that we undershoot rather than overshoot
Resources r = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, r.getDisplayMetrics());
this.setTextSize(TypedValue.COMPLEX_UNIT_PX, Math.max(Math.min(lo, px), minFontSize));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int height = getMeasuredHeight();
refitText(this.getText().toString(), parentWidth, parentHeight);
this.setMeasuredDimension(parentWidth, height);
}
@Override
protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) {
refitText(text.toString(), this.getWidth(), this.getHeight());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw) {
refitText(this.getText().toString(), w, h);
}
}
}
@fhur
Copy link
Author

fhur commented Sep 17, 2014

The UIHelper method is just this

public static float getPixelsFromDp(Resources resources, int dp) {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics());
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment