Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

parentWidth returns the wrong value when display size is the largest?

I extend com.google.android.material.chip.Chip

I have a text which I measure while in onMeasure.

My calculation says the text can fit in the chip's space, but in reality I see the text is truncated.

I would expect no truncation, as I measure before layout pass.

*I use the biggest display size, largest font size, Ukraine fonts.

Should I change my measurement code somehow?

  private String getLongestPossibleChipText(int textMaxWidth) {

final MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
final View parent = (View) getParent();
final int parentPaddingLeft = parent.getPaddingLeft();
final int parentPaddingRight = parent.getPaddingRight();
final int paddingLeft = getPaddingLeft();
final int paddingRight = getPaddingRight();
final int leftMargin = layoutParams.leftMargin;
final int rightMargin = layoutParams.rightMargin;

final int currentTextMaxWidth =
    parentWidth
        - (parentPaddingLeft
            + parentPaddingRight
            + paddingLeft
            + paddingRight
            + leftMargin
            + rightMargin);


    final TextPaint paint = getPaint();
    for (String chipText : chipTexts) {
      if (paint.measureText(chipText) <= currentTextMaxWidth) {
        return chipText;
      }
    }
    return Iterables.getLast(chipTexts);
  }
like image 314
Elad Benda Avatar asked Apr 09 '26 16:04

Elad Benda


1 Answers

I don't think that the text length is being computed correctly. From the documentation for ChipDrawable there is some internal structure to Chip that I don't think the code is accounting for. (Chip is a wrapper for ChipDrawable.) I will reproduce the diagram here:

enter image description here

It could be that the internal padding is all zero, so it won't matter. Nonetheless, the calculateTextBounds() method from ChipDrawable might be a good starting point.


The following code should compute the text space available within a Chip correctly and pick the string with the best fit. The candidates array must be sorted in ascending order by string length. Under certain circumstances, another character may look like it would fit but it is the character spacing (which is part of the character) that isn't fitting. If this is a problem, it may be possible to get a better-looking fit by using Paint#getTextBounds().

private fun findBestFitForChip(chip: Chip, candidates: Array<String>): String {
    val parent = chip.parent as ViewGroup
    val maxChipWidth =
        if (chip.layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
            parent.width - parent.paddingStart - parent.paddingEnd - chip.marginStart - chip.marginEnd
        } else {
            chip.width
        }
    val chipSizeLessText =
        with(chip) {
            // Keep the parentheses
            (chipStartPadding
                    + iconStartPadding
                    + chipIconSize
                    + iconEndPadding
                    + textStartPadding
                    + textEndPadding
                    + closeIconStartPadding
                    + closeIconSize
                    + closeIconEndPadding
                    + chipEndPadding)
        }
    val currentTextMaxWidth = maxChipWidth - chipSizeLessText

    val paint: TextPaint = chip.paint
    var result = ""
    for (i in (candidates.size - 1) downTo 0) {
        if (paint.measureText(candidates[i]) <= currentTextMaxWidth) {
            result = candidates[i]
            break
        }
    }
    return result
}
like image 53
Cheticamp Avatar answered Apr 11 '26 06:04

Cheticamp