package com.anlia.pageturn.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.GradientDrawable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver; import android.view.animation.LinearInterpolator; import android.widget.Scroller; import com.anlia.pageturn.bean.MyPoint; import com.anlia.pageturn.factory.PageFactory; import com.anlia.pageturn.utils.ViewUtils; /** * Created by anlia on 2017/12/11. */ public class CoverPageView extends View { private int defaultWidth;//默认宽度 private int defaultHeight;//默认高度 private int viewWidth; private int viewHeight; private int pageNum;//当前页数 private float xDown;//记录初始触摸的x坐标 private float scrollPageLeft;//滑动页左边界 private int scrollTime;//滑动动画时间 private PageFactory pageFactory; private MyPoint touchPoint;//触摸点 private Scroller mScroller; private GradientDrawable shadowDrawable; private Bitmap previousPage;//上一页bitmap private Bitmap currentPage;//当前页bitmap private Bitmap nextPage;//下一页bitmap private int touchStyle;//触摸类型 public static final int TOUCH_MIDDLE = 0;//点击中间区域 public static final int TOUCH_LEFT = 1;//点击左边区域 public static final int TOUCH_RIGHT = 2;//点击右边区域 private int pageState;//翻页状态,用于限制翻页动画结束前的触摸操作 public static final int PAGE_STAY = 0;//处于静止状态 public static final int PAGE_NEXT = 1;//翻至下一页 public static final int PAGE_PREVIOUS = 2;//翻至上一页 public CoverPageView(Context context) { super(context); init(context); } public CoverPageView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context){ defaultWidth = 600; defaultHeight = 1000; pageNum = 1; scrollPageLeft = 0; scrollTime = 300; touchStyle = TOUCH_RIGHT; pageState = PAGE_STAY; touchPoint = new MyPoint(-1,-1); mScroller = new Scroller(context,new LinearInterpolator()); int[] mBackShadowColors = new int[] { 0x66000000,0x00000000}; shadowDrawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors); shadowDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); } /** * 设置工厂类 * @param factory */ public void setPageFactory(final PageFactory factory){ //保证View已经完成了测量工作,各页bitmap已初始化 getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { getViewTreeObserver().removeOnPreDrawListener(this); if(factory.hasData){ pageFactory = factory; pageFactory.drawCurrentBitmap(currentPage,pageNum); postInvalidate(); } return true; } }); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int height = ViewUtils.measureSize(defaultHeight, heightMeasureSpec); int width = ViewUtils.measureSize(defaultWidth, widthMeasureSpec); setMeasuredDimension(width, height); viewWidth = width; viewHeight = height; previousPage = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.RGB_565); currentPage = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.RGB_565); nextPage = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.RGB_565); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(pageFactory !=null){ if(touchPoint.x ==-1 && touchPoint.y ==-1){ drawCurrentPage(canvas); pageState = PAGE_STAY; }else{ if(touchStyle == TOUCH_RIGHT){ drawCurrentPage(canvas); drawPreviousPage(canvas); drawShadow(canvas); }else { drawNextPage(canvas); drawCurrentPage(canvas); drawShadow(canvas); } } } } /** * 绘制上一页 * @param canvas */ private void drawPreviousPage(Canvas canvas){ canvas.drawBitmap(previousPage, scrollPageLeft, 0,null); } /** * 绘制当前页 * @param canvas */ private void drawCurrentPage(Canvas canvas){ if(touchStyle == TOUCH_RIGHT){ canvas.drawBitmap(currentPage, 0, 0,null); }else if(touchStyle == TOUCH_LEFT){ canvas.drawBitmap(currentPage, scrollPageLeft, 0,null); } } /** * 绘制下一页 * @param canvas */ private void drawNextPage(Canvas canvas){ canvas.drawBitmap(nextPage, 0, 0, null); } /** * 绘制阴影 * @param canvas */ private void drawShadow(Canvas canvas){ int left = (int)(viewWidth + scrollPageLeft); shadowDrawable.setBounds(left, 0, left + 30 , viewHeight); shadowDrawable.draw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); float x = event.getX(); float y = event.getY(); if(pageState == PAGE_STAY){ switch (event.getAction()){ case MotionEvent.ACTION_DOWN: xDown = x; if(x<=viewWidth/3){//左 touchStyle = TOUCH_LEFT; if(pageNum>1){ pageNum--; pageFactory.drawCurrentBitmap(currentPage,pageNum); pageFactory.drawNextBitmap(nextPage,pageNum); pageNum++; } }else if(x>viewWidth*2/3){//右 touchStyle = TOUCH_RIGHT; if(pageNum<pageFactory.pageTotal){ pageNum++; pageFactory.drawPreviousBitmap(previousPage,pageNum); pageFactory.drawCurrentBitmap(currentPage,pageNum); pageNum--; } }else if(x>viewWidth/3 && x<viewWidth*2/3){//中 touchStyle = TOUCH_MIDDLE; } break; case MotionEvent.ACTION_MOVE: if(touchStyle == TOUCH_LEFT){ if(pageNum>1){ scrollPage(x,y); } }else if(touchStyle == TOUCH_RIGHT){ if(pageNum<pageFactory.pageTotal){ scrollPage(x,y); } } break; case MotionEvent.ACTION_UP: autoScroll(); break; } } return true; } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { float x = mScroller.getCurrX(); float y = mScroller.getCurrY(); scrollPageLeft = 0 - (viewWidth - x); if (mScroller.getFinalX() == x && mScroller.getFinalY() == y){ if(touchStyle == TOUCH_RIGHT){ pageNum++; }else if(touchStyle == TOUCH_LEFT){ pageNum--; } resetView(); } postInvalidate(); } } /** * 计算滑动页面左边界位置,实现滑动当前页效果 * @param x * @param y */ private void scrollPage(float x, float y){ touchPoint.x = x; touchPoint.y = y; if(touchStyle == TOUCH_RIGHT){ scrollPageLeft = touchPoint.x - xDown; }else if(touchStyle == TOUCH_LEFT){ scrollPageLeft =touchPoint.x - xDown - viewWidth; } if(scrollPageLeft > 0){ scrollPageLeft = 0; } postInvalidate(); } /** * 自动完成滑动操作 */ private void autoScroll(){ switch (touchStyle){ case TOUCH_LEFT: if(pageNum>1){ autoScrollToPreviousPage(); } break; case TOUCH_RIGHT: if(pageNum<pageFactory.pageTotal){ autoScrollToNextPage(); } break; } } /** * 自动完成翻到下一页操作 */ private void autoScrollToNextPage(){ pageState = PAGE_NEXT; int dx,dy; dx = (int) -(viewWidth+scrollPageLeft); dy = (int) (touchPoint.y); int time =(int) ((1+scrollPageLeft/viewWidth) * scrollTime); mScroller.startScroll((int) (viewWidth+scrollPageLeft), (int) touchPoint.y, dx, dy, time); } /** * 自动完成返回上一页操作 */ private void autoScrollToPreviousPage(){ pageState = PAGE_PREVIOUS; int dx,dy; dx = (int) -scrollPageLeft; dy = (int) (touchPoint.y); int time =(int) (-scrollPageLeft/viewWidth * scrollTime); mScroller.startScroll((int) (viewWidth+scrollPageLeft), (int) touchPoint.y, dx, dy, time); } /** * 取消翻页动画,计算滑动位置与时间 */ private void startCancelAnim(){ int dx,dy; dx = (int) (viewWidth-1-touchPoint.x); dy = (int) (touchPoint.y); mScroller.startScroll((int) touchPoint.x, (int) touchPoint.y, dx, dy, scrollTime); } /** * 重置操作 */ private void resetView(){ scrollPageLeft = 0; touchPoint.x = -1; touchPoint.y = -1; } }