在自定义 FrameLayout 视图中启用 `onClick` 方法

Enabling the `onClick` method in a custom FrameLayout view

我无法获得使用自定义 FrameLayout 视图的 onClick 方法。

当我将默认 Button 视图重构为包含 Button 的自定义 ProgressButton 视图时,不会调用 onClick 方法。

自定义 ProgressButton 视图 class:

class ProgressButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0,
    defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyle, defStyleRes){

    private var button: Button

    init {
        val view = LayoutInflater.from(context).inflate(R.layout.view_progress_button, this, true)
        button = view.findViewById(R.id.button)
        context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.ProgressButton,
            0, 0
        ).apply {
            try {
                if (hasValue(R.styleable.ProgressButton_buttonText)) {
                    button.text = getString(R.styleable.ProgressButton_buttonText)
                }
                if (hasValue(R.styleable.ProgressButton_buttonBackground)) {
                    button.background = getDrawable(R.styleable.ProgressButton_buttonBackground)
                }
            } finally {
                recycle()
            }
        }
    }
}

ProgressButton XML 布局文件:res/layout/view_progress_button.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />

</FrameLayout>

ProgressButton 视图与 android:onClick 的用法:

<com.example.ui.common.ProgressButton
        android:id="@+id/progress_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="@{() -> viewModel.onProgressButtonClick()}"
        app:buttonText="@string/test"
        app:buttonBackground="@drawable/selectable_button_blue"
/>

使用 Android 数据绑定将点击侦听器传递到自定义视图的最佳方式是什么?

假设您在 build.gradle 中定义了 dataBinding.enabled true。如果没有,请查看 this

您的布局目前看起来不像是数据绑定布局。首先,您需要将 view_progress_button.xml 转换为如下所示的数据绑定布局:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="viewModel"
            type="com.your.package.YourViewModelClass" />
    </data>

    <FrameLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <com.example.ui.common.ProgressButton
        android:id="@+id/progress_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="@{() -> viewModel.onProgressButtonClick()}"
        app:buttonText="@string/test"
        app:buttonBackground="@drawable/selectable_button_blue"
        />

</FrameLayout>

AndroidStudio 中应该有一个选项可以让您自动转换布局。通过在布局中的根 ViewGroup 上按 alt + enter (Windows) 或 option + enter (OSX) 来执行此操作。在这种情况下,您希望在 FrameLayout 上点击该组合。

在您的 ProgressButton class 中,您想要做这样的事情:

val binding: ViewProgressButtonBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_progress_button, null, false);

而不是:

val view = LayoutInflater.from(context).inflate(R.layout.view_progress_button, this, true)

使用 binding 对象,您可以:

binding.setViewModel(yourViewModelInstance)

但是您可以实例化您的 ViewModel,但是在您的 ViewModel class 中您应该定义 onProgressButtonClick()

如果我没记错的话,您可能需要在 onClick:

的布局中执行类似的操作
android:onClick="@{(v) -> viewModel.onProgressButtonClick()}"

因为 lambda 期望将视图作为参数。

另一个注意事项是您不再需要执行 findViewById 因为您可以像这样访问该视图:

binding.button