Ecco la soluzione definitiva. Metti solo questa lezione nel tuo progetto.
@BindingMethods({
@BindingMethod(type = ViewPager.class, attribute = "android:offscreenPageLimit", method = "setOffscreenPageLimit"),
@BindingMethod(type = ViewPager.class, attribute = "android:adapter", method = "setAdapter"),
@BindingMethod(type = ViewPager.class, attribute = "android:currentPage", method = "setCurrentItem"),
})
public final class ViewPagerBindingAdapter {
@InverseBindingAdapter(attribute = "android:currentPage", event = "android:currentPageAttrChanged")
public static int getCurrentPage(@NonNull final ViewPager pager) {
return pager.getCurrentItem();
}
@BindingAdapter(value = {"android:onPageScrolled", "android:onPageSelected", "android:onPageScrollStateChanged",
"android:currentPageAttrChanged"}, requireAll = false)
public static void onSetAdapter(@NonNull final ViewPager pager, final OnPageScrolled scrolled, final OnPageSelected selected,
final OnPageScrollStateChanged scrollStateChanged, final InverseBindingListener currentPageAttrChanged) {
final ViewPager.OnPageChangeListener newValue;
if (scrolled == null && selected == null && scrollStateChanged == null && currentPageAttrChanged == null) {
newValue = null;
} else {
newValue = new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
if (scrolled != null) {
scrolled.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
@Override
public void onPageSelected(final int position) {
if (selected != null) {
selected.onPageSelected(position);
}
if (currentPageAttrChanged != null) {
currentPageAttrChanged.onChange();
}
}
@Override
public void onPageScrollStateChanged(final int state) {
if (scrollStateChanged != null) {
scrollStateChanged.onPageScrollStateChanged(state);
}
}
};
}
final ViewPager.OnPageChangeListener oldValue = ListenerUtil.trackListener(pager, newValue, R.id.page_change_listener);
if (oldValue != null) {
pager.removeOnPageChangeListener(oldValue);
}
if (newValue != null) {
pager.addOnPageChangeListener(newValue);
}
}
public interface OnPageScrolled {
void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
}
public interface OnPageSelected {
void onPageSelected(int position);
}
public interface OnPageScrollStateChanged {
void onPageScrollStateChanged(int state);
}
private ViewPagerBindingAdapter() {
throw new UnsupportedOperationException();
}
}
Aggiungere anche la risorsa id nelle risorse.
<resources>
<item name="page_change_listener" type="id"/>
</resources>
Allora si sarà in grado di usarlo in XML come:
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:currentPage="@={viewModel.currentPage}"
android:offscreenPageLimit="@{viewModel.offscreenPageLimit}"
android:onPageSelected="@{currentPage -> viewModel.pageSelected(currentPage)}"
android:adapter="@{adapter}"/>
Come si può vedere, currentPage
ha inversa vincolante, così il vostro ViewModel sarà in grado di impostare la pagina corrente e anche corrente ottenere pagina se l'utente fa scorrere.
Soluzione non buona. Poiché ViewPager aggiunge OnPageChangeListener a ArrayList interno, la chiamata a notifyChange() per questa proprietà consente di aggiungere più listener. – b1n0m
@ b1n0m aggiornato per rimuovere gli ascoltatori prima di aggiungere listener –