【问题标题】:Data bindings with custom listeners on custom view自定义视图上的自定义侦听器的数据绑定
【发布时间】:2015-11-30 19:04:33
【问题描述】:

我正在尝试使用新的 Android 数据绑定库绑定自定义视图上的事件,但遇到了问题。

这是我的自定义视图的相关部分:

public class SuperCustomView extends FrameLayout {
    private OnToggleListener mToggleListener;

    public interface OnToggleListener {
        void onToggle(boolean switchPosition);
    }

    public void setOnToggleListener(OnToggleListener listener) {
        mToggleListener = listener;
    }
    .../...
 }

我正在尝试使用此自定义视图并将onToggle 事件与以下内容绑定:

<data>
    <variable
        name="controller"
        type="com.xxx.BlopController"/>
</data>

<com.company.views.SuperCustomView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       app:onToggle="@{controller.toggleStrokeLimitation}"
       app:custom_title="Blah"
       app:custom_summary="Bloh"
       app:custom_widget="toggle"/>

toggleStrokeLimitation 是控制器上的一个方法:

public void toggleStrokeLimitation(boolean switchPosition) {
    maxStrokeEnabled.set(switchPosition);
}

编译时出现这个错误:

> java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Cannot find the setter for attribute 'app:onToggle' with parameter type java.lang.Object. file:/path/to/androidapp/app/src/main/res/layout/fragment_stroke.xml loc:36:35 - 36:67 ****\ data binding error ****

我尝试使用android:onToggle 而不是app:onToggle,但得到了同样的错误。

阅读binding events section of the doc 时,我觉得我可以将控制器的任何方法连接到onToggle 事件。

框架是否将controller.toggleStrokeLimitation 方法包装到SuperCustomView.OnToggleListener 中?关于框架提供的现有onClick 背后的魔法类型的任何提示?

【问题讨论】:

  • 尝试为 onToggle 属性 developer.android.com/tools/data-binding/… 实现自定义设置器,并确保 controller.toggleStrokeLimitation 是 OnToggleListener 类型
  • controller.toggleStrokeLimitation 的类型是什么?好像是 Object 而你的 setter 期望 OnToggleListener
  • 你说得对,我可以这样做,但我想将事件映射到自定义方法。就像developer.android.com/tools/data-binding/… 中解释的那样,我将根据我的推理编辑问题。

标签: android data-binding android-databinding


【解决方案1】:
@BindingMethods(@BindingMethod(type = SuperCustomView.class, attribute = "app:onToggle", method = "setOnToggleListener"))
public class SuperCustomView extends FrameLayout {
    private OnToggleListener mToggleListener;

    public interface OnToggleListener {
        void onToggle(boolean switchPosition);
    }

    public void setOnToggleListener(OnToggleListener listener) {
        mToggleListener = listener;
    }
    .../...
}

我测试代码的技巧是:

public void setOnToggleListener(final OnToggleListener listener) {
    this.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            toggle = !toggle;
            listener.onToggle(toggle);
        }
    });
}

在我的控制器对象上:

 public class MyController {

    private Context context;

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

    public void toggleStrokeLimitation(boolean switchPosition) {
        Toast.makeText(context, "Toggle" + switchPosition, Toast.LENGTH_SHORT).show();
    }
}

是的!成功了

或者,您可以使用 xml,例如:

 <com.androidbolts.databindingsample.model.SuperCustomView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:onToggleListener="@{controller.toggleStrokeLimitation}" />

现在不需要添加@BindingMethods 注解了。

文档说: "Some attributes have setters that don't match by name. For these methods, an attribute may be associated with the setter through BindingMethods annotation. This must be associated with a class and contains BindingMethod annotations, one for each renamed method. "

【讨论】:

  • 正是我想要的:)
  • 当我在界面中有两个方法时,即使我在自定义小部件类的顶部添加绑定方法,它也会给我错误。
  • @AsadMukhtar 每个接口使用一种方法.... 是 Android 的做事方式。在此处检查来自 android 的代码:android.googlesource.com/platform/frameworks/data-binding/+/…
【解决方案2】:

可能不需要 BindingMethods 用于在自定义视图上侦听侦听器,如果您按照 Java bean 格式正确定义方法名称。 这是一个例子

CustomView 类

public class CustomView extends LinearLayout {
    ...
    private OnCustomViewListener onCustomViewListener;

    ...
    public void setOnCustomViewListener(OnCustomViewListener onCustomViewListener) {
        this.onCustomViewListener = onCustomViewListener;
    }


    ....
    public interface OnCustomViewListener {
        void onCustomViewListenerMethod(int aNumber);
    }
}

XML

<...CustomView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:onCustomViewListener="@{viewModel.viewModelListenerMethod}" // or use can use app:onCustomViewListener="@{viewModel::viewModelListenerMethod}"
    />

视图模型

public class ViewModel extends BaseObservable{

    public void viewModelListenerMethod(int aNumber){
       // handle listener here
    }
}

【讨论】:

  • 不错的解决方案!如果 OnCustomViewListener 接口包含多个方法怎么办?
猜你喜欢
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 2013-01-06
  • 2014-05-21
相关资源
最近更新 更多