Yigit Boyar and George Mount members of the Android UI Toolkit team gave a talk on databinding. In the video at 13:41 George Mount says this
You can also do some of the weird listeners, like onTextChanged. TextWatcher has three methods on it, but everybody only cares about onTextChanged, right? You can actually access just one of them if you want, or all of them."
<Button android:onTextChanged="@{handlers.textChanged}" …/>
He seemed to be saying that instead of using the usual addTextChangedListener method that looks something like this
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) {}
});
we could simply do this
<EditText
android:onTextChanged="@{handlers::onTextChanged}"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Handlers class
public class Handlers{
public void onTextChanged(CharSequence s, int start, int before, int count) {
//Do something
}
}
The code works in this instance, but it doesn't seem to work in other cases where the listener has multiple methods like ViewPager's addOnPageChangeListener method. For example this doesn't work
<android.support.v4.view.ViewPager
android:OnPageSelected="@{handlers::onPageSelected}"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
and the Handlers class
public class Handlers{
public void onPageSelected(int position) {
//Do something
}
}
The project spits out this error when trying to build
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 ****
I'm a bit confused now because it turns out that EditText actually has an inherited onTextChanged method which the databinding library can also bind android:onTextChanged="@{handlers::onTextChanged}"
to.
So my question is that is it actually possible to bind to a single listener method and I'm missing something, or did George Mount make a mistake in his talk?
Let's hope that it wasn't a mistake in the talk :-)
It looks like we didn't implement it for ViewPager
. The implementation is not too difficult. There is a trick -- you must declare a single interface for each matching method.
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);
}
Then the binding adapter should be created for the events:
@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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With