Android Open Source - Ocypode Auto Resize Text View






From Project

Back to project page Ocypode.

License

The source code is released under:

MIT License

If you think the Android project Ocypode listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.ocypode.component.view.textview;
//  w  w  w. j a  va 2s.co m
/**
 *               DO WHAT YOU WANT TO PUBLIC LICENSE
 *                    Version 2, December 2004
 * 
 * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
 * 
 * Everyone is permitted to copy and distribute verbatim or modified
 * copies of this license document, and changing it is allowed as long
 * as the name is changed.
 * 
 *            DO WHAT YOU WANT TO PUBLIC LICENSE
 *   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 * 
 *  0. You just DO WHAT YOU WANT TO.
 */

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;

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() - getPaddingBottom()
        - getPaddingTop();
    mWidthLimit = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
    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();
    }
  }
}




Java Source Code List

com.ocypode.BuildConfig.java
com.ocypode.BuildConfig.java
com.ocypode.activity.IResultCallbackActivity.java
com.ocypode.activity.robo.AbstractRoboActivity.java
com.ocypode.activity.robo.AbstractRoboFragmentActivity.java
com.ocypode.activity.robo.fragment.AbstractRoboFragment.java
com.ocypode.bluetooth.BluetoothHelper.java
com.ocypode.component.Typefaced.java
com.ocypode.component.animation.AnimationCallbackListener.java
com.ocypode.component.delegate.IStartActivityDelegate.java
com.ocypode.component.delegate.StartActivityDelegate.java
com.ocypode.component.delegate.adaptor.IStartActivityAdaptor.java
com.ocypode.component.delegate.adaptor.StartActivityAdaptor.java
com.ocypode.component.delegate.adaptor.StartFragmentAdaptor.java
com.ocypode.component.view.button.TypefacedButton.java
com.ocypode.component.view.dialog.AlertDialogBuilder.java
com.ocypode.component.view.dialog.ProgressDialogBuilder.java
com.ocypode.component.view.dialog.titledescription.TitleDescriptionArrayAdapter.java
com.ocypode.component.view.dialog.titledescription.TitleDescriptionModel.java
com.ocypode.component.view.edittext.TypefacedEditText.java
com.ocypode.component.view.imageview.CircleImageView.java
com.ocypode.component.view.listview.LockableListView.java
com.ocypode.component.view.scrollview.LockableScrollView.java
com.ocypode.component.view.textview.AutoResizeTextView.java
com.ocypode.component.view.textview.TypefacedTextView.java
com.ocypode.repository.AbstractRepository.java
com.ocypode.utility.ICallback.java
com.ocypode.utility.Logcat.java
com.ocypode.utility.Utility.java
com.ocypode.utility.bitmap.BitmapUtil.java
com.ocypode.utility.formatter.CurrencyFormatter.java
com.ocypode.utility.formatter.DateFormatter.java
com.ocypode.utility.formatter.NumberFormatter.java
com.ocypode.utility.validation.StringValidation.java
com.ocypode.widgets.list.OCListView.java