55

I'm trying to bind events with views in xml using DataBinding Library shipped with Android M. I'm following examples from Android Developers and implementing step-by-step. for the view's attributes like visibility,text its working fine but if I try to bind with onclick, it doesn't work as expected. Here's the sample code that I've tried so far:

 <data>
    <import type="android.view.View"/>
    <variable name="user" type="com.example.databinding.User"/>
    <variable name="handlers" type="com.example.databinding.MyHandlers"/>
</data>

 <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{user.firstName}"
    android:visibility="@{user.isFriend ? View.VISIBLE : View.GONE}" />
 <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click Me"
    android:id="@+id/button"
    android:layout_gravity="left"
    android:onClick="@{handlers.onClickFriend}"/>

MainActivity :

  public class MainActivity extends AppCompatActivity {

  User user;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = 
    DataBindingUtil.setContentView(this,R.layout.activity_main);
    user = new User("Pankaj","Kumar",true,true);
    binding.setUser(user);
   }
 }

MyHandlers:

public class MyHandlers {
public void onClickFriend(View view){
    Log.i(MyHandlers.class.getSimpleName(),"Now Friend");
}

public void onClickEnemy(View view){
    Log.i(MyHandlers.class.getSimpleName(),"Now Enemy");
  }
}

I've written only required code to improve readability. Could someone help me on this.

4

9 回答 9

107

我认为你也需要绑定handlers,也许是这样的onCreate

MyHandlers handlers = new MyHandlers();
binding.setHandlers(handlers);
于 2015-08-12T10:27:30.890 回答
62

设置点击的多种方式

  1. 将处理程序传递给绑定。

    ActivityMainBinding 绑定 = DataBindingUtil.setContentView(this,R.layout.activity_main); 处理程序处理程序 = 新处理程序();绑定.setHandler(处理程序);

  2. 设置点击次数(使用以下任何一种)

    android:onClick="@{handler::onClickMethodReference}"

或者

android:onClick="@{handler.onClickMethodReference}"

或者

android:onClick="@{() -> handler.onClickLamda()}"

或者

android:onClick="@{(v) -> handler.onClickLamdaWithView(v)}"

或者

android:onClick="@{() -> handler.onClickLamdaWithView(model)}"

请参阅 Handler 类了解。

public class Handler {
    public void onClickMethodReference(View view) {
        //
    }
    public void onClickLamda() {
        //
    }
    public void onClickLamdaWithView(View view) {
        //
    }
    public void onClickLamdaWithObject(Model model) {
        //
    }
}

注意

  • 当您具有与属性onClick相同的参数时,您可以使用方法引用 (::)
  • 您可以传递任何对象,onClickLamdaWithObject例如示例。
  • 如果您需要传递View对象,则只需使用(v)->表达式。

进一步阅读

https://developer.android.com/topic/libraries/data-binding/expressions

于 2018-08-17T11:46:31.210 回答
16

在您的 xml 中使用此格式:

android:onClick="@{handlers::onClickFriend}"

注意::,不要担心 xml 编辑器中的红线,因为目前这是 Android Studio xml 编辑器的开放错误

handlers数据标签中的变量在哪里:

<data>
    <variable name="handlers" type="com.example.databinding.MyHandlers"/>
</data>

是你的onClickFriend方法:

public class MyHandlers {
    public void onClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(),"Now Friend");
    }
}

添加

onLongClick对于xml 中的句柄,添加以下内容:

android:onLongClick="@{handlers::onLongClickFriend}"

onLongClickFriend并在您的 ViewModel 类中添加方法:

public class MyHandlers {
    public boolean onLongClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(),"Long clicked Friend");
        return true;
    }
}

添加

如果需要显示 toast 消息,可以使用接口(更好的变体),或者在构造中传入contextMyHandlers

public class MyHandlers {
    public boolean onLongClickFriend(View view) {
        Toast.makeText(view.getContext(), "On Long Click Listener", Toast.LENGTH_SHORT).show();
        return true;
    }
}
于 2016-11-07T13:25:44.393 回答
4

你应该做

android:onClick="@{() -> handlers.onClickFriend()}"
于 2017-09-03T14:31:04.660 回答
4

如果你要使用你的activity,不妨替换context掉自动绑定的对象,否则你就是在浪费空间。

根据需要生成一个名为 context 的特殊变量,用于绑定表达式。context 的值是来自根 View 的 getContext() 的 Context。上下文变量将被具有该名称的显式变量声明覆盖。

binding.setContext(this);

<variable name="context" type="com.example.MyActivity"/>

请注意,如果您只使用onClick="someFunc"根本不是数据绑定功能的纯字符串。这是一个较旧的功能,它使用一点反射来查找上下文中的方法。

于 2016-09-19T23:49:47.520 回答
3

我发布这个只是为了涵盖实现这一目标的两种方法。1.通过Listener绑定 2.通过方法引用

布局:

<layout...>
<data>

        <variable
            name="handlers"
            type="com.example.databinding.MyPresenter" />
        <variable name="user" type="com.example.databinding.User"/>
</data>

<LinearLayout
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:text="Using Listener Binding"
            android:onClick="@{() -> handlers.onLisClick(user)}"/>

     <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:text="Using Method Ref"
            android:onClick="@{handlers::onButtonClicked}"/>            

</LinearLayout>
</layout>

活动:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding =
                DataBindingUtil.setContentView(this, R.layout.activity_main);
        MyPresenter presenter = new MyPresenter();
        User user = new User("Alex","RJ")
        binding.setUser(user);
        binding.setHandlers(presenter);
    }

我的演讲者:

public class MyPresenter{

//using listener binding
public void onLisClick(User user){
//do something..
}


//using method reference
public void onButtonClicked(View view){

// do something
}

}

注意:
1.当使用方法引用时,方法签名应该与您为任何其他 onClick 方法编写的相同,即 public 和 View 作为参数。

2.在使用监听器绑定时,如果您愿意并执行任何操作,您也可以直接传递对象。

于 2018-06-27T14:41:07.223 回答
2

不必创建单独的类MyHandlers并调用setHandlers处理android:onClick。您可以只使用方法:public void onClickFriend(View view)public void onClickEnemy(View view)in MainActivity。活动视图:

public class MainActivity extends AppCompatActivity {
    User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding =
                DataBindingUtil.setContentView(this, R.layout.activity_main);
        user = new User("Pankaj", "Kumar", true, true);
        binding.setUser(user);
    }

    public void onClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(), "Now Friend");
    }

    public void onClickEnemy(View view) {
        Log.i(MyHandlers.class.getSimpleName(), "Now Enemy");
    }
}

一个布局:

<data>
    <import type="android.view.View"/>
    <variable name="user" type="com.example.databinding.User"/>
</data>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{user.firstName}"
    android:visibility="@{user.isFriend ? View.VISIBLE : View.GONE}" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click Me"
    android:id="@+id/button"
    android:layout_gravity="left"
    android:onClick="@{onClickFriend}"/>

看一下为 MVVM 模式使用数据绑定库的示例:http: //cases.azoft.com/mvvm-android-data-binding

于 2015-12-18T12:40:23.257 回答
1

我发布这个是因为我遇到了另一种发生这种情况的情况。如果您有两个引用布局文件的活动,一个定义了 onclick 事件,而另一个定义了 onclick 事件,那么您不会收到相同的警告,并且奇怪的是在您定义事件的活动中。

要检查这一点,我建议通过布局名称查找布局文件的用法,right clicking然后按find references。不要忘记重建应用程序后记。

于 2018-05-09T11:08:04.400 回答
0

对于那些在处理长点击事件方面有困难的人:

首先在你的布局中创建一个带有 id 的视图。

<data>
        <variable
            name="tempDesc"
            type="String" />
        <variable
            name="activity"
            type="com.naruto.trangoapp.MainActivity" />
</data>

<TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{(view) -> activity.changeDescText(view)}"
            android:text="@{tempDesc}" />

在您的 onCreate 方法中,使用视图的 id 名称来设置任何侦听器:-

binding.textView.setOnLongClickListener(this::onLongClick);

然后只需创建一个具有相同名称的布尔方法,即 onLongClick 如下所示:-

private boolean onLongClick(View l) {
        Toast.makeText(this, "Description", Toast.LENGTH_SHORT).show();
        return true;
    }

就这样!!

注意:您还可以通过在 onCreate 方法中为活动变量设置上下文来将任何方法设置为布局中的任何视图:-

binding.setActivity(this);

然后,在布局中定义并传递方法名称和视图,以在 Activity 文件中使用它。就像我为我的Textview 使用了一个变量名为“activity”的方法changeDescText(v)。这是我在活动文件中的方法:-

public void changeDescText(View view) {
        binding.setTempDesc("Description Changed");
    }
于 2020-03-21T19:11:16.280 回答