com.qs.qswlw.view.Mypager.UltraViewPagerView.java Source code

Java tutorial

Introduction

Here is the source code for com.qs.qswlw.view.Mypager.UltraViewPagerView.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.qs.qswlw.view.Mypager;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import com.qs.qswlw.view.Mypager.transformer.UltraVerticalTransformer;

/**
 * Created by mikeafc on 15/11/25.
 */
public class UltraViewPagerView extends ViewPager implements UltraViewPagerAdapter.UltraViewPagerCenterListener {

    private UltraViewPagerAdapter pagerAdapter;

    //Internal state to schedule a new measurement pass.
    private boolean needsMeasurePage;

    private float multiScrRatio = Float.NaN;
    private boolean enableLoop;
    private boolean autoMeasureHeight;
    private double itemRatio = Double.NaN;
    private int constrainLength;

    private int itemMarginLeft;
    private int itemMarginTop;
    private int itemMarginRight;
    private int itemMarginBottom;

    private float ratio = Float.NaN;

    private UltraViewPager.ScrollMode scrollMode = UltraViewPager.ScrollMode.HORIZONTAL;

    public UltraViewPagerView(Context context) {
        super(context);
        init(context, null);
    }

    public UltraViewPagerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        setClipChildren(false);
        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        onMeasurePage(widthMeasureSpec, heightMeasureSpec);
    }

    protected void onMeasurePage(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d("TEST", "onMeasurePage" + getCurrentItem());
        View child = pagerAdapter.getViewAtPosition(getCurrentItem());
        if (child == null) {
            child = getChildAt(0);
        }
        if (child == null) {
            return;
        }
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            if ((view.getPaddingLeft() != itemMarginLeft || view.getPaddingTop() != itemMarginTop
                    || view.getPaddingRight() != itemMarginRight || view.getPaddingBottom() != itemMarginBottom)) {
                view.setPadding(itemMarginLeft, itemMarginTop, itemMarginRight, itemMarginBottom);
            }
        }

        ViewGroup.LayoutParams lp = child.getLayoutParams();
        final int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
        final int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);

        int childWidth = (int) ((MeasureSpec.getSize(childWidthSpec) - getPaddingLeft() - getPaddingRight())
                * pagerAdapter.getPageWidth(getCurrentItem()));
        int childHeight = MeasureSpec.getSize(childHeightSpec) - getPaddingTop() - getPaddingBottom();

        if (!needsMeasurePage || childWidth == 0 && childHeight == 0) {
            return;
        }

        if (!Double.isNaN(itemRatio)) {
            int itemHeight = (int) (childWidth / itemRatio);
            for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
                View view = getChildAt(i);
                view.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(itemHeight, MeasureSpec.EXACTLY));
            }
        } else {
            for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
                View view = getChildAt(i);
                if (pagerAdapter.getPageWidth(getCurrentItem()) != 1) {
                    view.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
                            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                } else {
                    view.measure(childWidthSpec, childHeightSpec);
                }
            }
        }

        final boolean isHorizontalScroll = scrollMode == UltraViewPager.ScrollMode.HORIZONTAL;

        childWidth = itemMarginLeft + child.getMeasuredWidth() + itemMarginRight;
        childHeight = itemMarginTop + child.getMeasuredHeight() + itemMarginBottom;

        if (!Float.isNaN(ratio)) {
            heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (getMeasuredWidth() / ratio),
                    MeasureSpec.EXACTLY);
            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
            for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
                View view = getChildAt(i);
                view.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
            }
        } else {
            if (autoMeasureHeight) {
                if (isHorizontalScroll) {
                    constrainLength = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);
                    setMeasuredDimension(getMeasuredWidth(), childHeight);
                } else {
                    constrainLength = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
                    setMeasuredDimension(childWidth, getMeasuredHeight());
                }

                needsMeasurePage = childHeight == itemMarginTop + itemMarginBottom;
            }
        }

        if (!pagerAdapter.isEnableMultiScr()) {
            return;
        }

        int pageLength = isHorizontalScroll ? getMeasuredWidth() : getMeasuredHeight();

        final int childLength = isHorizontalScroll ? child.getMeasuredWidth() : child.getMeasuredHeight();

        // Check that the measurement was successful
        if (childLength > 0) {
            needsMeasurePage = false;
            int difference = pageLength - childLength;
            if (getPageMargin() == 0) {
                setPageMargin(-difference);
            }
            int offscreen = (int) Math.ceil((float) pageLength / (float) childLength) + 1;
            setOffscreenPageLimit(offscreen);
            requestLayout();
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // Schedule a new measurement pass as the dimensions have changed
        needsMeasurePage = true;
    }

    @Override
    public void setAdapter(PagerAdapter adapter) {
        if (adapter != null) {
            pagerAdapter = new UltraViewPagerAdapter(adapter);
            pagerAdapter.setCenterListener(this);
            pagerAdapter.setEnableLoop(enableLoop);
            pagerAdapter.setMultiScrRatio(multiScrRatio);
            needsMeasurePage = true;
            constrainLength = 0;
            super.setAdapter(pagerAdapter);
        } else {
            super.setAdapter(adapter);
        }
    }

    @Override
    public void setCurrentItem(int item) {
        setCurrentItem(item, false);
    }

    @Override
    public void setCurrentItem(int item, boolean smoothScroll) {
        if (pagerAdapter.getCount() != 0 && pagerAdapter.isEnableLoop()) {
            item = pagerAdapter.getCount() / 2 + item % pagerAdapter.getRealCount();
        }
        super.setCurrentItem(item, smoothScroll);
    }

    @Override
    public int getCurrentItem() {
        if (pagerAdapter.getCount() != 0) {
            int position = super.getCurrentItem();
            return position % pagerAdapter.getRealCount();
        }
        return super.getCurrentItem();
    }

    /**
     * Set the currently selected page.
     *
     * @param item         Item index to select
     * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately
     */
    void setCurrentItemFake(int item, boolean smoothScroll) {
        super.setCurrentItem(item, smoothScroll);
    }

    /**
     * Get the currently selected page.
     */
    int getCurrentItemFake() {
        return super.getCurrentItem();
    }

    public void setMultiScreen(float ratio) {
        multiScrRatio = ratio;
        if (pagerAdapter != null) {
            pagerAdapter.setMultiScrRatio(ratio);
            needsMeasurePage = true;
        }
        float pageMargin = (1 - ratio) * getResources().getDisplayMetrics().widthPixels;
        if (scrollMode == UltraViewPager.ScrollMode.VERTICAL) {
            setPageMargin((int) (pageMargin));
        } else {
            setPageMargin((int) (-(pageMargin + convertDp2Px(getContext(), 1f))));
        }

    }

    private int convertDp2Px(Context context, float dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                context.getResources().getDisplayMetrics());
    }

    public void setEnableLoop(boolean status) {
        enableLoop = status;
        if (pagerAdapter != null) {
            pagerAdapter.setEnableLoop(enableLoop);
        }
    }

    public void setItemRatio(double itemRatio) {
        this.itemRatio = itemRatio;
    }

    public void setAutoMeasureHeight(boolean autoMeasureHeight) {
        this.autoMeasureHeight = autoMeasureHeight;
    }

    public void setScrollMode(UltraViewPager.ScrollMode scrollMode) {
        this.scrollMode = scrollMode;
        if (scrollMode == UltraViewPager.ScrollMode.VERTICAL)
            setPageTransformer(false, new UltraVerticalTransformer());
    }

    public UltraViewPager.ScrollMode getScrollMode() {
        return scrollMode;
    }

    public int getConstrainLength() {
        return constrainLength;
    }

    public void setItemMargin(int left, int top, int right, int bottom) {
        itemMarginLeft = left;
        itemMarginTop = top;
        itemMarginRight = right;
        itemMarginBottom = bottom;
    }

    public float getRatio() {
        return ratio;
    }

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

    @Override
    public void center() {
        setCurrentItem(0);
    }

    @Override
    public void resetPosition() {
        setCurrentItem(getCurrentItem());
    }

    private MotionEvent swapTouchEvent(MotionEvent event) {
        float width = getWidth();
        float height = getHeight();

        float swappedX = (event.getY() / height) * width;
        float swappedY = (event.getX() / width) * height;

        event.setLocation(swappedX, swappedY);

        return event;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (scrollMode == UltraViewPager.ScrollMode.VERTICAL) {
            boolean intercept = super.onInterceptTouchEvent(swapTouchEvent(ev));
            //If not intercept, touch event should not be swapped.
            swapTouchEvent(ev);
            return intercept;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (scrollMode == UltraViewPager.ScrollMode.VERTICAL)
            return super.onTouchEvent(swapTouchEvent(ev));
        return super.onTouchEvent(ev);
    }
}