Viewpager 的相关总结

1、修改切换item的时间

public class FixedSpeedScroller extends Scroller {  
        private int mDuration = 300;  
      
        public FixedSpeedScroller(Context context) {  
            super(context);  
        }  
      
        public FixedSpeedScroller(Context context, android.view.animation.Interpolator interpolator) {  
            super(context, interpolator);  
        }  
      
        public FixedSpeedScroller(Context context, android.view.animation.Interpolator interpolator, boolean flywheel) {  
            super(context, interpolator, flywheel);  
        }  
      
      
        @Override  
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {  
            super.startScroll(startX, startY, dx, dy, mDuration);  
        }  
      
        @Override  
        public void startScroll(int startX, int startY, int dx, int dy) {  
            super.startScroll(startX, startY, dx, dy, mDuration);  
        }  
    }
private void setViewPagerScrollSpeed(){  
        try {  
            Field mScroller = null;  
            mScroller = ViewPager.class.getDeclaredField("mScroller");  
            if(mScroller != null){
                mScroller.setAccessible(true);   
                FixedSpeedScroller scroller = new FixedSpeedScroller( getContext(), new LinearInterpolator());  
                mScroller.set(mUserInfoViewPager, scroller);  
            }
        }catch(NoSuchFieldException e){  
              
        }catch (IllegalArgumentException e){  
              
        }catch (IllegalAccessException e){  
              
        }  
    }

2、修改Item的切换动画

mUserInfoViewPager.setPageTransformer(true, new PageTransformer() {
             
            private static final float MIN_SCALE = 0.85f;  
            private static final float MIN_ALPHA = 0.5f;
             
            @Override
            public void transformPage(View view, float position) {
                // 
                int pageWidth = view.getWidth();  
                int pageHeight = view.getHeight();                
          
                if (position < -1)  {                      
                    view.setAlpha(0);  
          
                } else if (position <= 1) { 
                    //a页滑动至b页 ; a页从 0.0 -1 ;b页从1 ~ 0.0 
                    // [-1,1]  
                    // Modify the default slide transition to shrink the page as well  
                    float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));  
                    float vertMargin = pageHeight * (1 - scaleFactor) / 2;  
                    float horzMargin = pageWidth * (1 - scaleFactor) / 2;  
                    if (position < 0){  
                        view.setTranslationX(horzMargin - vertMargin / 2);  
                    } else  {  
                        view.setTranslationX(-horzMargin + vertMargin / 2);  
                    }  
          
                    // Scale the page down (between MIN_SCALE and 1)  
                    view.setScaleX(scaleFactor);  
                    view.setScaleY(scaleFactor);  
          
                    // Fade the page relative to its size.  
                    view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)/ (1 - MIN_SCALE) * (1 - MIN_ALPHA));  
          
                } else  { // (1,+Infinity]  
                    // This page is way off-screen to the right.  
                    view.setAlpha(0);  
                }  
                
            }
        });

3、ViewPager实现Gallery类似效果

package com.joyodream.pingo.near.ui;

import java.lang.reflect.Field;

import android.content.Context;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
import android.widget.Scroller;

import com.joyodream.common.util.DipPixelUtil;

/**
 * 
 * 自定义的展示图片的控件
 * 通过Camera 调整z轴距离,实现图片放大缩小
 * 
 * 注意:
 * 1、为了实现在屏幕上面看到多个Item,需要在滑动的过程中刷新父控件
 * 2、另外,通过设置clipChildren = false,不去裁剪子控件的绘图区域
 * 3、
 * 
 * @author lipeilong
 * 
 */
public class NearViewPager extends ViewPager {

    /**
     * The camera class is used to 3D transformation matrix.
     */
    private Camera mCamera = new Camera();
    
    /**
     * The max zoom value (Z axis).
     */
    private int mMaxZoom     = -120;
    
    private int mMaxAlpha    = 0x8f;

    private OnPageChangeListener mScrollListener;
    
    private int mScrollPosition;
    
    private int mScrollOffset;

    public int mCurPosition;

    private float mDownX;

    private float mDownY;

    private boolean mClick;    

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

    public NearViewPager(Context context) {
        super(context);
        //
        init();
    }

    private void init() {

        // Enable set transformation.
        this.setStaticTransformationsEnabled(true);
        // Enable set the children drawing order.
        this.setChildrenDrawingOrderEnabled(true);
        
        this.setOverScrollMode(ViewPager.OVER_SCROLL_NEVER);
        super.setOnPageChangeListener(new MyOnPageChangeListener());    
        
        setViewPagerScrollSpeed();
    }
    
    private void setViewPagerScrollSpeed(){  
        try {  
            Field mScroller = null;  
            mScroller = ViewPager.class.getDeclaredField("mScroller");  
            if(mScroller != null){
                mScroller.setAccessible(true);   
                FixedSpeedScroller scroller = new FixedSpeedScroller( getContext(), new LinearInterpolator());  
                mScroller.set(this, scroller);  
            }
        }catch(NoSuchFieldException e){  
              
        }catch (IllegalArgumentException e){  
              
        }catch (IllegalAccessException e){  
              
        }  
    }

    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        // Current selected index.
        int selectedIndex = getCurrentItem();

        if (selectedIndex < 0) {
            return i;
        }

        if (i < selectedIndex) {
            return i;
        } else if (i >= selectedIndex) {
            return childCount - 1 - i + selectedIndex;
        } else {
            return i;
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        
        super.onSizeChanged(w, h, oldw, oldh);
    }    

    @Override
    protected boolean getChildStaticTransformation(View child, Transformation t) {
        super.getChildStaticTransformation(child, t);
        t.clear();
        t.setTransformationType(Transformation.TYPE_MATRIX);
        
        int index    = findViewIndex(child);
        if(index != -1){
            transformImageBitmap(child, t, index);
        }

        return true;
    }
    
    /**
     * 
     *  找出子控件的索引
     * @param child
     * @return
     */
    private int findViewIndex(View child){
        
        int index = (Integer) child.getTag();
        
        return index;
    }
    
    /**
     *  
     *  刷新所有的子控件,通过这个来触发 getChildStaticTransformation 的调用
     *  
     */
    private void invalidateVisibleChilds() {
        for (int i = 0; i < getChildCount(); i++) {
            getChildAt(i).invalidate();            
        }        
    }

