Android Event Listener Data Binding for ViewPager

匿名 (未验证) 提交于 2019-12-03 08:44:33

问题:

Is it possible to bind a handler for setOnPageChangeListener to a ViewPager in XML file with the Android Binding functionality?

The demos show onClick events but I am curious as to how much event functionality I can implement with it. Any links on the capabilities of Data Binding would be great as well. Thanks.

Hypothetical example:

example_activity.xml

<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android">  <data>    <variable name="handlers" type="com.example.Handlers"/> </data>  <android.support.v4.view.ViewPager     android:id="@+id/pager"     xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent"      android:onPageChangeListener="@{handlers.pageChanged}" /> </layout> 

Handler.java

package com.example.viewmodels;  import android.view.View;  public class Handlers {     public void pageChanged(View view){} } 

The compilation error is:

Error:(62) No resource identifier found for attribute 'onPageChangeListener' in package 'android'

回答1:

It is possible to do this. You need to implement a custom binding adapter because there is no BindingAdapter classes predefined for View classes from Android support libraries.

For how to implement the custom adapter you may read this.

The code should be something like the below, I haven't tested them thoroughly:

<android.support.v4.view.ViewPager     android:id="@+id/pager"     xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent"     app:onPageChangeListener="@{handlers}" /> 

Your BindingAapter code:

@BindingAdapter("onPageChangeListener") public static void setOnPageChangeListener(ViewPager viewPager, ViewPager.OnPageChangeListener listener) {     Log.i("setOnPageChangeListener");      // clear listeners first avoid adding duplicate listener upon calling notify update related code     viewPager.clearOnPageChangeListeners();     viewPager.addOnPageChangeListener(listener); } 

P.S. Your handler class being passed should implements ViewPager.OnPageChangeListener.



回答2:

Here is ultimate solution. Just put this class in your project.

@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();     } } 

Also add id resource in your resources.

<resources>     <item name="page_change_listener" type="id"/> </resources> 

Then you will be able to use it in xml like:

<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}"/> 

As you can see, currentPage has inverse binding, so your viewModel will be able to set current page and also get current page if user swipes.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!