com.tmall.ultraviewpager.UltraViewPager.java Source code

Java tutorial

Introduction

Here is the source code for com.tmall.ultraviewpager.UltraViewPager.java

Source

/*
 *
 *  MIT License
 *
 *  Copyright (c) 2017 Alibaba Group
 *
 *  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.tmall.ultraviewpager;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.os.Build;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

/**
 * Created by mikeafc on 15/10/26.<br>
 * UltraViewPager is a super extension for ViewPager.<br>
 * It's actually a RelativeLayout in order to display indicator, UltraViewPager offers some usual
 * method delegate for ViewPager, you can also invoke more method by call getViewPager() and get the actual
 * ViewPager.
 */
public class UltraViewPager extends RelativeLayout implements IUltraViewPagerFeature {

    public enum ScrollMode {
        HORIZONTAL(0), VERTICAL(1);
        int id;

        ScrollMode(int id) {
            this.id = id;
        }

        static ScrollMode getScrollMode(int id) {
            for (ScrollMode scrollMode : values()) {
                if (scrollMode.id == id)
                    return scrollMode;
            }
            throw new IllegalArgumentException();
        }
    }

    public enum Orientation {
        HORIZONTAL, VERTICAL
    }

    public enum ScrollDirection {
        NONE(0), BACKWARD(1), FORWARD(2);
        int id;

        ScrollDirection(int id) {
            this.id = id;
        }

        static ScrollDirection getScrollDirection(int id) {
            for (ScrollDirection direction : values()) {
                if (direction.id == id)
                    return direction;
            }
            throw new IllegalArgumentException();
        }
    }

    private final Point size;
    private final Point maxSize;

    private float ratio = Float.NaN;

    //Maximum width of child when enable multiScreen.
    private int maxWidth = -1;

    //Maximum height of child when enable multiScreen.
    private int maxHeight = -1;

    private UltraViewPagerView viewPager;
    private UltraViewPagerIndicator pagerIndicator;

    private TimerHandler timer;

    public UltraViewPager(Context context) {
        super(context);
        size = new Point();
        maxSize = new Point();
        initView();
    }