    /**
     * 
     * @param child
     * @param t
     * @param index
     */
    private void transformImageBitmap(View child, Transformation t, int index) {

        mCamera.save();

        final Matrix imageMatrix     = t.getMatrix();
        final int imageHeight         = child.getHeight();
        final int imageWidth         = child.getWidth();
        int        width            = getPageMargin() + imageWidth;
        
        if(index == mScrollPosition){ // 当前项从最大变化到最小 z轴变化范围 mMaxZoom *(1 -- 0)
            
            float dz        = mMaxZoom * ( 1- mScrollOffset * 1f / width);
            int alpha        = (int) (mMaxAlpha * mScrollOffset * 1f / width);
            mCamera.translate(0, 0, dz);

            if(child instanceof NearImageView){
                ((NearImageView)child).setShadeAlpha(alpha);
            }
            
        }else if(index == mScrollPosition + 1){ // 当前项的后一项从最小变化到最大 ,z轴变化范围 mMaxZoom * (0 -- 1)
            
            float dz         =  mMaxZoom * mScrollOffset * 1f / width;
            
            int alpha        = (int) (mMaxAlpha * ( 1- mScrollOffset * 1f / width ));
            mCamera.translate(0, 0, dz);
            
            if(child instanceof NearImageView){
                ((NearImageView)child).setShadeAlpha(alpha);
            }
            
        }else { // 当前项的后2项或者前N项大小不发生变化,z轴不变                        
            mCamera.translate(0, 0, 0);
            
            if(child instanceof NearImageView){
                ((NearImageView)child).setShadeAlpha(mMaxAlpha);
            }
        }

        mCamera.getMatrix(imageMatrix);
        
        imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));        
        imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));

        mCamera.restore();
    }
    
    @Override
    public void setOnPageChangeListener(OnPageChangeListener listener) {
        mScrollListener = listener;
    };
    
    
    
    /**
     * @author lipeilong
     *
     */
    private class MyOnPageChangeListener implements OnPageChangeListener {
        

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if (mScrollListener != null) {
                mScrollListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }
            
            mScrollPosition = position;
            mScrollOffset    = positionOffsetPixels;
            
            // 刷新子控件
            if(System.currentTimeMillis() % 2 == 0){
                
                invalidateVisibleChilds();            
            }
        }
        
        @Override
        public void onPageSelected(int position) {
            mCurPosition    = position;
            if (mScrollListener != null) {
                mScrollListener.onPageSelected(position);
            }
        }
        
        @Override
        public void onPageScrollStateChanged(final int state) {
            
            if (mScrollListener != null) {
                mScrollListener.onPageScrollStateChanged(state);
            }            
        }
    }
    
    
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // 
        final float MAX_DISTANCE    = 50;        
        switch(ev.getAction()){        
        case MotionEvent.ACTION_DOWN:
            mDownX    = ev.getRawX();
            mDownY    = ev.getRawY();
            mClick    = true;            
            break;
        case MotionEvent.ACTION_UP:
            if(mClick && Math.abs(ev.getRawX()- mDownX) < MAX_DISTANCE && Math.abs(ev.getRawY() - mDownY) < MAX_DISTANCE){
                // 点击事件
                performMyClick(ev);
                
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if(Math.abs(ev.getRawX()- mDownX) > MAX_DISTANCE || Math.abs(ev.getRawY() - mDownY) > MAX_DISTANCE){
                mClick = false;
            }
            break;
        }
            
        return super.onTouchEvent(ev);
    }
    
    private void performMyClick(MotionEvent ev){
        
        int index    = getCurrentItem();
        if(isAtLeft(ev)){
            setCurrentItem(index - 1);
        }else if(isAtRight(ev)){
            setCurrentItem(index + 1);
        }

    }
    
    
    private boolean isAtLeft(MotionEvent ev){
        int margin    = DipPixelUtil.dip2px(getContext(), 56);
        int left    = getLeft() - margin;
        int right    = getRight() + margin;
        int top        = getTop();
        int bottom    = getBottom();
        
        // 必须使用全局坐标,同时要减去title和通知栏高度
        int x        = (int) ev.getRawX();
        int y        = (int) ev.getRawY() - DipPixelUtil.dip2px(getContext(), 96);
        if(y > top && y < bottom){
            
            if(x < left){
                return true;
            }
        }
        
        return false;
    }
    
    private boolean isAtRight(MotionEvent ev){
        int margin    = DipPixelUtil.dip2px(getContext(), 56);
        int left    = getLeft() - margin;
        int right    = getRight() + margin;
        int top        = getTop();
        int bottom    = getBottom();
        
        int x        = (int) ev.getRawX();
        int y        = (int) ev.getRawY() - DipPixelUtil.dip2px(getContext(), 96);
        if(y > top && y < bottom){
            
            if(x > right){
                return true;
            }
        }
        
        return false;
    }
    
    public class FixedSpeedScroller extends Scroller {  
        private int mDuration = 300;  
      
        public FixedSpeedScroller(Context context) {  
            super(context);  
        }  
      
        public FixedSpeedScroller(Context context, android.view.animation.Interpolator interpolator) {  
            super(context, interpolator);  
        }  
      
        public FixedSpeedScroller(Context context, android.view.animation.Interpolator interpolator, boolean flywheel) {  
            super(context, interpolator, flywheel);  
        }  
      
      
        @Override  
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {  
            super.startScroll(startX, startY, dx, dy, mDuration);  
        }  
      
        @Override  
        public void startScroll(int startX, int startY, int dx, int dy) {  
            super.startScroll(startX, startY, dx, dy, mDuration);  
        }  
    }
}

注意:1、设置父控件、子控件的clipChildren=false 2、滑动的时候刷新子控件

posted @ 2015-06-15 11:44  lipeil  阅读(1562)  评论(1编辑  收藏  举报