Двухсторонняя привязка данных с переключателем внутри пользовательского вида относительного расположения - PullRequest
0 голосов
/ 12 мая 2019

Я пытаюсь реализовать некоторые настраиваемые привязывающие адаптеры, чтобы я мог привязать данные своего значения viewmodel к значению switch.ischecked в моем настраиваемом представлении.Я хочу, чтобы состояние переключателя изменилось, если оно включено в изменениях моей модели представления и наоборот.Я просмотрел множество статей о том, как этого добиться, но он все еще ничего не делает.Я вижу, что мой метод setSwitchChecked используется реализацией привязки данных, но на самом деле он ничего не устанавливает.2 других адаптера остаются неиспользованными.Любая помощь в том, что я пропускаю или делаю не так, приветствуется.

ViewModel

open class SettingsViewModel @Inject constructor(): ViewModel() {

    var enabled: MutableLiveData<Boolean> = MutableLiveData()

}

Фрагмент

class SettingsFragment @Inject constructor(): Fragment() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory

    private lateinit var viewDataBinding: FragmentSettingsBinding
    private lateinit var viewModel: SettingsViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view: View = inflater.inflate(R.layout.fragment_settings, container, false)

        viewModel = ViewModelProviders.of(activity!!, viewModelFactory).get(SettingsViewModel::class.java)

        viewDataBinding = FragmentSettingsBinding.inflate(inflater, container, false).apply {
            viewmodel = viewModel
        }

      return view
    }
}

CustomView XML-привязка

<com.stinson.sleepcycles.views.SwitchRow
            android:id="@+id/switch_row"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:switchLabel="@string/enabled"
            app:switchChecked="@{viewmodel.enabled}"/>

Пользовательский класс просмотра

class SwitchRow constructor(context: Context, attrs: AttributeSet, defStyle: Int = 0) :
    RelativeLayout(context, attrs, defStyle), View.OnClickListener {

    constructor(context: Context, attrs: AttributeSet): this(context, attrs, 0)

    init {
        val view = inflate(context, R.layout.view_switch_row, this)

        val a = context.theme.obtainStyledAttributes(attrs, R.styleable.SwitchRow, defStyle, 0)
        try {
            view.text_label.text = a.getString(R.styleable.SwitchRow_switchLabel)
            view.switch_toggle.isChecked = a.getBoolean(R.styleable.SwitchRow_switchChecked, false)
        } finally {
            a.recycle()
        }

        view.setOnClickListener {
            view.switch_toggle.callOnClick()
        }
        view.switch_toggle.setOnClickListener {
            toggleSwitch(view)
        }
    }

    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_UP) {
            this.callOnClick()
        }
        return super.dispatchTouchEvent(event)
    }

    override fun onClick(view: View?) {
        if (view != null) view.callOnClick()
    }

    private fun toggleSwitch(view: View) {
        view.switch_toggle.isChecked = !view.switch_toggle.isChecked
    }
}

Пользовательский вид XML

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/selectableItemBackground"
    android:clickable="true"
    android:padding="16dp">

    <TextView
        android:id="@+id/text_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/text_size_medium"
        tools:text="Label" />

    <androidx.appcompat.widget.SwitchCompat
        android:id="@+id/switch_toggle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"/>

</RelativeLayout>

Связывающие адаптеры

@BindingAdapter("switchCheckedAttrChanged")
fun setListener(switchRow: SwitchRow, listener: InverseBindingListener) {
    switchRow.switch_toggle.setOnCheckedChangeListener { _, _ ->
        listener.onChange()
    }
}

@BindingAdapter("switchChecked")
fun setSwitchChecked(switchRow: SwitchRow, value: Boolean) {
    if (value != switchRow.switch_toggle.isChecked) {
        switchRow.switch_toggle.isChecked = value
    }
}

@InverseBindingAdapter(attribute = "switchChecked")
fun getSwitchChecked(switchRow: SwitchRow): Boolean {
    return switchRow.switch_toggle.isChecked
}

1 Ответ

0 голосов
/ 20 мая 2019

Ваш InverseBindingAdapter должен иметь следующую аннотацию:

@InverseBindingAdapter(attribute = "switchChecked", event = "switchCheckedAttrChanged")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...