web-dev-qa-db-ja.com

ChipGroup単一選択

少なくとも1つの選択されたアイテムを常に持つようにChipGroupRadioGroupのように動作させるにはどうすればよいですか? setSingleSelection(true)を設定すると、Chipを2回クリックしても何も選択されない可能性が追加されます。

10
adriennoir

解決策は、クリックされたチップをプリセットしてから、チップのクリック可能なプロパティを切り替えることです。

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

@adriennoirの回答の簡単な修正(コトリン)。助けてくれてありがとう! 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)
        }
    }

}
6
Todd DeLand

これを達成するには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属性を設定すると、チップグループに属する1つのチップをチェックすると、同じグループ内で以前にチェックされたチップのチェックがすべて解除されます。この動作は、RadioGroupの動作を反映しています。

5
Joaquim Ley

ほとんどの答えは素晴らしく、本当に助けになります。 setSingleSelection(true) ChipGroupで既にチェックされているチップのチェックが解除されないようにするための、@ adriennoirおよび@Todd DeLandへのもう1つのわずかな変更、これが私の解決策です。

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
}

私にとっては、クリックできないようにすることなく、同じチェック済みチップがチェック解除されないようにする必要があります。この方法では、ユーザーはチェックされたチップをクリックして派手な波及効果を見ることができ、何も起こりません。

3
toktorio

これは私の作業ソリューションです

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()));
                }
            }
    });
0
zayn1991

これは私がやった方法です:

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