aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/AndroidBootstrap/src/com/beardedhen/androidbootstrap/utils/AutoResizeTextView.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/AndroidBootstrap/src/com/beardedhen/androidbootstrap/utils/AutoResizeTextView.java')
-rw-r--r--libraries/AndroidBootstrap/src/com/beardedhen/androidbootstrap/utils/AutoResizeTextView.java303
1 files changed, 303 insertions, 0 deletions
diff --git a/libraries/AndroidBootstrap/src/com/beardedhen/androidbootstrap/utils/AutoResizeTextView.java b/libraries/AndroidBootstrap/src/com/beardedhen/androidbootstrap/utils/AutoResizeTextView.java
new file mode 100644
index 000000000..be6f328d3
--- /dev/null
+++ b/libraries/AndroidBootstrap/src/com/beardedhen/androidbootstrap/utils/AutoResizeTextView.java
@@ -0,0 +1,303 @@
+package com.beardedhen.androidbootstrap.utils;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.RectF;
+import android.os.Build;
+import android.text.Layout.Alignment;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.util.AttributeSet;
+import android.util.SparseIntArray;
+import android.util.TypedValue;
+import android.widget.TextView;
+
+/**
+ *
+ * Code from user M-WaJeEh on StackOverflow at
+ * http://stackoverflow.com/questions/5033012/auto-scale-textview-text-to-fit-within-bounds/17782522#17782522
+ *
+ */
+
+public class AutoResizeTextView extends TextView {
+private interface SizeTester {
+ /**
+ *
+ * @param suggestedSize
+ * Size of text to be tested
+ * @param availableSpace
+ * available space in which text must fit
+ * @return an integer < 0 if after applying {@code suggestedSize} to
+ * text, it takes less space than {@code availableSpace}, > 0
+ * otherwise
+ */
+ public int onTestSize(int suggestedSize, RectF availableSpace);
+}
+
+private RectF mTextRect = new RectF();
+
+private RectF mAvailableSpaceRect;
+
+private SparseIntArray mTextCachedSizes;
+
+private TextPaint mPaint;
+
+private float mMaxTextSize;
+
+private float mSpacingMult = 1.0f;
+
+private float mSpacingAdd = 0.0f;
+
+private float mMinTextSize = 20;
+
+private int mWidthLimit;
+
+private static final int NO_LINE_LIMIT = -1;
+private int mMaxLines;
+
+private boolean mEnableSizeCache = true;
+private boolean mInitiallized;
+
+public AutoResizeTextView(Context context) {
+ super(context);
+ initialize();
+}
+
+public AutoResizeTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initialize();
+}
+
+public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initialize();
+}
+
+private void initialize() {
+ mPaint = new TextPaint(getPaint());
+ mMaxTextSize = getTextSize();
+ mAvailableSpaceRect = new RectF();
+ mTextCachedSizes = new SparseIntArray();
+ if (mMaxLines == 0) {
+ // no value was assigned during construction
+ mMaxLines = NO_LINE_LIMIT;
+ }
+ mInitiallized = true;
+}
+
+@Override
+public void setText(final CharSequence text, BufferType type) {
+ super.setText(text, type);
+ adjustTextSize(text.toString());
+}
+
+@Override
+public void setTextSize(float size) {
+ mMaxTextSize = size;
+ mTextCachedSizes.clear();
+ adjustTextSize(getText().toString());
+}
+
+@Override
+public void setMaxLines(int maxlines) {
+ super.setMaxLines(maxlines);
+ mMaxLines = maxlines;
+ reAdjust();
+}
+
+public int getMaxLines() {
+ return mMaxLines;
+}
+
+@Override
+public void setSingleLine() {
+ super.setSingleLine();
+ mMaxLines = 1;
+ reAdjust();
+}
+
+@Override
+public void setSingleLine(boolean singleLine) {
+ super.setSingleLine(singleLine);
+ if (singleLine) {
+ mMaxLines = 1;
+ } else {
+ mMaxLines = NO_LINE_LIMIT;
+ }
+ reAdjust();
+}
+
+@Override
+public void setLines(int lines) {
+ super.setLines(lines);
+ mMaxLines = lines;
+ reAdjust();
+}
+
+@Override
+public void setTextSize(int unit, float size) {
+ Context c = getContext();
+ Resources r;
+
+ if (c == null)
+ r = Resources.getSystem();
+ else
+ r = c.getResources();
+ mMaxTextSize = TypedValue.applyDimension(unit, size,
+ r.getDisplayMetrics());
+ mTextCachedSizes.clear();
+ adjustTextSize(getText().toString());
+}
+
+@Override
+public void setLineSpacing(float add, float mult) {
+ super.setLineSpacing(add, mult);
+ mSpacingMult = mult;
+ mSpacingAdd = add;
+}
+
+/**
+ * Set the lower text size limit and invalidate the view
+ *
+ * @param minTextSize
+ */
+public void setMinTextSize(float minTextSize) {
+ mMinTextSize = minTextSize;
+ reAdjust();
+}
+
+private void reAdjust() {
+ adjustTextSize(getText().toString());
+}
+
+private void adjustTextSize(String string) {
+ if (!mInitiallized) {
+ return;
+ }
+ int startSize = (int) mMinTextSize;
+ int heightLimit = getMeasuredHeight() - getCompoundPaddingBottom()
+ - getCompoundPaddingTop();
+ mWidthLimit = getMeasuredWidth() - getCompoundPaddingLeft()
+ - getCompoundPaddingRight();
+ mAvailableSpaceRect.right = mWidthLimit;
+ mAvailableSpaceRect.bottom = heightLimit;
+ super.setTextSize(
+ TypedValue.COMPLEX_UNIT_PX,
+ efficientTextSizeSearch(startSize, (int) mMaxTextSize,
+ mSizeTester, mAvailableSpaceRect));
+}
+
+private final SizeTester mSizeTester = new SizeTester() {
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ @Override
+ public int onTestSize(int suggestedSize, RectF availableSPace) {
+ mPaint.setTextSize(suggestedSize);
+ String text = getText().toString();
+ boolean singleline = getMaxLines() == 1;
+ if (singleline) {
+ mTextRect.bottom = mPaint.getFontSpacing();
+ mTextRect.right = mPaint.measureText(text);
+ } else {
+ StaticLayout layout = new StaticLayout(text, mPaint,
+ mWidthLimit, Alignment.ALIGN_NORMAL, mSpacingMult,
+ mSpacingAdd, true);
+ // return early if we have more lines
+ if (getMaxLines() != NO_LINE_LIMIT
+ && layout.getLineCount() > getMaxLines()) {
+ return 1;
+ }
+ mTextRect.bottom = layout.getHeight();
+ int maxWidth = -1;
+ for (int i = 0; i < layout.getLineCount(); i++) {
+ if (maxWidth < layout.getLineWidth(i)) {
+ maxWidth = (int) layout.getLineWidth(i);
+ }
+ }
+ mTextRect.right = maxWidth;
+ }
+
+ mTextRect.offsetTo(0, 0);
+ if (availableSPace.contains(mTextRect)) {
+ // may be too small, don't worry we will find the best match
+ return -1;
+ } else {
+ // too big
+ return 1;
+ }
+ }
+};
+
+/**
+ * Enables or disables size caching, enabling it will improve performance
+ * where you are animating a value inside TextView. This stores the font
+ * size against getText().length() Be careful though while enabling it as 0
+ * takes more space than 1 on some fonts and so on.
+ *
+ * @param enable
+ * enable font size caching
+ */
+public void enableSizeCache(boolean enable) {
+ mEnableSizeCache = enable;
+ mTextCachedSizes.clear();
+ adjustTextSize(getText().toString());
+}
+
+private int efficientTextSizeSearch(int start, int end,
+ SizeTester sizeTester, RectF availableSpace) {
+ if (!mEnableSizeCache) {
+ return binarySearch(start, end, sizeTester, availableSpace);
+ }
+ String text = getText().toString();
+ int key = text == null ? 0 : text.length();
+ int size = mTextCachedSizes.get(key);
+ if (size != 0) {
+ return size;
+ }
+ size = binarySearch(start, end, sizeTester, availableSpace);
+ mTextCachedSizes.put(key, size);
+ return size;
+}
+
+private static int binarySearch(int start, int end, SizeTester sizeTester,
+ RectF availableSpace) {
+ int lastBest = start;
+ int lo = start;
+ int hi = end - 1;
+ int mid = 0;
+ while (lo <= hi) {
+ mid = (lo + hi) >>> 1;
+ int midValCmp = sizeTester.onTestSize(mid, availableSpace);
+ if (midValCmp < 0) {
+ lastBest = lo;
+ lo = mid + 1;
+ } else if (midValCmp > 0) {
+ hi = mid - 1;
+ lastBest = hi;
+ } else {
+ return mid;
+ }
+ }
+ // make sure to return last best
+ // this is what should always be returned
+ return lastBest;
+
+}
+
+@Override
+protected void onTextChanged(final CharSequence text, final int start,
+ final int before, final int after) {
+ super.onTextChanged(text, start, before, after);
+ reAdjust();
+}
+
+@Override
+protected void onSizeChanged(int width, int height, int oldwidth,
+ int oldheight) {
+ mTextCachedSizes.clear();
+ super.onSizeChanged(width, height, oldwidth, oldheight);
+ if (width != oldwidth || height != oldheight) {
+ reAdjust();
+ }
+}
+}