Почему ChipGroup внутри HorizontalScrollView с полем ChipEnd не работает?

1

У меня есть Chips внутри ChipGroup и эта ChipGroup внутри HorizontalScrollView. Но моя проблема - marginEnd на последнем чипе не работает!

Я пытался изменить параметры макета программно, но не успешно

<HorizontalScrollView
    android:id="@+id/chips_container"
    android:layout_width="0dp"
    android:layout_height="56dp"
    android:layout_gravity="center_vertical"
    android:visibility="gone"
    app:layout_constraintBottom_toTopOf="@+id/dividerSmartReplies"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    tools:visibility="visible">

    <com.google.android.material.chip.ChipGroup
        android:id="@+id/chip_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        app:chipSpacing="8dp"
        app:singleLine="true"
        app:singleSelection="true">

        <com.google.android.material.chip.Chip
            style="@style/Widget.MaterialComponents.Chip.Choice"
            android:layout_width="wrap_content"
            android:layout_height="42dp"
            android:layout_marginStart="8dp"
            android:textColor="@color/selector_smart_reply_chip_text"
            app:checkedIconVisible="false"
            app:chipBackgroundColor="@color/selector_smart_reply_chip"
            app:chipCornerRadius="21dp"
            app:chipStrokeColor="@color/app_base_blue"
            app:chipStrokeWidth="1dp" />

        <com.google.android.material.chip.Chip
            style="@style/Widget.MaterialComponents.Chip.Choice"
            android:layout_width="wrap_content"
            android:layout_height="42dp"
            android:textColor="@color/selector_smart_reply_chip_text"
            app:checkedIconVisible="false"
            app:chipBackgroundColor="@color/selector_smart_reply_chip"
            app:chipCornerRadius="21dp"
            app:chipStrokeColor="@color/app_base_blue"
            app:chipStrokeWidth="1dp" />

        <com.google.android.material.chip.Chip
            style="@style/Widget.MaterialComponents.Chip.Choice"
            android:layout_width="wrap_content"
            android:layout_height="42dp"
            android:textColor="@color/selector_smart_reply_chip_text"
            app:checkedIconVisible="false"
            app:chipBackgroundColor="@color/selector_smart_reply_chip"
            app:chipCornerRadius="21dp"
            app:chipStrokeColor="@color/app_base_blue"
            app:chipStrokeWidth="1dp" />

        <com.google.android.material.chip.Chip
            style="@style/Widget.MaterialComponents.Chip.Choice"
            android:layout_width="wrap_content"
            android:layout_height="42dp"
            android:layout_marginEnd="8dp"
            android:textColor="@color/selector_smart_reply_chip_text"
            app:checkedIconVisible="false"
            app:chipBackgroundColor="@color/selector_smart_reply_chip"
            app:chipCornerRadius="21dp"
            app:chipStrokeColor="@color/app_base_blue"
            app:chipStrokeWidth="1dp" />
    </com.google.android.material.chip.ChipGroup>

</HorizontalScrollView>

Мне нужно дополнительное место после последнего чипа. Обработка ChipGroup работала, но не ожидала результата пользовательского интерфейса.

Теги:
horizontalscrollview
margin

2 ответа

0
Лучший ответ

Я понял эту проблему! ChipGroup расширяет FlowLayout. FlowLayout в методе onMeasure() не учитывает marginRight от последнего дочернего элемента до finalWidth.
Мое окончательное решение:

class SmartRepliesGroup @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
    defStyle: Int = 0
) : ChipGroup(context, attributeSet, defStyle) {

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val maxWidth =
            if (widthMode != -2147483648 && widthMode != 1073741824) 2147483647 else width
        var childLeft = this.paddingLeft
        var childTop = this.paddingTop
        var childBottom = childTop
        var maxChildRight = 0
        val maxRight = maxWidth - this.paddingRight

        var finalWidth = 0
        var lastChildMarginRight = 0
        while (finalWidth < this.childCount) {
            val child = this.getChildAt(finalWidth)
            if (child.visibility != 8) {
                this.measureChild(child, widthMeasureSpec, heightMeasureSpec)
                val lp = child.layoutParams
                var leftMargin = 0
                var rightMargin = 0
                if (lp is MarginLayoutParams) {
                    leftMargin += lp.leftMargin
                    rightMargin += lp.rightMargin
                    lastChildMarginRight = rightMargin
                }

                var childRight = childLeft + leftMargin + child.measuredWidth
                if (childRight > maxRight && !this.isSingleLine) {
                    childLeft = this.paddingLeft
                    childTop = childBottom + this.lineSpacing
                }

                childRight = childLeft + leftMargin + child.measuredWidth
                childBottom = childTop + child.measuredHeight
                if (childRight > maxChildRight) {
                    maxChildRight = childRight
                }

                childLeft += leftMargin + rightMargin + child.measuredWidth + this.itemSpacing
            }
            ++finalWidth
        }

        finalWidth =
            getMeasuredDimension(width, widthMode, maxChildRight + lastChildMarginRight)
        val finalHeight = getMeasuredDimension(height, heightMode, childBottom)
        this.setMeasuredDimension(finalWidth, finalHeight)
    }

    private fun getMeasuredDimension(size: Int, mode: Int, childrenEdge: Int): Int =
        when (mode) {
            -2147483648 -> Math.min(childrenEdge, size)
            1073741824 -> size
            else -> childrenEdge
        }
}
  • 0
    В идеале, мы бы добавили улучшенный код (строки) в официальную реализацию ChipGroup, так что в этом не было бы необходимости. Тем более, что этот ответ не содержит констант, только необработанные целые числа.
  • 0
    На самом деле, это не работает для меня. Последний чип не имеет правильного поля. Правильно ли я понимаю: в моем представлении SmartRepliesGroup я, например, добавляю свойство marginEnd . Последний чип внутри этой группы должен получить маржу, примененную родителем?
Показать ещё 1 комментарий
0

Эй, я знаю, что уже немного поздно, и я рад, что вы нашли ответ, который работает для вас. Однако я думаю, что у меня есть лучшее решение:

  • Добавьте начальный и конечный отступ 8dp к вашему HorizontalScrollView
  • Сделать clipToPadding ложным

Вот как должен выглядеть ваш HorizontalScrollView:

    <HorizontalScrollView
        android:id="@+id/chips_container"
        android:layout_width="0dp"
        android:layout_height="56dp"
        android:layout_gravity="center_vertical"
        android:visibility="gone"
        app:layout_constraintBottom_toTopOf="@+id/dividerSmartReplies"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:visibility="visible"

        android:paddingStart="8dp"
        android:paddingEnd="8dp"
        android:clipToPadding="false"
>

И вы можете удалить поля как на первом, так и на последнем чипе!

  • 0
    Здравствуй! С вашим решением полоса прокрутки имеет вставки, поэтому в моем случае это не применимо. i.imgur.com/1zA0Zzd.png

Ещё вопросы

Сообщество Overcoder
Наверх
Меню