Litho Radio Group контейнер - PullRequest
       30

Litho Radio Group контейнер

0 голосов
/ 20 апреля 2020

Я следовал примеру с флажком в руководстве по 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)
    }
}

Однако я считаю, что это должно быть заключено в родительский элемент, чтобы получить несколько переключателей и состояние должен управляться от родителя. Как уже упоминалось в документах:

Давайте рассмотрим список переключателей, в котором нельзя одновременно проверять несколько элементов. Состояние всех переключателей зависит от того, нажаты ли и проверены ли другие элементы. Вместо того, чтобы переключать все переключатели в состояние, вы должны сохранять состояние элемента, по которому щелкнули в родительском элементе, и распространять эту информацию сверху вниз через детей.

Ссылка

Я довольно много искал, но не могу найти что-нибудь подходящее. Я также проверил реализацию Spinner Component, но не могу найти хорошую реализацию. Было бы здорово помочь, если бы я мог привести конкретный пример?

1 Ответ

1 голос
/ 25 апреля 2020

Вы должны создать группу 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
        )
    }
}

Ссылки:

Бонус: - Это также очень хороший пример того, как вы получите обратные вызовы действий пользователя в вашей модели представления, и компактный пример управляемого сервером интерфейса пользователя на Android.

...