/* * MIT License * * Copyright (c) 2017 Jan Heinrich Reimer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.heinrichreimersoftware.materialintro.view; import android.content.Context; import android.database.DataSetObserver; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.v4.view.PagerAdapter; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class FadeableViewPager extends SwipeBlockableViewPager { public FadeableViewPager(Context context) { super(context); } public FadeableViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void setAdapter(PagerAdapter adapter) { super.setAdapter(new PagerAdapterWrapper(adapter)); } @Override public PagerAdapter getAdapter() { PagerAdapterWrapper wrapper = (PagerAdapterWrapper) super.getAdapter(); return wrapper == null ? null : wrapper.getAdapter(); } @SuppressWarnings("deprecation") @Deprecated @Override public void setOnPageChangeListener(OnPageChangeListener listener) { super.setOnPageChangeListener(new OnPageChangeListenerWrapper(listener)); } @Override public void addOnPageChangeListener(@NonNull OnPageChangeListener listener) { super.addOnPageChangeListener(new OnPageChangeListenerWrapper(listener)); } @Override public void removeOnPageChangeListener(@NonNull OnPageChangeListener listener) { super.removeOnPageChangeListener(new OnPageChangeListenerWrapper(listener)); } @Override public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) { super.setPageTransformer(reverseDrawingOrder, new PageTransformerWrapper(transformer, getAdapter())); } private class OnPageChangeListenerWrapper implements OnPageChangeListener { private final OnPageChangeListener listener; private OnPageChangeListenerWrapper(OnPageChangeListener listener) { this.listener = listener; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { int count = listener instanceof OnOverscrollPageChangeListener ? FadeableViewPager.super.getAdapter().getCount() : getAdapter().getCount(); listener.onPageScrolled(Math.min(position, count - 1), position < count ? positionOffset : 0, position < count ? positionOffsetPixels : 0); } @Override public void onPageSelected(int position) { int count = listener instanceof OnOverscrollPageChangeListener ? FadeableViewPager.super.getAdapter().getCount() : getAdapter().getCount(); listener.onPageSelected(Math.min(position, count - 1)); } @Override public void onPageScrollStateChanged(int state) { listener.onPageScrollStateChanged(state); } } private class PagerAdapterWrapper extends PagerAdapter { private final PagerAdapter adapter; private PagerAdapterWrapper(PagerAdapter adapter) { this.adapter = adapter; adapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { notifyDataSetChanged(); } @Override public void onInvalidated() { notifyDataSetChanged(); } }); } public PagerAdapter getAdapter() { return adapter; } @Override public int getCount() { return adapter.getCount() + 1; } @Override public boolean isViewFromObject(View view, Object object) { return object != null && adapter.isViewFromObject(view, object); } @Override public void startUpdate(ViewGroup container) { adapter.startUpdate(container); } @Override public Object instantiateItem(ViewGroup container, int position) { if (position < adapter.getCount()) return adapter.instantiateItem(container, position); return null; } @Override public void destroyItem(ViewGroup container, int position, Object object) { if (position < adapter.getCount()) adapter.destroyItem(container, position, object); } @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { if (position < adapter.getCount()) adapter.setPrimaryItem(container, position, object); } @Override public void finishUpdate(ViewGroup container) { adapter.finishUpdate(container); } @SuppressWarnings("deprecation") @Deprecated @Override public void startUpdate(View container) { adapter.startUpdate(container); } @SuppressWarnings("deprecation") @Deprecated @Override public Object instantiateItem(View container, int position) { if (position < adapter.getCount()) return adapter.instantiateItem(container, position); return null; } @SuppressWarnings("deprecation") @Deprecated @Override public void destroyItem(View container, int position, Object object) { if (position < adapter.getCount()) adapter.destroyItem(container, position, object); } @SuppressWarnings("deprecation") @Deprecated @Override public void setPrimaryItem(View container, int position, Object object) { if (position < adapter.getCount()) adapter.setPrimaryItem(container, position, object); } @SuppressWarnings("deprecation") @Deprecated @Override public void finishUpdate(View container) { adapter.finishUpdate(container); } @Override public Parcelable saveState() { return adapter.saveState(); } @Override public void restoreState(Parcelable state, ClassLoader loader) { adapter.restoreState(state, loader); } @Override public int getItemPosition(Object object) { int position = adapter.getItemPosition(object); if (position < adapter.getCount()) return position; return POSITION_NONE; } @Override public void registerDataSetObserver(DataSetObserver observer) { adapter.registerDataSetObserver(observer); } @Override public void unregisterDataSetObserver(DataSetObserver observer) { adapter.unregisterDataSetObserver(observer); } @Override public CharSequence getPageTitle(int position) { if (position < adapter.getCount()) return adapter.getPageTitle(position); return null; } @Override public float getPageWidth(int position) { if (position < adapter.getCount()) return adapter.getPageWidth(position); return 1f; } } private class PageTransformerWrapper implements PageTransformer { private final PageTransformer pageTransformer; private final PagerAdapter adapter; private PageTransformerWrapper(PageTransformer pageTransformer, PagerAdapter adapter) { this.pageTransformer = pageTransformer; this.adapter = adapter; } @Override public void transformPage(View page, float position) { pageTransformer.transformPage(page, Math.min(position, adapter.getCount() - 1)); } } public interface OnOverscrollPageChangeListener extends OnPageChangeListener { } public static class SimpleOnOverscrollPageChangeListener implements OnOverscrollPageChangeListener { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } } }