Litho Radio Group 容器

Litho Radio Group container

我遵循了 Litho 指南中的复选框示例,并为单选按钮构建了一个类似的实现:

@LayoutSpec
object CRadioSpec {

    @OnCreateLayout
    fun onCreateLayout(
        c: ComponentContext,
        @Prop value: String,
        @State isChecked: Boolean
    ): Component? {
        return Column.create(c)
            .alignContent(YogaAlign.CENTER)
            .widthDip(20F)
            .child(
                Image.create(c)
                    .drawableRes(
                        if (isChecked) R.drawable.ic_checkbox_on
                        else R.drawable.ic_checkbox_off)
                    .clickHandler(CRadio.onCheckboxClicked(c))
            )
            .child(
                Text.create(c)
                    .alignment(TextAlignment.CENTER)
                    .alignSelf(YogaAlign.CENTER)
                    .widthDip(20F)
                    .text(value)
                    .build()
            )
            .build()
    }

    @OnCreateInitialState
    fun onCreateInitialState(
        c: ComponentContext?,
        isChecked: StateValue<Boolean?>,
        @Prop initChecked: Boolean
    ) {
        isChecked.set(initChecked)
    }

    @OnUpdateState
    fun updateCheckboxState(isChecked: StateValue<Boolean?>) {
         isChecked.get()?.let {
             isChecked.set(it.not())
         }
    }

    @OnUpdateState
    fun updateCheckbox(isChecked: StateValue<Boolean?>) {
        isChecked.get()?.let {
            isChecked.set(it.not())
        }

    }

    @OnEvent(ClickEvent::class)
    fun onCheckboxClicked(c: ComponentContext?) {
        CRadio.updateCheckbox(c)
    }
}

但是我认为这是为了获得多个单选框而将其包装在父级中,并且必须从父级管理状态。正如文档中提到的:

Let’s take the example of a list of radio buttons, where you cannot have multiple items checked at the same time. The state of all the radio buttons depends on whether other items get clicked and checked. Instead of making all the radio buttons stateful, you should keep the state of what item is clicked in the parent and propagate that information top-down to the children through props.

Link

我进行了大量搜索,但找不到任何相关内容。我还检查了 Spinner 组件的实现,但无法获得良好的实现。如果我能被引导到一个具体的例子,那将是一个很大的帮助?

您必须创建一个 Radio 组并从那里管理状态,即父级:

这是一种方法:

@LayoutSpec
object CrgSpec {
    @OnCreateLayout
    fun onCreateLayout(
        c: ComponentContext,
        @Prop viewModel: ViewModel,
        @State fields: ArrayList<RadioItem>,
        @Prop parentId: String
    ): Component? {
        val row =
            Row.create(c)
                .alignItems(YogaAlign.CENTER)
                .alignContent(YogaAlign.SPACE_AROUND)
                .flexGrow(1F)
                .wrap(YogaWrap.WRAP)
        fields.forEach { item ->
            row.child(
                CRadio.create(c)
                    .value(item.text)
                    .clickHandler(Crg.onClicked(c, item.id, item.text))
                    .isChecked(item.isChecked)
                    .id(item.id)
                    .build()
            )
        }
        val column = Column.create(c)
            .paddingDip(YogaEdge.TOP, 20F)
            .child(row.build())
        return column.child(
            TextInput.create(c)
                //.visibleHandler()
                .backgroundRes(R.drawable.edit_text_bg)
                .build()
        ).build()
    }

    @OnCreateInitialState
    fun onCreateInitialState(
        c: ComponentContext?,
        fields: StateValue<ArrayList<RadioItem>>,
        @Prop initChecked: ArrayList<RadioItem>
    ) {
        fields.set(initChecked)
    }

    @OnUpdateState
    fun updateCheckboxState(
        fields: StateValue<ArrayList<RadioItem>>,
        @Param id: String
    ) {
        fields.get()?.let { radioItem ->
            radioItem.forEach {
                it.isChecked = it.id == id
            }
            fields.set(radioItem)
        }
    }


    @OnUpdateState
    fun updateCheckbox(
        fields: StateValue<ArrayList<RadioItem>>,
        @Param id: String
    ) {
        fields.get()?.let { radioItem ->
            radioItem.forEach {
                it.isChecked = it.id == id
            }
            fields.set(radioItem)
        }
    }

    @OnEvent(ClickEvent::class)
    fun onClicked(
        c: ComponentContext?,
        @Prop viewModel: ViewModel,
        @Param id: String,
        @Prop parentId: String,
        @Param itemValue: String
    ) {
        Timber.d("id is: $id")
        CirclesRadioGroup.updateCheckbox(c, id)
        viewModel.onRadioUpdate(
            id,
            parentId,
            itemValue
        )
    }
}

参考文献:

奖励:- 这也是一个很好的示例,说明如何在视图模型中获取用户操作回调,以及服务器驱动 UI on Android 的紧凑示例。