Exemplo n.º 1
0
  /**
   * Computes the maximum font size which makes the TextView's (possibly multi-line) text fit in the
   * bounding box defined by the viewWidth and viewHeight parameters, always within the range
   * ({@link #MIN_TEXT_SIZE}, {@link #MAX_TEXT_SIZE}) but taking into account any predetermined font
   * size constraints that come from the font size coordinator (if present).
   *
   * @param viewWidth the width of the View into which the text will be drawn (including padding)
   * @param viewHeight the height of the View into which the text will be drawn (including padding)
   * @param force whether or not to force a recalculation of font size (this could otherwise be
   *     avoided
   */
  private void fitText(int viewWidth, int viewHeight, boolean force) {
    // Avoid unnecessary (re)fitting: 0 or negative view dimensions
    if (viewWidth <= 0 || viewHeight <= 0) return;

    // Avoid unnecessary (re)fitting: text is empty
    if (text == null || text.isEmpty()) return;

    // Compute the target text width/height as the provided container width minus relevant padding
    int targetWidth = viewWidth - this.getPaddingLeft() - this.getPaddingRight();
    int targetHeight = viewHeight - this.getPaddingBottom() - this.getPaddingTop();

    // Avoid unnecessary (re)fitting: no forcing and target dimensions are the same as last time
    if (!force && targetWidth == lastTargetWidth && targetHeight == lastTargetHeight) return;

    // At this point we know a new size computation will take place...

    // Log.d("TFV", "fitText: IS REFITTING, text: " + this.getText() + ", hash: " + hashCode() + "
    // w=" + viewWidth + ", h=" + viewHeight + ", forced: " + force);

    // Initialise lo & hi bounds:
    float lo = MIN_TEXT_SIZE;
    float hi = (coordinator == null) ? MAX_TEXT_SIZE : coordinator.getCoordinatedTextSize();

    // See if we can use the "hi" instead of iterating (if "hi" fits then iterating will only get us
    // back to a value marginally smaller than "hi"):
    float textSize = hi;

    // Only iterate if "hi" was too big:
    if (!textFits(textSize, targetWidth, targetHeight)) {
      // Fitting loop (binary search):
      while ((hi - lo) > THRESHOLD) {
        textSize = (hi + lo) / 2;

        // See if our text fits
        if (textFits(textSize, targetWidth, targetHeight))
          lo = textSize; // was too small, so increase lo
        else hi = textSize; // was too big, so reduce hi
      }

      // We set lo as the new textSize, so that we undershoot rather than overshoot:
      textSize = lo;
    }

    // Log.d("TFV", "final textSize for slot " + coordinatorSlot + ": " + textSize);

    // Remember target dimensions:
    lastTargetWidth = targetWidth;
    lastTargetHeight = targetHeight;

    // Set new textSize:
    this.setTextSizePx(
        textSize,
        coordinator
            == null); // if there is a coordinate the new size is not applied immediately but at a
                      // later time determined by the coordinator

    // Inform coordinator if there is one:
    if (coordinator != null) coordinator.updated(this);
  }
Exemplo n.º 2
0
  /**
   * @param context
   * @param coordinator
   * @param coordinatorSlot
   */
  public TextFitView(Context context, TextSizeCoordinator coordinator, int coordinatorSlot) {
    super(context);

    this.coordinator = coordinator;
    // Set or claim coordinator slot:
    this.coordinatorSlot =
        coordinator != null
            ? (coordinatorSlot >= 0 ? coordinatorSlot : coordinator.claimSlot(this))
            : UNASSIGNED_SLOT;

    // Initialise paint:
    paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
    paint.setAntiAlias(true); // text looks pixellated otherwise
    paint.setColor(DEFAULT_TEXT_COLOR);
    paint.setTextSize(textSizePx);
  }