【问题标题】:android:onClick attribute is not working through data bindingandroid:onClick 属性不能通过数据绑定工作
【发布时间】:2021-08-28 19:46:36
【问题描述】:

这是我的 Fragment 类的代码。

class FragmentOne : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        // return inflater.inflate(R.layout.fragment_one, container, false)
        val binding: FragmentOneBinding =
            DataBindingUtil.inflate(inflater, R.layout.fragment_one, container, false)
        return binding.root
    }

    fun onClicking(){
        Toast.makeText(activity, "You clicked me.", Toast.LENGTH_SHORT).show()

    }
}

这是我的片段 XML 代码。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".FragmentOne">

    <data>
        <variable
            name="clickable"
            type="com.example.fragmentpractise1.FragmentOne" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hola Gola"
        android:layout_marginTop="40dp"
        android:onClick="@{()-> clickable.onClicking()}"/>

    </LinearLayout>
</layout>

现在我想了解的是,为什么android:onClick 没有显示任何吐司结果。按下按钮没有任何反应。我可以通过在 Fragment 类中的按钮 id 上设置 onClickListener 来显示 toast,但无法使用数据绑定通过 XML 中的onClick 属性显示 toast。

【问题讨论】:

  • 您尚未为clickable 定义值。你膨胀了绑定,但是你没有对绑定做任何事情来告诉它clickable 的值是什么。因此,数据绑定将clickable 视为null。幸运的是,它抑制了NullPointerExceptions,所以你没有崩溃(尽管 Logcat 中可能仍然有一些消息——我忘记了)。

标签: android kotlin android-databinding


【解决方案1】:

您在尚未设置的 xml 中调用 clickable.onClicking()。当您实例化一个数据绑定对象时,您可能还必须设置它的变量(例如您的示例中的clickable

像这样在实例化后设置该变量


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        // return inflater.inflate(R.layout.fragment_one, container, false)
        val binding: FragmentOneBinding =
            DataBindingUtil.inflate(inflater, R.layout.fragment_one, container, false)
        binding.clickable = this // your fragment
        return binding.root
    }

在 onClick 中使用v 而不是() 更合理一些,因为这是Java 语法中的一个lambda,它接收一个视图参数。我建议将其更改为以下以提高可读性

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hola Gola"
        android:layout_marginTop="40dp"
        android:onClick="@{ v -> clickable.onClicking()}"/>

【讨论】:

  • 解决了。但我仍有疑问。在声明变量“clikcable”时,我也声明了类型。那么是否也需要一直在片段中实例化?如果您能对此主题进行更多说明,将会很有帮助。
  • 是的,您必须这样做,因为即使您声明了类型,编译器和运行时也无法猜测该类型中的哪个对象适合您的变量。但是你可以利用反射来做到这一点。不过,这并不是一件容易的事。您可以查看this answer,了解您可以在 BaseFragment 中做什么。使用该函数后,您将拥有绑定类,您可以在其上调用 inflate 函数来获取绑定。您可以利用另一个反射调用在其中使用固定名称设置该变量。
  • 这个方法太复杂了,极大地降低了代码的可读性并且脱离了这个问题的上下文。但是你可以问另一个关于“神奇地”在数据绑定中设置对象的问题,我和这里的其他人可能会想出更好的方法
  • 现在知道了。非常感谢!
猜你喜欢
  • 2017-12-07
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 2011-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多