45

我怎样才能强制 aChipGroup像 aRadioGroup一样总是至少有一个选定的项目?如果您在 . 上单击两次,设置setSingleSelection(true)还增加了不选择任何内容的可能性Chip

4

7 回答 7

90

为了防止所有芯片被取消选择,您可以使用以下方法setSelectionRequired

chipGroup.setSelectionRequired(true)

您还可以使用app:selectionRequired属性在布局中定义它:

<com.google.android.material.chip.ChipGroup
    app:singleSelection="true"
    app:selectionRequired="true"
    app:checkedChip="@id/..."
    ..>

注意:这需要最低版本1.2.0

于 2019-11-20T06:27:34.687 回答
22

编辑

使用版本不再需要1.2.0-alpha02的hacky 解决方案!

要么使用属性app:selectionRequired="true"


<com.google.android.material.chip.ChipGroup
            android:id="@+id/group"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:selectionRequired="true"
            app:singleSelection="true">

  (...)
</com.google.android.material.chip.ChipGroup>

或者在代码中


// Kotlin
group.isSelectionRequired = true

// Java
group.setSelectionRequired(true);


对于旧版本

有两个步骤可以实现这一点

步骤1

我们内置了此支持,只需确保将其添加app:singleSelection="true"到您的ChipGroup中,例如:

XML

<com.google.android.material.chip.ChipGroup
            android:id="@+id/group"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:singleSelection="true">

        <com.google.android.material.chip.Chip
                android:id="@+id/option_1"
                style="@style/Widget.MaterialComponents.Chip.Choice"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Option 1" />

        <com.google.android.material.chip.Chip
                android:id="@+id/option_2"
                style="@style/Widget.MaterialComponents.Chip.Choice"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Option 2" />
</com.google.android.material.chip.ChipGroup>

代码


// Kotlin
group.isSingleSelection = true

// Java
group.setSingleSelection(true);

第2步

现在支持无线电组之类的功能:


var lastCheckedId = View.NO_ID
chipGroup.setOnCheckedChangeListener { group, checkedId ->
    if(checkedId == View.NO_ID) {
        // User tried to uncheck, make sure to keep the chip checked          
        group.check(lastCheckedId)
        return@setOnCheckedChangeListener
    }
    lastCheckedId = checkedId

    // New selection happened, do your logic here.
    (...)

}

文档

ChipGroup 还支持一组芯片的多重排除范围。当您设置 app:singleSelection 属性时,选中一个属于芯片组的芯片会取消选中同一组中任何先前选中的芯片。该行为反映了 RadioGroup 的行为。

于 2019-07-08T13:42:51.410 回答
15

A solution would be to preset a clicked chip and then toggling the clickable property of the chips:

chipGroup.setOnCheckedChangeListener((chipGroup, id) -> {
    Chip chip = ((Chip) chipGroup.getChildAt(chipGroup.getCheckedChipId()));
    if (chip != null) {
        for (int i = 0; i < chipGroup.getChildCount(); ++i) {
            chipGroup.getChildAt(i).setClickable(true);
        }
        chip.setClickable(false);
    }
});
于 2018-11-05T15:53:35.703 回答
6

@adriennoir 的答案的简要修改(在 Kotlin 中)。谢谢您的帮助!注意getChildAt()需要一个索引。

for (i in 0 until group.childCount) {
    val chip = group.getChildAt(i)
    chip.isClickable = chip.id != group.checkedChipId
}

这是我较大的`setOnCheckedChangeListener,用于上下文:

intervalChipGroup.setOnCheckedChangeListener { group, checkedId ->

    for (i in 0 until group.childCount) {
        val chip = group.getChildAt(i)
        chip.isClickable = chip.id != group.checkedChipId
    }

    when (checkedId) {
        R.id.intervalWeek -> {
            view.findViewById<Chip>(R.id.intervalWeek).chipStrokeWidth = 1F
            view.findViewById<Chip>(R.id.intervalMonth).chipStrokeWidth = 0F
            view.findViewById<Chip>(R.id.intervalYear).chipStrokeWidth = 0F
            currentIntervalSelected = weekInterval
            populateGraph(weekInterval)
        }
        R.id.intervalMonth -> {
            view.findViewById<Chip>(R.id.intervalWeek).chipStrokeWidth = 0F
            view.findViewById<Chip>(R.id.intervalMonth).chipStrokeWidth = 1F
            view.findViewById<Chip>(R.id.intervalYear).chipStrokeWidth = 0F
            currentIntervalSelected = monthInterval
            populateGraph(monthInterval)

        }
        R.id.intervalYear -> {
            view.findViewById<Chip>(R.id.intervalWeek).chipStrokeWidth = 0F
            view.findViewById<Chip>(R.id.intervalMonth).chipStrokeWidth = 0F
            view.findViewById<Chip>(R.id.intervalYear).chipStrokeWidth = 1F
            currentIntervalSelected = yearInterval
            populateGraph(yearInterval)
        }
    }

}
于 2019-01-18T21:39:25.810 回答
4

大多数答案都很棒,对我很有帮助。对@adriennoir 和@Todd DeLand 的另一个细微修改,以防止取消选中setSingleSelection(true)ChipGroup 中已检查的芯片,这是我的解决方案:

for (i in 0 until chipGroup.childCount) {
    val chip = chipGroup.getChildAt(i) as Chip
    chip.isCheckable = chip.id != chipGroup.checkedChipId
    chip.isChecked = chip.id == chipGroup.checkedChipId
}

对我来说,我只需要防止取消选中相同的选中芯片而不使其不可点击。这样,用户仍然可以点击选中的芯片,看到花哨的涟漪效果,什么都不会发生。

于 2019-02-03T21:55:36.340 回答
1

我是这样做的:

var previousSelection: Int = default_selection_id 
chipGroup.setOnCheckedChangeListener { chipGroup, id ->
    if (id == -1) //nothing is selected.
        chipGroup.check(previousSelection)
    else
        previousSelection = id
于 2019-01-24T14:09:13.200 回答
0

这是我的工作解决方案

mChipGroup.setOnCheckedChangeListener((group, checkedId) -> {
            for (int i = 0; i < mChipGroup.getChildCount(); i++) {
                Chip chip = (Chip) mChipGroup.getChildAt(i);
                if (chip != null) {
                    chip.setClickable(!(chip.getId() == mChipGroup.getCheckedChipId()));
                }
            }
    });
于 2019-09-11T12:57:15.107 回答