package com.greenaddress.greenbits.ui; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Paint; import android.util.AttributeSet; import android.util.TypedValue; public class FontFitEditText extends android.support.v7.widget.AppCompatEditText { //Attributes private Paint mTestPaint; private float mTextSizeMax; private float mTextSizeMin; public FontFitEditText(final Context context) { super(context); initialise(); } public FontFitEditText(final Context context, final AttributeSet attrs) { super(context, attrs); final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FontFitEditText); mTextSizeMax = typedArray.getDimensionPixelSize(R.styleable.FontFitEditText_textSizeMax, 0); mTextSizeMax = pxToDp(mTextSizeMax); mTextSizeMin = typedArray.getDimensionPixelSize(R.styleable.FontFitEditText_textSizeMin, 0); typedArray.recycle(); mTextSizeMin = pxToDp(mTextSizeMin); initialise(); } private void initialise() { mTestPaint = new Paint(); mTestPaint.set(this.getPaint()); //max size defaults to the initially specified text size unless it is too small } private float getScale() { return (getResources().getDisplayMetrics().densityDpi / 160); } private float pxToDp(final float px) { return px / getScale(); } private float dpiToPx(final float px) { return px * getScale(); } /* Re size the font so the specified text fits in the text box * assuming the text box is the specified width. */ private void refitText(final String text, final int textWidth) { if (textWidth <= 0) return; int targetWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight(); targetWidth = (int)pxToDp(targetWidth); // font size in dp float hi = (mTextSizeMax > 0 && mTextSizeMax > mTextSizeMin) ? mTextSizeMax : 28; float lo = (mTextSizeMin > 0 && mTextSizeMin < hi) ? mTextSizeMin : 16; final float threshold = 0.5f; // How close we have to be mTestPaint.set(this.getPaint()); while ((hi - lo) > threshold) { final float sizeDpi = (hi + lo) / 2; final float sizePx = dpiToPx(sizeDpi); mTestPaint.setTextSize(sizePx); if (pxToDp(mTestPaint.measureText(text)) >= targetWidth) hi = sizeDpi; // too big else lo = sizeDpi; // too small } // Use lo so that we undershoot rather than overshoot this.setTextSize(TypedValue.COMPLEX_UNIT_DIP, lo); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int parentWidth = MeasureSpec.getSize(widthMeasureSpec); final int height = getMeasuredHeight(); refitText(UI.getText(this), parentWidth); 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()); } @Override protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { if (w != oldw) refitText(UI.getText(this), w); } }