Componentを使用したオプションチップセットの作成

6854 ワード

個人プロジェクトで使用するオプションのチップセットを復習します.

デフォルトでは、LazyRowは水平スクロール機能をサポートしています.chipをクリックすると、UI要素は次のようにchipの色を変更するだけです.

例では、chipは4つに実装され、chipリストがアレイに格納されて管理されるため、chipをアレイに追加したり、chipのボタンを押して削除したりすることができる.
(チップを追加または削除する場合は、可変状態リストOfを使用してチップを管理すると便利です)
まず、チップごとにChipStateを作成しました.
data class ChipState(
    var text: String,
    val isSelected: MutableState<Boolean>
)
これは、チップが選択されている必要があるため、isSelectedをMutableStateとして指定するチップを表します.
次はChip関数であり、Chipに対応するUIである.
@Composable
private fun Chip(
    text: String,
    selected: Boolean,
    modifier: Modifier = Modifier,
    onChipClicked: (String, Boolean) -> Unit,
    onDeleteButtonClicked: (String, Boolean) -> Unit
) {
    Surface(
        color = when {
            selected -> colorResource(id = R.color.main_ingredient)
            else -> colorResource(id = R.color.sub_ingredient)
        },
        contentColor = Color.White,
        shape = RoundedCornerShape(16.dp),
        border = BorderStroke(
            width = 1.dp,
            color = when {
                selected -> colorResource(id = R.color.main_ingredient)
                else -> colorResource(id = R.color.sub_ingredient)
            }
        ),
        modifier = modifier
    ) {
        Row(modifier = Modifier) {
            Text(
                text = text,
                style = typography.body2,
                modifier = Modifier
                    .padding(8.dp)
                    .clickable { onChipClicked(text, selected) }
            )
            
            Image(
                imageVector = Icons.Default.Clear,
                contentDescription = null,
                modifier = Modifier
                    .padding(8.dp)
                    .size(20.dp)
                    .clickable { onDeleteButtonClicked(text, selected) },
                colorFilter = ColorFilter.tint(Color.White)
            )
        }
    }
}
ChipはChipグループにのみ使用される関数であるためprivateとして宣言される.
パラメータの意味は次のとおりです.
1.textはチップに書き込むテキストです.
2.selectedはチップの色を決定します.
3.onChipClickedの場合、chipをクリックすると呼び出されるramda関数.
4.onDeleteButtonClickedは、削除ボタンをクリックしたときに呼び出されるramda関数です.
@Composable
fun Chips(
    modifier: Modifier = Modifier,
    elements: List<ChipState>,
    onChipClicked: (String, Boolean, Int) -> Unit,
    onDeleteButtonClicked: (String, Boolean, Int) -> Unit
) {
    LazyRow(modifier = modifier) {
        items(elements.size){ idx ->
            Chip(
                text = elements[idx].text,
                selected = elements[idx].isSelected.value,
                onChipClicked = { content, isSelected ->
                    onChipClicked(content,isSelected,idx)
                },
                onDeleteButtonClicked = { content, isSelected ->
                    onDeleteButtonClicked(content, isSelected, idx)
                }
            )
            Spacer(modifier = Modifier.padding(8.dp))
        }
    }
}
次に、複数のチップを表すChips関数を示します.
Elementsパラメータはchipリストのリストであり、chipが何個あるかを示す.
したがって、LazyRow Compositoryブログを使用して、items{}として必要な数(elements.size)のチップを作成します.
onChipClicked関数とonDeleteButtonClickedのパラメータタイプがChipとは異なることがわかります.
ChipのonChipClickedは1つのチップに対するクリック処理であるため、テキストと選択のみが伝達される.
ただし、ChipsのonChipClickedは、いくつかのチップがクリックされたインデックス情報を必要とするため、呼び出されるパラメータが異なる.
同様に、onDeleteButtonClicked関数のパラメータも異なります.
このようにして作られたChips Componentをどのように応用しますか?
val elements by remember {
     mutableStateOf(
        listOf(
            ChipState("item1", mutableStateOf(false)),
            ChipState("item2", mutableStateOf(false)),
            ChipState("item3", mutableStateOf(false)),
            ChipState("item4", mutableStateOf(false))
        )
     )
 }

 Column(modifier = Modifier.padding(10.dp)) {
     Chips(
         modifier = Modifier.padding(8.dp),
         elements = elements,
         onChipClicked = { content, isSelected, idx ->
             // called when chip clicked
         	elements[idx].isSelected.value = !elements[idx].isSelected.value
 		 },
         onImageClicked = { content, isMain, idx ->
            // called when delete button clicked
         }
     )
}
ステータス配列を作成してChipを管理し、情報をChipsのパラメータとして渡します.
chipをクリックすると、chipのisSelected変数を変更する必要があります.onChipClickedには上記のコードが含まれています.
また、上記のChipsを適用して、追加/削除可能なChipリストを作成する例を作成します.
val elements = remember {
    mutableStateListOf(
        ChipState("item1", mutableStateOf(false)),
        ChipState("item2", mutableStateOf(false)),
        ChipState("item3", mutableStateOf(false)),
        ChipState("item4", mutableStateOf(false))
    )
}

var newChipText by remember { mutableStateOf("") }
Column(modifier = Modifier.padding(10.dp)) {
    TextField(
        modifier = Modifier.fillMaxWidth(),
        value = newChipText,
        onValueChange = { newChipText = it },
        trailingIcon = {
            IconButton(
                onClick = {
                    elements.add(ChipState(newChipText, mutableStateOf(false)))
                    newChipText = ""
                }
            ) {
                Icon(imageVector = Icons.Default.Search, contentDescription = "")
            }
        }
    )

    Chips(
        modifier = Modifier.padding(8.dp),
        elements = elements,
        onChipClicked = { content, isSelected, idx ->
            elements[idx].isSelected.value = !elements[idx].isSelected.value
        },
        onDeleteButtonClicked = { content, isMain, idx ->
            elements.removeAt(idx)
        }
    )
}
これはchipを追加/削除できるchipリストであるため、可変ステータスリストで追加/削除するとステータスが変化します.
(変位リストを使用すると、リストの状態が変化する可能性がありますので、予想通りに操作できない場合があります)
次に、chipを追加するためのTextFieldを作成し、アイコンをクリックすると、TextFieldを入力するテキストを含むchipを追加できます.
また、onDeleteButtonClickedの要素のidxの2番目のChipStateを削除する必要があります(ChipsのXアイコンをクリックします).
上記の例の成果物は次のとおりです.

初期状態では、item 2のXボタンをクリックして削除できます.

TextFieldにtestを入力し、ボタンをクリックしてChipsに追加します.

また、新しく作成したチップの選択ステータスを調整することもできます.