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

时间:2019-01-23 23:40:36

标签: android android-layout kotlin android-databinding android-jetpack

我无法使用onClick方法来处理自定义FrameLayout视图。

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

自定义ProgressButton视图类:

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的{​​{1}}视图:

android:onClick

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

1 个答案:

答案 0 :(得分:0)

假设您在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>

Android Studio中应该有一个选项可以让您自动转换布局。通过在布局的根ViewGroup上按Alt + Enter(Windows)或Option + Enter(OSX)来执行此操作。在这种情况下,您希望在FrameLayout上实现该组合。

在您的ProgressButton类中,您想要执行以下操作:

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类中应该定义onProgressButtonClick()

如果我没记错的话,您可能需要在布局中为onClick做这样的事情:

android:onClick="@{(v) -> viewModel.onProgressButtonClick()}"

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

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

binding.button