    public UltraViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        size = new Point();
        maxSize = new Point();
        initView();
        initView(context, attrs);
    }

    public UltraViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        size = new Point();
        maxSize = new Point();
        initView();
    }

    private void initView() {
        viewPager = new UltraViewPagerView(getContext());
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            viewPager.setId(viewPager.hashCode());
        } else {
            viewPager.setId(View.generateViewId());
        }

        addView(viewPager, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT));
    }

    private void initView(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.UltraViewPager);
        setAutoScroll(ta.getInt(R.styleable.UltraViewPager_upv_autoscroll, 0));
        setInfiniteLoop(ta.getBoolean(R.styleable.UltraViewPager_upv_infiniteloop, false));
        setRatio(ta.getFloat(R.styleable.UltraViewPager_upv_ratio, Float.NaN));
        setScrollMode(ScrollMode.getScrollMode(ta.getInt(R.styleable.UltraViewPager_upv_scrollmode, 0)));
        disableScrollDirection(
                ScrollDirection.getScrollDirection(ta.getInt(R.styleable.UltraViewPager_upv_disablescroll, 0)));
        setMultiScreen(ta.getFloat(R.styleable.UltraViewPager_upv_multiscreen, 1f));
        setAutoMeasureHeight(ta.getBoolean(R.styleable.UltraViewPager_upv_automeasure, false));
        setItemRatio(ta.getFloat(R.styleable.UltraViewPager_upv_itemratio, Float.NaN));
        ta.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (!Float.isNaN(ratio)) {
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (widthSize / ratio), MeasureSpec.EXACTLY);
        }
        size.set(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
        if (maxWidth >= 0 || maxHeight >= 0) {
            maxSize.set(maxWidth, maxHeight);
            constrainTo(size, maxSize);
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(size.x, MeasureSpec.EXACTLY);
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(size.y, MeasureSpec.EXACTLY);
        }
        if (viewPager.getConstrainLength() > 0) {
            if (viewPager.getConstrainLength() == heightMeasureSpec) {
                viewPager.measure(widthMeasureSpec, heightMeasureSpec);
                setMeasuredDimension(size.x, size.y);
            } else {
                if (viewPager.getScrollMode() == ScrollMode.HORIZONTAL) {
                    super.onMeasure(widthMeasureSpec, viewPager.getConstrainLength());
                } else {
                    super.onMeasure(viewPager.getConstrainLength(), heightMeasureSpec);
                }
            }
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startTimer();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        stopTimer();
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        if (visibility == VISIBLE) {
            startTimer();
        } else {
            stopTimer();
        }
    }

    @Override
    public void onStartTemporaryDetach() {
        super.onStartTemporaryDetach();
        stopTimer();
    }

    @Override
    public void onFinishTemporaryDetach() {
        super.onFinishTemporaryDetach();
        startTimer();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (timer != null) {
            final int action = ev.getAction();
            if (action == MotionEvent.ACTION_DOWN)
                stopTimer();
            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)
                startTimer();
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public IUltraIndicatorBuilder initIndicator() {
        disableIndicator();
        pagerIndicator = new UltraViewPagerIndicator(getContext());
        pagerIndicator.setViewPager(viewPager);
        pagerIndicator.setIndicatorBuildListener(new UltraViewPagerIndicator.UltraViewPagerIndicatorListener() {
            @Override
            public void build() {
                removeView(pagerIndicator);
                addView(pagerIndicator, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT));
            }
        });
        return pagerIndicator;
    }

    @Override
    public IUltraIndicatorBuilder initIndicator(int focusColor, int normalColor, int radiusInPixel, int gravity) {
        return initIndicator().setFocusColor(focusColor).setNormalColor(normalColor).setRadius(radiusInPixel)
                .setGravity(gravity);
    }

    @Override
    public IUltraIndicatorBuilder initIndicator(int focusColor, int normalColor, int strokeColor, int strokeWidth,
            int radiusInPixel, int gravity) {
        return initIndicator().setFocusColor(focusColor).setNormalColor(normalColor).setStrokeWidth(strokeWidth)
                .setStrokeColor(strokeColor).setRadius(radiusInPixel).setGravity(gravity);
    }

    @Override
    public IUltraIndicatorBuilder initIndicator(int focusResId, int normalResId, int gravity) {
        return initIndicator().setFocusResId(focusResId).setNormalResId(normalResId).setGravity(gravity);
    }

    @Override
    public IUltraIndicatorBuilder initIndicator(Bitmap focusBitmap, Bitmap normalBitmap, int gravity) {
        return initIndicator().setFocusIcon(focusBitmap).setNormalIcon(normalBitmap).setGravity(gravity);
    }

    @Override
    public void disableIndicator() {
        if (pagerIndicator != null) {
            removeView(pagerIndicator);
            pagerIndicator = null;
        }
    }

    public IUltraIndicatorBuilder getIndicator() {
        return pagerIndicator;
    }

    private TimerHandler.TimerHandlerListener mTimerHandlerListener = new TimerHandler.TimerHandlerListener() {
        @Override
        public void callBack() {
            scrollNextPage();
        }
    };

    @Override
    public void setAutoScroll(int intervalInMillis) {
        if (0 == intervalInMillis)
            return;
        if (timer != null) {
            disableAutoScroll();
        }
        timer = new TimerHandler(mTimerHandlerListener, intervalInMillis);
        startTimer();
    }

    @Override
    public void disableAutoScroll() {
        stopTimer();
        timer = null;
    }

    @Override
    public void setScrollMode(ScrollMode scrollMode) {
        viewPager.setScrollMode(scrollMode);
    }

    @Override
    public void setInfiniteLoop(boolean enableLoop) {
        viewPager.setEnableLoop(enableLoop);
    }

    @Override
    public void setMaxWidth(int width) {
        maxWidth = width;
    }

    @Override
    public void setRatio(float ratio) {
        this.ratio = ratio;
        viewPager.setRatio(ratio);
    }

    @Override
    public void setHGap(int pixel) {
        int screenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
        viewPager.setMultiScreen((screenWidth - pixel) / (float) screenWidth);
        viewPager.setPageMargin(pixel);
    }

    @Override
    public void setMaxHeight(int height) {
        maxHeight = height;
    }

    @Override
    public void disableScrollDirection(UltraViewPager.ScrollDirection direction) {

    }

    @Override
    public void scrollNextPage() {
        if (viewPager != null && viewPager.getAdapter() != null && viewPager.getAdapter().getCount() > 0) {
            final int curr = viewPager.getCurrentItemFake();
            int nextPage = 0;
            if (curr < viewPager.getAdapter().getCount() - 1) {
                nextPage = curr + 1;
            }
            viewPager.setCurrentItemFake(nextPage, true);
        }
    }

    @Override
    public void setMultiScreen(float ratio) {
        if (ratio <= 0 || ratio > 1) {
            throw new IllegalArgumentException("");
        }
        if (ratio <= 1f) {
            viewPager.setMultiScreen(ratio);
        }
    }

    @Override
    public void setAutoMeasureHeight(boolean status) {
        viewPager.setAutoMeasureHeight(status);
    }

    @Override
    public void setItemRatio(double ratio) {
        viewPager.setItemRatio(ratio);
    }

    @Override
    public void setItemMargin(int left, int top, int right, int bottom) {
        viewPager.setItemMargin(left, top, right, bottom);
    }

    @Override
    public void setScrollMargin(int left, int right) {
        viewPager.setPadding(left, 0, right, 0);
    }

    /**
     * delegate viewpager
     */

    public void setAdapter(PagerAdapter adapter) {
        viewPager.setAdapter(adapter);
    }

    public void setOffscreenPageLimit(int limit) {
        viewPager.setOffscreenPageLimit(limit);
    }

    public PagerAdapter getAdapter() {
        return viewPager.getAdapter() == null ? null
                : ((UltraViewPagerAdapter) viewPager.getAdapter()).getAdapter();
    }

    public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
        if (pagerIndicator == null) {
            viewPager.addOnPageChangeListener(listener);
        } else {
            pagerIndicator.setPageChangeListener(listener);
        }
    }

    public void setCurrentItem(int item) {
        viewPager.setCurrentItem(item);
    }

    public void setCurrentItem(int item, boolean smoothScroll) {
        viewPager.setCurrentItem(item, smoothScroll);
    }

    public int getCurrentItem() {
        return viewPager.getCurrentItem();
    }

    public void setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) {
        viewPager.setPageTransformer(reverseDrawingOrder, transformer);
    }

    public ViewPager getViewPager() {
        return viewPager;
    }

    private void constrainTo(Point size, Point maxSize) {
        if (maxSize.x >= 0) {
            if (size.x > maxSize.x) {
                size.x = maxSize.x;
            }
        }
        if (maxSize.y >= 0) {
            if (size.y > maxSize.y) {
                size.y = maxSize.y;
            }
        }
    }

    private void startTimer() {
        if (timer == null || !timer.isStopped)
            return;
        timer.listener = mTimerHandlerListener;
        timer.removeCallbacksAndMessages(null);
        timer.sendEmptyMessageDelayed(TimerHandler.MSG_TIMER_ID, timer.interval);
        timer.isStopped = false;
    }

    private void stopTimer() {
        if (timer == null || timer.isStopped)
            return;
        timer.removeCallbacksAndMessages(null);
        timer.listener = null;
        timer.isStopped = true;
    }

    @Override
    public void setInfiniteRatio(int infiniteRatio) {
        if (viewPager.getAdapter() != null && viewPager.getAdapter() instanceof UltraViewPagerAdapter) {
            ((UltraViewPagerAdapter) viewPager.getAdapter()).setInfiniteRatio(infiniteRatio);
        }
    }
}