/* * Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner, * Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain, * Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter, * Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann, * Samuel Zweifel * * This file is part of Jukefox. * * Jukefox is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or any later version. Jukefox is * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Jukefox. If not, see <http://www.gnu.org/licenses/>. */ package ch.ethz.dcg.pancho3.tablet.widget; import android.content.Context; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.util.TypedValue; import android.widget.TextView; public class FontFitTextView extends TextView { // Attributes private Paint mTestPaint; public FontFitTextView(Context context) { super(context); setSingleLine(true); initialise(); } public FontFitTextView(Context context, AttributeSet attrs) { super(context, attrs); 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 } /* * 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 textHeight) { if (textWidth <= 0) { return; } int targetWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight(); int targetHeight = textHeight - this.getPaddingTop() - this.getPaddingBottom(); 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); Rect rect = new Rect(); mTestPaint.getTextBounds(text, 0, text.length(), rect); if (Math.abs(rect.width()) >= targetWidth || Math.abs(rect.height()) >= targetHeight) { hi = size; // too big } else { lo = size; // too small } } // Use lo so that we undershoot rather than overshoot this.setTextSize(TypedValue.COMPLEX_UNIT_PX, (float) Math.floor(lo)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int parentHeight = MeasureSpec.getSize(heightMeasureSpec); int parentWidth = MeasureSpec.getSize(widthMeasureSpec); refitText(this.getText().toString(), parentWidth, parentHeight); setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight()); } @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 || h != oldh) { refitText(this.getText().toString(), w, h); } } }