在自定义 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
我无法获得使用自定义 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