数据绑定:使用多种方法从侦听器绑定单个方法

Olu*_*ide 10 data-binding android android-databinding

Android UI Toolkit团队的Yigit Boyar和George Mount成员就数据绑定进行了讨论.在13:41的视频中,乔治山说这个

你也可以做一些奇怪的听众,比如onTextChanged.TextWatcher有三种方法,但每个人都只关心onTextChanged,对吧?如果需要,您实际上只能访问其中一个或全部."

<Button android:onTextChanged="@{handlers.textChanged}" …/>
Run Code Online (Sandbox Code Playgroud)

他似乎在说,而不是使用看起来像这样的通常的addTextChangedListener方法

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        //Do something
    }

    @Override
    public void afterTextChanged(Editable editable) {}
});
Run Code Online (Sandbox Code Playgroud)

我们可以简单地这样做

<EditText 
    android:onTextChanged="@{handlers::onTextChanged}"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
Run Code Online (Sandbox Code Playgroud)

处理程序类

public class Handlers{
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        //Do something
    }
}
Run Code Online (Sandbox Code Playgroud)

代码在这个实例中起作用,但它似乎不适用于监听器有多个方法的其他情况,例如ViewPager的addOnPageChangeListener方法.例如,这不起作用

<android.support.v4.view.ViewPager
    android:OnPageSelected="@{handlers::onPageSelected}"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
Run Code Online (Sandbox Code Playgroud)

和Handlers类

public class Handlers{
    public void onPageSelected(int position) {
        //Do something
    }
}
Run Code Online (Sandbox Code Playgroud)

该项目在尝试构建时吐出此错误

Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Could not resolve handlers::onPageSelected as a listener.

****\ data binding error ****
Run Code Online (Sandbox Code Playgroud)

我现在有点困惑,因为事实证明EditText实际上有一个继承的onTextChanged方法,数据绑定库也可以绑定android:onTextChanged="@{handlers::onTextChanged}"到该方法.

所以我的问题是,它实际上是否可能绑定到单个侦听器方法而我错过了什么,或者George Mount在他的谈话中犯了错误?

Geo*_*unt 11

让我们希望这不是谈话中的错误:-)

看起来我们没有实现它ViewPager.实施并不太难.有一个技巧 - 您必须为每个匹配方法声明一个接口.

public interface OnPageScrollStateChanged {
    void onPageScrollStateChanged(int state);
}
public interface OnPageScrolled {
    void onPageScrolled(int position, float offset, int offsetPixels);
}
public interface OnPageSelected {
    void onPageSelected(int position);
}
Run Code Online (Sandbox Code Playgroud)

然后应该为事件创建绑定适配器:

@BindingAdapter(value = {"android:onPageScrollStateChanged",
                         "android:onPageScrolled",
                         "android:onPageSelected"}, requireAll=false)
public static void setViewPagerListeners(ViewPager view,
        final OnPageScrollStateChanged scrollStateChanged,
        final OnPageScrolled scrolled,
        final OnPageSelected selected) {
    OnPageChangeListener newListener = null;
    if (scrollStateChanged != null || scrolled != null || selected != null) {
        newListener = new OnPageChangeListener() {
            @Override
            public void onPageScrollStateChanged(int state) {
                if (scrollStateChanged != null) {
                    scrollStateChanged.onPageScrollStateChanged(state);
                }
            }
            // similar with the other two methods ...
        };
    }

    OnPageChangeListener oldListener = ListenerUtil.trackListener(view,
        newListener, R.id.viewPagerListener);
    if (oldListener != null) {
        view.removeOnPageChangeListener(oldListener);
    }
    if (newListener != null) {
        view.addOnPageChangeListener(newListener);
    }
}
Run Code Online (Sandbox Code Playgroud)