Android Event Listener Data Binding for ViewPager

后端 未结 3 1995
猫巷女王i
猫巷女王i 2021-01-02 03:36

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

3条回答
  •  傲寒
    傲寒 (楼主)
    2021-01-02 03:54

    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.

    
        
    
    

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

    
    

    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.

提交回复
热议问题