芯片组单选
ChipGroup single selection
如何强制 ChipGroup
像 RadioGroup
一样始终至少选择一项?设置 setSingleSelection(true)
还可以增加在 Chip
.
上单击两次时不选择任何内容的可能性
一个解决方案是预设一个点击筹码,然后切换筹码的可点击 属性:
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);
}
});
对@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)
}
}
}
我是这样做的:
var previousSelection: Int = default_selection_id
chipGroup.setOnCheckedChangeListener { chipGroup, id ->
if (id == -1) //nothing is selected.
chipGroup.check(previousSelection)
else
previousSelection = id
大部分答案都很棒,对我很有帮助。对@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
}
对我来说,我只需要在不使其不可点击的情况下防止取消选中相同的已选中 Chip。这样,用户仍然可以点击选中的芯片并看到花哨的波纹效果,而不会发生任何事情。
编辑
版本 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 步
我们有此支持 built-in,只需确保将 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 also supports a multiple-exclusion scope for a set of chips.
When you set the app:singleSelection attribute, checking one chip that
belongs to a chip group unchecks any previously checked chip within
the same group. The behavior mirrors that of RadioGroup.
这是我的工作解决方案
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()));
}
}
});
为了防止所有芯片被取消选择,您可以使用方法 setSelectionRequired
:
chipGroup.setSelectionRequired(true)
您也可以使用 app:selectionRequired
属性在布局中定义它:
<com.google.android.material.chip.ChipGroup
app:singleSelection="true"
app:selectionRequired="true"
app:checkedChip="@id/..."
..>
注意:这需要最低版本1.2.0
如果 singleSelection 不适用于添加的动态筹码,您必须 生成 id为每个芯片创建它们然后添加到 ChipGroup.
val chip = inflater.inflate(
R.layout.item_crypto_currency_category_chip,
binding.chipGroupCryptoCurrencyCategory,
false) as Chip
chip.id = ViewCompat.generateViewId()
binding.chipGroupCryptoCurrencyCategory.addView(chip)
//Set default value with index 0 when ChipGroup created.
if (index == 0) binding.chipGroupCryptoCurrencyCategory.check(chip.id)
item_crypto_currency_category_chip.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.chip.Chip xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/chip_smart_contract"
style="@style/Widget.Signal.Chip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
item_crypto_currency_tag_category.xml
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_6x"
android:scrollbars="none"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.chip.ChipGroup
android:id="@+id/chip_group_crypto_currency_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true"
app:singleLine="true"
/>
</HorizontalScrollView>
结果:
如何强制 ChipGroup
像 RadioGroup
一样始终至少选择一项?设置 setSingleSelection(true)
还可以增加在 Chip
.
一个解决方案是预设一个点击筹码,然后切换筹码的可点击 属性:
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);
}
});
对@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)
}
}
}
我是这样做的:
var previousSelection: Int = default_selection_id
chipGroup.setOnCheckedChangeListener { chipGroup, id ->
if (id == -1) //nothing is selected.
chipGroup.check(previousSelection)
else
previousSelection = id
大部分答案都很棒,对我很有帮助。对@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
}
对我来说,我只需要在不使其不可点击的情况下防止取消选中相同的已选中 Chip。这样,用户仍然可以点击选中的芯片并看到花哨的波纹效果,而不会发生任何事情。
编辑
版本 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 步
我们有此支持 built-in,只需确保将 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 also supports a multiple-exclusion scope for a set of chips. When you set the app:singleSelection attribute, checking one chip that belongs to a chip group unchecks any previously checked chip within the same group. The behavior mirrors that of RadioGroup.
这是我的工作解决方案
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()));
}
}
});
为了防止所有芯片被取消选择,您可以使用方法 setSelectionRequired
:
chipGroup.setSelectionRequired(true)
您也可以使用 app:selectionRequired
属性在布局中定义它:
<com.google.android.material.chip.ChipGroup
app:singleSelection="true"
app:selectionRequired="true"
app:checkedChip="@id/..."
..>
注意:这需要最低版本1.2.0
如果 singleSelection 不适用于添加的动态筹码,您必须 生成 id为每个芯片创建它们然后添加到 ChipGroup.
val chip = inflater.inflate(
R.layout.item_crypto_currency_category_chip,
binding.chipGroupCryptoCurrencyCategory,
false) as Chip
chip.id = ViewCompat.generateViewId()
binding.chipGroupCryptoCurrencyCategory.addView(chip)
//Set default value with index 0 when ChipGroup created.
if (index == 0) binding.chipGroupCryptoCurrencyCategory.check(chip.id)
item_crypto_currency_category_chip.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.chip.Chip xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/chip_smart_contract"
style="@style/Widget.Signal.Chip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
item_crypto_currency_tag_category.xml
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_6x"
android:scrollbars="none"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.chip.ChipGroup
android:id="@+id/chip_group_crypto_currency_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true"
app:singleLine="true"
/>
</HorizontalScrollView>
结果: