您的位置:首页 > 移动开发 > Android开发

Android Viewpager3D广告轮播

2017-06-11 20:51 211 查看
Android Viewpager3D广告轮播

MainActivity

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

}

Image3DView

package com.example.viewpage_3d;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Camera;

import android.graphics.Canvas;

import android.graphics.Matrix;

import android.graphics.drawable.Drawable;

import android.net.Uri;

import android.util.AttributeSet;

import android.widget.ImageView;

public class Image3DView extends ImageView {  

    /** 

     * 旋转角度的基准值 

     */  

    private static final float BASE_DEGREE = 50f;  

    /** 

     * 旋转深度的基准值 

     */  

    private static final float BASE_DEEP = 150f;  

    private Camera mCamera;  

    private Matrix mMaxtrix;  

    private Bitmap mBitmap;  

    /** 

     * 当前图片对应的下标 

     */  

    private int mIndex;  

    /** 

     * 在前图片在X轴方向滚动的距离 

     */  

    private int mScrollX;  

    /** 

     * Image3DSwitchView控件的宽度 

     */  

    private int mLayoutWidth;  

    /** 

     * 当前图片的宽度 

     */  

    private int mWidth;  

    /** 

     * 当前旋转的角度 

     */  

    private float mRotateDegree;  

    /** 

     * 旋转的中心点 

     */  

    private float mDx;  

    /** 

     * 旋转的深度 

     */  

    private float mDeep;  

  

    public Image3DView(Context context, AttributeSet attrs) {  

        super(context, attrs);  

        mCamera = new Camera();  

        mMaxtrix = new Matrix();  

    }  

  

    /** 

     * 初始化Image3DView所需要的信息,包括图片宽度,截取背景图等。 

     */  

    public void initImageViewBitmap() {  

        if (mBitmap == null) {  

            setDrawingCacheEnabled(true);  

            buildDrawingCache();  

            mBitmap = getDrawingCache();  

        }  

        mLayoutWidth = Image3DSwitchView.mWidth;  

        mWidth = getWidth() + Image3DSwitchView.IMAGE_PADDING * 2;  

    }  

  

    /** 

     * 设置旋转角度。 

     *  

     * @param index 

     *            当前图片的下标 

     * @param scrollX 

     *            当前图片在X轴方向滚动的距离 

     */  

    public void setRotateData(int index
4000
, int scrollX) {  

        mIndex = index;  

        mScrollX = scrollX;  

    }  

  

    /** 

     * 回收当前的Bitmap对象,以释放内存。 

     */  

    public void recycleBitmap() {  

        if (mBitmap != null && !mBitmap.isRecycled()) {  

            mBitmap.recycle();  

        }  

    }  

  

    @Override  

    public void setImageResource(int resId) {  

        super.setImageResource(resId);  

        mBitmap = null;  

        initImageViewBitmap();  

    }  

  

    @Override  

    public void setImageBitmap(Bitmap bm) {  

        super.setImageBitmap(bm);  

        mBitmap = null;  

        initImageViewBitmap();  

    }  

  

    @Override  

    public void setImageDrawable(Drawable drawable) {  

        super.setImageDrawable(drawable);  

        mBitmap = null;  

        initImageViewBitmap();  

    }  

  

    @Override  

    public void setImageURI(Uri uri) {  

        super.setImageURI(uri);  

        mBitmap = null;  

        initImageViewBitmap();  

    }  

  

    @Override  

    protected void onDraw(Canvas canvas) {  

        if (mBitmap == null) {  

            // 如果Bitmap对象还不存在,先使用父类的onDraw方法进行绘制  

            super.onDraw(canvas);  

        } else {  

            if (isImageVisible()) {  

                // 绘图时需要注意,只有当图片可见的时候才进行绘制,这样可以节省运算效率  

                computeRotateData();  

                mCamera.save();  

                mCamera.translate(0.0f, 0.0f, mDeep);  

                mCamera.rotateY(mRotateDegree);  

                mCamera.getMatrix(mMaxtrix);  

                mCamera.restore();  

                mMaxtrix.preTranslate(-mDx, -getHeight() / 2);  

                mMaxtrix.postTranslate(mDx, getHeight() / 2);  

                canvas.drawBitmap(mBitmap, mMaxtrix, null);  

            }  

        }  

    }  

  

    /** 

     * 在这里计算所有旋转所需要的数据。 

     */  

    private void computeRotateData() {  

        float degreePerPix = BASE_DEGREE / mWidth;  

        float deepPerPix = BASE_DEEP / ((mLayoutWidth - mWidth) / 2);  

        switch (mIndex) {  

        case 0:  

            mDx = mWidth;  

            mRotateDegree = 360f - (2 * mWidth + mScrollX) * degreePerPix;  

            if (mScrollX < -mWidth) {  

                mDeep = 0;  

            } else {  

                mDeep = (mWidth + mScrollX) * deepPerPix;  

            }  

            break;  

        case 1:  

            if (mScrollX > 0) {  

                mDx = mWidth;  

                mRotateDegree = (360f - BASE_DEGREE) - mScrollX * degreePerPix;  

                mDeep = mScrollX * deepPerPix;  

            } else {  

                if (mScrollX < -mWidth) {  

                    mDx = -Image3DSwitchView.IMAGE_PADDING * 2;  

                    mRotateDegree = (-mScrollX - mWidth) * degreePerPix;  

                } else {  

                    mDx = mWidth;  

                    mRotateDegree = 360f - (mWidth + mScrollX) * degreePerPix;  

                }  

                mDeep = 0;  

            }  

            break;  

        case 2:  

            if (mScrollX > 0) {  

                mDx = mWidth;  

                mRotateDegree = 360f - mScrollX * degreePerPix;  

                mDeep = 0;  

                if (mScrollX > mWidth) {  

                    mDeep = (mScrollX - mWidth) * deepPerPix;  

                }  

            } else {  

                mDx = -Image3DSwitchView.IMAGE_PADDING * 2;  

                mRotateDegree = -mScrollX * degreePerPix;  

                mDeep = 0;  

                if (mScrollX < -mWidth) {  

                    mDeep = -(mWidth + mScrollX) * deepPerPix;  

                }  

            }  

            break;  

        case 3:  

            if (mScrollX < 0) {  

                mDx = -Image3DSwitchView.IMAGE_PADDING * 2;  

                mRotateDegree = BASE_DEGREE - mScrollX * degreePerPix;  

                mDeep = -mScrollX * deepPerPix;  

            } else {  

                if (mScrollX > mWidth) {  

                    mDx = mWidth;  

                    mRotateDegree = 360f - (mScrollX - mWidth) * degreePerPix;  

                } else {  

                    mDx = -Image3DSwitchView.IMAGE_PADDING * 2;  

                    mRotateDegree = BASE_DEGREE - mScrollX * degreePerPix;  

                }  

                mDeep = 0;  

            }  

            break;  

        case 4:  

            mDx = -Image3DSwitchView.IMAGE_PADDING * 2;  

            mRotateDegree = (2 * mWidth - mScrollX) * degreePerPix;  

            if (mScrollX > mWidth) {  

                mDeep = 0;  

            } else {  

                mDeep = (mWidth - mScrollX) * deepPerPix;  

            }  

            break;  

        }  

    }  

  

    /** 

     * 判断当前图片是否可见。 

     *  

     * @return 当前图片可见返回true,不可见返回false。 

     */  

    private boolean isImageVisible() {  

        boolean isVisible = false;  

        switch (mIndex) {  

        case 0:  

            if (mScrollX < (mLayoutWidth - mWidth) / 2 - mWidth) {  

                isVisible = true;  

            } else {  

                isVisible = false;  

            }  

            break;  

        case 1:  

            if (mScrollX > (mLayoutWidth - mWidth) / 2) {  

                isVisible = false;  

            } else {  

                isVisible = true;  

            }  

            break;  

        case 2:  

            if (mScrollX > mLayoutWidth / 2 + mWidth / 2  

                    || mScrollX < -mLayoutWidth / 2 - mWidth / 2) {  

                isVisible = false;  

            } else {  

                isVisible = true;  

            }  

            break;  

        case 3:  

            if (mScrollX < -(mLayoutWidth - mWidth) / 2) {  

                isVisible = false;  

            } else {  

                isVisible = true;  

            }  

            break;  

        case 4:  

            if (mScrollX > mWidth - (mLayoutWidth - mWidth) / 2) {  

                isVisible = true;  

            } else {  

                isVisible = false;  

            }  

            break;  

        }  

        return isVisible;  

    }  

}  

Image3DSwitchView

package com.example.viewpage_3d;

import android.content.Context;

import android.os.Handler;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.VelocityTracker;

import android.view.ViewConfiguration;

import android.view.ViewGroup;

import android.widget.Scroller;

public class Image3DSwitchView extends ViewGroup {  
 

    /** 

     * 图片左右两边的空白间距 

     */  

    public static final int IMAGE_PADDING = 10;  

    private static final int TOUCH_STATE_REST = 0;  

    private static final int TOUCH_STATE_SCROLLING = 1;  

    /** 

     * 滚动到下一张图片的速度 

     */  

    private static final int SNAP_VELOCITY = 600;  

    /** 

     * 表示滚动到下一张图片这个动作 

     */  

    private static final int SCROLL_NEXT = 0;  

    /** 

     * 表示滚动到上一张图片这个动作 

     */  

    private static final int SCROLL_PREVIOUS = 1;  

    /** 

     * 表示滚动回原图片这个动作 

     */  

    private static final int SCROLL_BACK = 2;  

    private static Handler handler = new Handler();  

    /** 

     * 控件宽度 

     */  

    public static int mWidth;  

    private VelocityTracker mVelocityTracker;  

    private Scroller mScroller;  

    /** 

     * 图片滚动监听器,当图片发生滚动时回调这个接口 

     */  

    private OnImageSwitchListener mListener;  

    /** 

     * 记录当前的触摸状态 

     */  

    private int mTouchState = TOUCH_STATE_REST;  

    /** 

     * 记录被判定为滚动运动的最小滚动值 

     */  

    private int mTouchSlop;  

    /** 

     * 记录控件高度 

     */  

    private int mHeight;  

    /** 

     * 记录每张图片的宽度 

     */  

    private int mImageWidth;  

    /** 

     * 记录图片的总数量 

     */  

    private int mCount;  

    /** 

     * 记录当前显示图片的坐标 

     */  

    private int mCurrentImage;  

    /** 

     * 记录上次触摸的横坐标值 

     */  

    private float mLastMotionX;  

    /** 

     * 是否强制重新布局 

     */  

    private boolean forceToRelayout;  

    private int[] mItems;  

  

    public Image3DSwitchView(Context context, AttributeSet attrs) {  

        super(context, attrs);  

        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();  

        mScroller = new Scroller(context);  

    }  

  

    @Override  

    protected void onLayout(boolean changed, int l, int t, int r, int b) {  

        if (changed || forceToRelayout) {  

            mCount = getChildCount();  

            // 图片数量必须大于5,不然无法正常显示  

            if (mCount < 5) {  

                return;  

            }  

            mWidth = getMeasuredWidth();  

            mHeight = getMeasuredHeight();  

            // 每张图片的宽度设定为控件宽度的百分之六十  

            mImageWidth = (int) (mWidth * 0.6);  

            if (mCurrentImage >= 0 && mCurrentImage < mCount) {  

                mScroller.abortAnimation();  

                setScrollX(0);  

                int left = -mImageWidth * 2 + (mWidth - mImageWidth) / 2;  

                // 分别获取每个位置上应该显示的图片下标  

                int[] items = { getIndexForItem(1), getIndexForItem(2),  

                        getIndexForItem(3), getIndexForItem(4),  

                        getIndexForItem(5) };  

                mItems = items;  

                // 通过循环为每张图片设定位置  

                for (int i = 0; i < items.length; i++) {  

                    Image3DView childView = (Image3DView) getChildAt(items[i]);  

                    childView.layout(left + IMAGE_PADDING, 0, left  

                            + mImageWidth - IMAGE_PADDING, mHeight);  

                    childView.initImageViewBitmap();  

                    left = left + mImageWidth;  

                }  

                refreshImageShowing();  

            }  

            forceToRelayout = false;  

        }  

    }  

  

    @Override  

    public boolean onTouchEvent(MotionEvent event) {  

        if (mScroller.isFinished()) {  

            if (mVelocityTracker == null) {  

                mVelocityTracker = VelocityTracker.obtain();  

            }  

            mVelocityTracker.addMovement(event);  

            int action = event.getAction();  

            float x = event.getX();  

            switch (action) {  

            case MotionEvent.ACTION_DOWN:  

                // 记录按下时的横坐标  

                mLastMotionX = x;  

                break;  

            case MotionEvent.ACTION_MOVE:  

                int disX = (int) (mLastMotionX - x);  

                mLastMotionX = x;  

                scrollBy(disX, 0);  

                // 当发生移动时刷新图片的显示状态  

                refreshImageShowing();  

                break;  

            case MotionEvent.ACTION_UP:  

                mVelocityTracker.computeCurrentVelocity(1000);  

                int velocityX = (int) mVelocityTracker.getXVelocity();  

                if (shouldScrollToNext(velocityX)) {  

                    // 滚动到下一张图  

                    scrollToNext();  

                } else if (shouldScrollToPrevious(velocityX)) {  

                    // 滚动到上一张图  

                    scrollToPrevious();  

                } else {  

                    // 滚动回当前图片  

                    scrollBack();  

                }  

                if (mVelocityTracker != null) {  

                    mVelocityTracker.recycle();  

                    mVelocityTracker = null;  

                }  

                break;  

            }  

        }
bc9e
 

        return true;  

    }  

  

    /** 

     * 根据当前的触摸状态来决定是否屏蔽子控件的交互能力。 

     */  

    @Override  

    public boolean onInterceptTouchEvent(MotionEvent ev) {  

        int action = ev.getAction();  

        if ((action == MotionEvent.ACTION_MOVE)  

                && (mTouchState != TOUCH_STATE_REST)) {  

            return true;  

        }  

        float x = ev.getX();  

        switch (action) {  

        case MotionEvent.ACTION_DOWN:  

            mLastMotionX = x;  

            mTouchState = TOUCH_STATE_REST;  

            break;  

        case MotionEvent.ACTION_MOVE:  

            int xDiff = (int) Math.abs(mLastMotionX - x);  

            if (xDiff > mTouchSlop) {  

                mTouchState = TOUCH_STATE_SCROLLING;  

            }  

            break;  

        case MotionEvent.ACTION_UP:  

        default:  

            mTouchState = TOUCH_STATE_REST;  

            break;  

        }  

        return mTouchState != TOUCH_STATE_REST;  

    }  

  

    @Override  

    public void computeScroll() {  

        if (mScroller.computeScrollOffset()) {  

            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  

            refreshImageShowing();  

            postInvalidate();  

        }  

    }  

  

    /** 

     * 设置图片滚动的监听器,每当有图片滚动时会回调此接口。 

     *  

     * @param listener 

     *            图片滚动监听器 

     */  

    public void setOnImageSwitchListener(OnImageSwitchListener listener) {  

        mListener = listener;  

    }  

  

    /** 

     * 设置当前显示图片的下标,注意如果该值小于零或大于等于图片的总数量,图片则无法正常显示。 

     *  

     * @param currentImage 

     *            图片的下标 

     */  

    public void setCurrentImage(int currentImage) {  

        mCurrentImage = currentImage;  

        requestLayout();  

    }  

  

    /** 

     * 滚动到下一张图片。 

     */  

    public void scrollToNext() {  

        if (mScroller.isFinished()) {  

            int disX = mImageWidth - getScrollX();  

            checkImageSwitchBorder(SCROLL_NEXT);  

            if (mListener != null) {  

                mListener.onImageSwitch(mCurrentImage);  

            }  

            beginScroll(getScrollX(), 0, disX, 0, SCROLL_NEXT);  

        }  

    }  

  

    /** 

     * 滚动到上一张图片。 

     */  

    public void scrollToPrevious() {  

        if (mScroller.isFinished()) {  

            int disX = -mImageWidth - getScrollX();  

            checkImageSwitchBorder(SCROLL_PREVIOUS);  

            if (mListener != null) {  

                mListener.onImageSwitch(mCurrentImage);  

            }  

            beginScroll(getScrollX(), 0, disX, 0, SCROLL_PREVIOUS);  

        }  

    }  

  

    /** 

     * 滚动回原图片。 

     */  

    public void scrollBack() {  

        if (mScroller.isFinished()) {  

            beginScroll(getScrollX(), 0, -getScrollX(), 0, SCROLL_BACK);  

        }  

    }  

  

    /** 

     * 回收所有图片对象,释放内存。 

     */  

    public void clear() {  

        for (int i = 0; i < mCount; i++) {  

            Image3DView childView = (Image3DView) getChildAt(i);  

            childView.recycleBitmap();  

        }  

    }  

  

    /** 

     * 让控件中的所有图片开始滚动。 

     */  

    private void beginScroll(int startX, int startY, int dx, int dy,  

            final int action) {  

        int duration = (int) (700f / mImageWidth * Math.abs(dx));  

        mScroller.startScroll(startX, startY, dx, dy, duration);  

        invalidate();  

        handler.postDelayed(new Runnable() {  

            @Override  

            public void run() {  

                if (action == SCROLL_NEXT || action == SCROLL_PREVIOUS) {  

                    forceToRelayout = true;  

                    requestLayout();  

                }  

            }  

        }, duration);  

    }  

  

    /** 

     * 根据当前图片的下标和传入的item参数,来判断item位置上应该显示哪张图片。 

     *  

     * @param item 

     *            取值范围是1-5 

     * @return 对应item位置上应该显示哪张图片。 

     */  

    private int getIndexForItem(int item) {  

        int index = -1;  

        index = mCurrentImage + item - 3;  

        while (index < 0) {  

            index = index + mCount;  

        }  

        while (index > mCount - 1) {  

            index = index - mCount;  

        }  

        return index;  

    }  

  

    /** 

     * 刷新所有图片的显示状态,包括当前的旋转角度。 

     */  

    private void refreshImageShowing() {  

        for (int i = 0; i < mItems.length; i++) {  

            Image3DView childView = (Image3DView) getChildAt(mItems[i]);  

            childView.setRotateData(i, getScrollX());  

            childView.invalidate();  

        }  

    }  

  

    /** 

     * 检查图片的边界,防止图片的下标超出规定范围。 

     */  

    private void checkImageSwitchBorder(int action) {  

        if (action == SCROLL_NEXT && ++mCurrentImage >= mCount) {  

            mCurrentImage = 0;  

        } else if (action == SCROLL_PREVIOUS && --mCurrentImage < 0) {  

            mCurrentImage = mCount - 1;  

        }  

    }  

  

    /** 

     * 判断是否应该滚动到下一张图片。 

     */  

    private boolean shouldScrollToNext(int velocityX) {  

        return velocityX < -SNAP_VELOCITY || getScrollX() > mImageWidth / 2;  

    }  

  

    /** 

     * 判断是否应该滚动到上一张图片。 

     */  

    private boolean shouldScrollToPrevious(int velocityX) {  

        return velocityX > SNAP_VELOCITY || getScrollX() < -mImageWidth / 2;  

    }  

  

    /** 

     * 图片滚动的监听器 

     */  

    public interface OnImageSwitchListener {  

  

        /** 

         * 当图片滚动时会回调此方法 

         *  

         * @param currentImage 

         *            当前图片的坐标 

         */  

        void onImageSwitch(int currentImage);  

  

    }  

}  

//以下是xml布局:

activity_main

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:background="#fff" >

    <com.example.viewpage_3d.Image3DSwitchView

        android:id="@+id/image_switch_view"

        android:layout_width="match_parent"

        android:layout_height="150dp" >

        <com.example.viewpage_3d.Image3DView

            android:id="@+id/image1"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:scaleType="fitXY"

            android:src="@drawable/aa" />

        <com.example.viewpage_3d.Image3DView

            android:id="@+id/image3"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:scaleType="fitXY"

            android:src="@drawable/cc" />

        <com.example.viewpage_3d.Image3DView

            android:id="@+id/image4"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:scaleType="fitXY"

            android:src="@drawable/dd" />

        <com.example.viewpage_3d.Image3DView

            android:id="@+id/image5"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:scaleType="fitXY"

            android:src="@drawable/ee" />

        <com.example.viewpage_3d.Image3DView

            android:id="@+id/image6"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:scaleType="fitXY"

            android:src="@drawable/ff" />

    </com.example.viewpage_3d.Image3DSwitchView>

</RelativeLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: