使用DataBinding库绑定事件

时间:2015-08-12 09:58:00

标签: android data-binding android-6.0-marshmallow android-databinding

我正在尝试使用Android M附带的 DataBinding Library 将事件与xml中的视图绑定。我正在关注Android Developers中的示例并逐步实施。对于视图的属性,如可见性,文本工作正常,但如果我尝试与onclick绑定,它不会按预期工作。这是我到目前为止尝试过的示例代码:

 <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");
  }
}

我只编写了所需的代码来提高可读性。有人可以帮我解决这个问题。

9 个答案:

答案 0 :(得分:92)

我认为你还需要绑定handlers,也许在onCreate中也可以这样:

MyHandlers handlers = new MyHandlers();
binding.setHandlers(handlers);

答案 1 :(得分:14)

在xml:

中使用此格式
android:onClick="@{handlers::onClickFriend}"

请注意::,不要担心xml编辑器中的红线,因为目前Android Studio xml编辑器已打开bug

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");
    }
}

<强> ADDED

对于xml中的句柄onLongClick,请添加:

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

并在ViewModel类中添加onLongClickFriend方法:

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

<强> ADDED

如果您需要显示toast消息,可以使用接口(更好的变体),或者在context类中传递MyHandlers

public class MyHandlers {

    private Context context;

    public MyHandlers(Context context) {
        this.context = context;
    }

    public boolean onLongClickFriend(View view) {
        Toast.makeText(context, "On Long Click Listener", Toast.LENGTH_SHORT).show();
        return true;
    }
}

答案 2 :(得分:10)

许多设置方法点击

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

<input type="text" placeholder="City, Zip Code, Coordinates" onChange={evt => this.updateInputValue(evt)} value={this.state.inputValue}/>

2)设置点击次数(使用以下任一选项)

ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
Hander handler = new Handler();
binding.setHandlers(handlers);

OR

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

OR

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

OR

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

OR

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

请参阅Handler类以了解它们。

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

请注意

  • 与属性 onClick 相同的参数时,可以使用方法参考(::)
  • 您可以传递任何对象,例如public class Handler { public void onClickMethodReference(View view) { // } public void onClickLamda() { // } public void onClickLamdaWithView(View view) { // } public void onClickLamdaWithObject(Model model) { // } } 示例。
  • 如果您需要传递onClickLamdaWithObject对象,则只需使用 View 表达式。

进一步阅读

reset_index

答案 3 :(得分:4)

如果您要使用自己的活动,也可以替换自动绑定的context对象,否则会浪费空间。

  

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

binding.setContext(this);

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

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

答案 4 :(得分:4)

你应该做

android:onClick="@{() -> handlers.onClickFriend()}"

答案 5 :(得分:2)

创建单独的班级if并调用MyHandlers以处理setHandlers并非强制性要求。您可以在android:onClick中使用public void onClickFriend(View view)public void onClickEnemy(View view)方法。 活动视图:

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");
    }
}

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

答案 6 :(得分:2)

我发布此内容只是为了介绍实现此目的的两种方法。 1.通过听众绑定 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);
    }

MyPresenter:

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 as parameter)编写的签名相同。

2。使用侦听器绑定的好处是,如果需要并可以执行任何操作,也可以直接传递对象。

答案 7 :(得分:1)

我发布这个是因为我还有另一种情况发生了这种情况。如果你有两个活动引用布局文件,一个定义onclick事件,另一个没有得到相同的警告,奇怪的是你定义事件的活动。

要检查此项,我建议您在布局名称上按right clicking查找布局文件的用法,然后按find references。不要忘记重建应用程序。

答案 8 :(得分: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);

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

public void changeDescText(View view) {
        binding.setTempDesc("Description Changed");
    }