ChipGroup单选

时间:2018-11-05 13:06:26

标签: android android-chips

我如何强迫ChipGroupRadioGroup一样始终拥有至少一个选定项?设置setSingleSelection(true)还会增加单击Chip两次时未选择任何内容的可能性。

8 个答案:

答案 0 :(得分:12)

要防止取消选择所有筹码,可以使用方法 setSelectionRequired

chipGroup.setSelectionRequired(true)

您还可以使用 app:selectionRequired 属性在布局中对其进行定义:

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

注意:这要求最低版本为 1.2.0-alpha02

答案 1 :(得分:9)

一种解决方案是预先设置点击的芯片,然后切换芯片的clickable属性:

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);
    }
});

答案 2 :(得分:4)

@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)
        }
    }

}

答案 3 :(得分:2)

有两个步骤可以实现

步骤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.
    (...)

}

来自docs

  

ChipGroup还支持一组芯片的多重排除范围。   设置app:singleSelection属性时,请检查一块   属于芯片组的人取消选中其中任何先前检查过的芯片   同一组。该行为反映了RadioGroup的行为。

答案 4 :(得分:0)

这是我的方法:

var previousSelection: Int = default_selection_id 
chipGroup.setOnCheckedChangeListener { chipGroup, id ->
    if (id == -1) //nothing is selected.
        chipGroup.check(previousSelection)
    else
        previousSelection = id

答案 5 :(得分:0)

大多数答案都很好,对我来说真的很有帮助。为了防止取消选中setSingleSelection(true) ChipGroup中已经检查过的筹码,对@adriennoir和@Todd DeLand进行了另一项轻微的修改,这是我的解决方案:

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
}

对我来说,我只需要防止取消选中同一选中的Chip而不使它不可点击即可。这样,用户仍然可以单击选中的芯片并看到花哨的涟漪效应,而不会发生任何事情。

答案 6 :(得分: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()));
                }
            }
    });

答案 7 :(得分:-1)

对于避免不必要地遍历所有ChipGroup子级的通用解决方案,请尝试以下操作...

chip_group.setOnCheckedChangeListener(object : ChipGroup.OnCheckedChangeListener {
    @IdRes
    private var lastCheckedChipId: Int = View.NO_ID

    override fun onCheckedChanged(chipGroup: ChipGroup, checkedChipId: Int) {
        chipGroup.findViewById<Chip>(checkedChipId).isClickable = false
        if (lastCheckedChipId != checkedChipId && lastCheckedChipId != -1) {
            chipGroup.findViewById<Chip>(lastCheckedChipId).isClickable = true
        }
        lastCheckedChipId = checkedChipId
    }
})

请记住在您的app:singleSelection="true"上指定ChipGroup

更新: 我观察到在销毁并重新创建屏幕后,此代码崩溃,这是由于onCheckedChange()checkedChipId == -1(默认)调用,因此findViewById()调用返回了{{1} }。可以通过检查这种情况并尽早返回来解决:

null