在自定义relativelayout视图中使用开关进行2路数据绑定

时间:2019-05-12 18:23:57

标签: android kotlin android-databinding 2-way-object-databinding

我正在尝试实现一些自定义的绑定适配器,以便可以将我的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 :(得分:0)

您的InverseBindingAdapter应该具有以下注释:

add_subdirectory()