转载请注明来自:5进制空间-android区

相信做电子书的同学,都遇到过翻页动画的需求吧,如果你不满足与点击滑动翻页的话,这边文章应该能够帮助到你。

先上个效果图:

效果还是很不错的,不过与ibook那个效果比起来,还是有差距的。应为这个没用到openGL做3D效果,只是用的2d的canvas画布去画的view,添加了阴影效果,还是挺有立体感的。而且比较流畅。openGL实现肯定效果会更好,不过就我目前的技术实力,实现希望还是渺茫的。

废话少说,还是上代码吧:

这里需要两个UI的view类和一个使用方法的demo。
第一个pageTurnerView.java:

public class PageTurnerViewP1 extends RelativeLayout{       private static final int CORNER_RIGHT_MASK = 1;      private static final int CORNER_TOP_MASK = 2;      public static final int CORNER_BOTTOM_LEFT = 0;      public static final int CORNER_BOTTOM_RIGHT = 1;      public static final int CORNER_TOP_LEFT = 2;      public static final int CORNER_TOP_RIGHT = 3;      private static final int INVALIDATE = 1;      private static final int INITIAL_TIME_DELAY = 100;      private static final int TIME_DELAY = 10;//      private static final int TIME_STEPS = 30;      private boolean mPageTurning;      private boolean mStepping;      public long mNextTime;      private int mTimeStep;      private int mDrawnTimeStep;      private int mCorner;      private Drawable mBackPage;      private Drawable mPageBackground;      private Path mForegroundPath;      private Path mBackPagePath;      private Path mBackgroundPath;      private float mRotation;      private Rect mChildRect = new Rect();      private int mOuterOffsetX;      private int mOuterOffsetY;      public float mPivotX;      private int mPageId;      private PageViewP1 mPage;      private PointF mPageTurnCorner = new PointF();      private PointF mOppositeCorner = new PointF();      private PointF mPageDim = new PointF();      private int mStepLen = 1;      public static final int KEEP = 0;      public static final int NEXT = 1;      public static final int LAST = 2;      public int mWhere = KEEP;      public boolean isBgInit = true;      public boolean isBackInit = true;      private  float ax,ay,bx,by,cx,cy,dx,dy,ex,ey,c0x,c0y;      private int mMaxStep=30;      public final Handler mHandler = new Handler() {          public void handleMessage(Message msg) {              if (msg.what != 1) { return; }//              PageTurnerViewP1.this.invalidate();              refreshUI();//              PageTurnerViewP1.this.invalidate((int)bx, (int)ay, (int)dx, (int)dy);              if (PageTurnerViewP1.this.mStepping) { return; }              msg = obtainMessage(1);              long current = SystemClock.uptimeMillis();              if (PageTurnerViewP1.this.mNextTime < current) {                   //PageTurnerViewP1.access$102(PageTurnerViewP1.this, current + 10L);                  PageTurnerViewP1.this.mNextTime= current + 5L;               }               sendMessageAtTime(msg, PageTurnerViewP1.this.mNextTime);               //PageTurnerViewP1.access$114(PageTurnerViewP1.this, 10L);                 PageTurnerViewP1.this.mNextTime+= 5L;           }       };            public PageTurnerViewP1(Context context) {           super(context);           Log.i("==================== PageTurnerViewP1(Context context) =================", "" + this);       }       public PageTurnerViewP1(Context context, AttributeSet attrs) {           super(context, attrs);                        this.mPageId = -1;             this.mCorner = -1;       }       protected void onFinishInflate() {           super.onFinishInflate();           if (this.mPageId != -1) {               this.mPage = ((PageViewP1)findViewById(this.mPageId));               if (this.mPage != null)                   this.mPage.setPageTurner(this);           }       }       public void setPageId(int pageId) {           this.mPageId = pageId;           this.mPage = ((PageViewP1)findViewById(this.mPageId));           if (this.mPage != null)               this.mPage.setPageTurner(this);       }       public int getPageId() {           return this.mPageId;       }       public void setPage(PageViewP1 pageViewP1) {           this.mPage = pageViewP1;       }       public PageViewP1 getPage() {           return this.mPage;       }       public void setCorner(int corner) {           this.mCorner = corner;       }       public int getCorner() {           return this.mCorner;       }       protected void dispatchDraw(Canvas canvas) {                        Log.v("log dispatchDraw:", "drawing back page"+mPageTurning); //          if ((this.mPageTurning) && (this.mPage != null) && (computePageTurn())) {           if ((computePageTurn())&& (this.mPageTurning) && (this.mPage != null) ) {               this.mPage.setClipPath(this.mForegroundPath);           }           super.dispatchDraw(canvas);           if (this.mPageTurning) {               drawBackground(canvas);               drawBackPage(canvas);                              if (!updateTimeStep()) {                   this.mHandler.removeMessages(1);                   if (this.mPage != null) {                       this.mPage.onPageTurnFinished(canvas);                   }                   this.mPageTurning = false;                   this.mStepping = false;                   invalidate();               }           }       }       public void startPageTurn(int mTimeStep) {           if ((this.mPage == null) && (this.mPageId != -1)) {               this.mPage = ((PageViewP1)findViewById(this.mPageId));           }           if (this.mPage == null) {               return;           }           this.mPage.setPageTurner(this);           Drawable d = this.mPage.getPageBackground();           if (d != null) {               this.mPageBackground = d;           }           d = this.mPage.getBackPage();           if (d != null) {               this.mBackPage = d;           }           int corner = this.mPage.getCorner();           if (corner != -1) {               this.mCorner = corner;           } //          this.mStepping=false;           this.mPageTurning = true;           this.mTimeStep = mTimeStep;           this.mDrawnTimeStep = -1;           Message msg = this.mHandler.obtainMessage(1);           this.mNextTime = (SystemClock.uptimeMillis() + 5L);           this.mHandler.sendMessageAtTime(msg, this.mNextTime);       }       public void stepPageTurn() {           if (!this.mStepping) {               this.mStepping = true;               startPageTurn(this.mTimeStep);           } else { //                           refreshUI();           }       }       public void refreshUI(){           computePageTurn(); //                    this.invalidate();       }       private void sendUIhandler(){           Message msg = this.mHandler.obtainMessage(1);           this.mNextTime = (SystemClock.uptimeMillis() + 30L);           this.mHandler.sendMessageAtTime(msg, this.mNextTime);       }       private boolean updateTimeStep() {           if (this.mTimeStep >mMaxStep || this.mTimeStepthis.mMaxStep)) {          if ( (this.mTimeStep this.mMaxStep)) {              return false;          }          if (this.mPage == null) {              return false;          }          this.mDrawnTimeStep = this.mTimeStep;          View child = this.mPage.getChildAt(0);          child.getDrawingRect(this.mChildRect);//          this.mOuterOffsetX = (child.getLeft() - getLeft());//          this.mOuterOffsetY = (child.getTop() - getTop());          this.mOuterOffsetX = 0;          this.mOuterOffsetY = 0;           float width = this.mChildRect.right;          float height = this.mChildRect.bottom;          if(!mStepping){              this.mPivotX = (this.mTimeStep / 30.0f * width);          }          this.mForegroundPath = new Path();          this.mBackPagePath = new Path();          this.mBackgroundPath = new Path();          float slope = width / (this.mPivotX - width);          float y = this.mPivotX * slope;           this.mPageTurnCorner.x = 0.0F;          this.mPageTurnCorner.y = height;          this.mOppositeCorner.x = width;          this.mOppositeCorner.y = 0.0F;          float x0 = this.mPivotX;          float cornerIntersect = height * width / (height + width);          if ((this.mCorner & 0x1) != 0) {              this.mPageTurnCorner.x = width;              this.mOppositeCorner.x = 0.0F;              x0 = width - x0;          }           if ((this.mCorner & 0x2) != 0) {              this.mPageTurnCorner.y = 0.0F;              this.mOppositeCorner.y = height;          }           this.mPageDim.x = width;          this.mPageDim.y = height;          float page_slope;           if (this.mPivotX 2){            LinearGradient grad = new LinearGradient(                    ex,ey,ex+(dx-ex)/4,ey+(dy-ey)/4,R.color.gray3,Color.TRANSPARENT,Shader.TileMode.CLAMP);            Paint p=new Paint();            p.setShader(grad);//            p.setAlpha(120);            canvas.drawPath(this.mBackgroundPath,p);            //end test              }          canvas.restore();       }       private void drawBackPage(Canvas canvas) {          float width = this.mChildRect.right;          float height = this.mChildRect.bottom;          canvas.save();//          canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));          canvas.clipPath(this.mBackPagePath, Region.Op.INTERSECT);          float xShift = 2.0F * this.mPivotX - width;          float xRotate = width - this.mPivotX;          float yRotate = height;          if ((this.mCorner & 0x1) != 0) {              xShift = width - 2.0F * this.mPivotX;              xRotate = this.mPivotX;          }          if ((this.mCorner & 0x2) != 0) {              yRotate = 0.0F;          }          canvas.translate(this.mOuterOffsetX + xShift, this.mOuterOffsetY);          canvas.rotate(this.mRotation, xRotate, yRotate);           //画原本的背面          if (this.mBackPage != null) {              this.mBackPage.setBounds(0, 0, this.mChildRect.right, this.mChildRect.bottom);              this.mBackPage.draw(canvas);          }          //画回调函数中的画背面          if (this.mPage != null) {                Log.v("log2 drawBackPage2:", "drawing back page");              this.mPage.drawBackPage(canvas);          }           canvas.restore();          canvas.save();//            LinearGradient grad = new LinearGradient(                    ex,ey,ex-(ex-bx)/4,ey-(ey-by)/4,R.color.gray3,0xC9C9C9,Shader.TileMode.CLAMP);            Paint p=new Paint();            p.setShader(grad);//            p.setAlpha(120);            canvas.drawPath(this.mBackPagePath,p);            canvas.restore();            //中间阴影问题,起点蓝色-》 白色-》 蓝色终点,这样起点前和终点后的区域也为蓝色了。            canvas.save();//            canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));            LinearGradient grad1 = new LinearGradient(                    ex-(ex-bx)/4,ey-(ey-by)/4,bx,by,0xC9C9C9,R.color.gray3,Shader.TileMode.CLAMP);            Paint p1=new Paint();            p1.setShader(grad1);//            p1.setAlpha(120);            canvas.drawPath(this.mBackPagePath,p1);            canvas.restore();//                  }       public int getmTimeStep(){           return mTimeStep;      }      public void setmTimeStep(int mTimeStep ){           this.mTimeStep= mTimeStep;      }      public boolean getmStepping(){           return mStepping;      }      public void setmStepping(boolean mStepping ){           this.mStepping= mStepping;      }       public void setmStepLen(int mStepLen){          this.mStepLen=mStepLen;      }      public int getmStepLen(){          return this.mStepLen;      }       public void setmMaxStep(int mMaxStep){          this.mMaxStep=mMaxStep;      }      public int getmMaxStep(){          return this.mMaxStep;      }     public void setPreStart(int where)    {        switch (where)        {            case NEXT:            case LAST:                mWhere = where;                break;             default:                mWhere = KEEP;                break;        }         isBgInit = true;        isBackInit = true;     } }

第二个view类pageView.java:

public class PageViewP1 extends RelativeLayout {    public static final int CORNER_BOTTOM_LEFT = 0;    public static final int CORNER_BOTTOM_RIGHT = 1;    public static final int CORNER_TOP_LEFT = 2;    public static final int CORNER_TOP_RIGHT = 3;    private Path mClipPath;    private PageTurnerViewP1 mPageTurner;    private Callback mCallback;    private int mCorner;    private Drawable mBackPage;    private Drawable mPageBackground;     public PageViewP1(Context context) {        super(context);    }     public PageViewP1(Context context, AttributeSet attrs ) {        super(context, attrs );         this.mBackPage =this.getBackground();        this.mCorner = -1;    }     void setPageTurner(PageTurnerViewP1 pageTurnerViewP1) {        this.mPageTurner = pageTurnerViewP1;    }     void setClipPath(Path clipPath) {        this.mClipPath = clipPath;    }     public void setCallback(Callback callback)  {        this.mCallback = callback;    }     void drawBackPage(Canvas canvas) {       if (this.mCallback != null)           this.mCallback.onDrawBackPage(canvas);    }     void drawBackground(Canvas canvas) {        if (this.mCallback != null)            this.mCallback.onDrawBackground(canvas);    }     public void startPageTurn() {        if (this.mPageTurner != null)            this.mPageTurner.startPageTurn(0);    }     void onPageTurnFinished(Canvas canvas) {        this.mCallback.onPageTurnFinished(canvas);        this.mClipPath = null;    }     protected void dispatchDraw(Canvas canvas) {        if (this.mClipPath != null) {            canvas.save();            canvas.clipPath(this.mClipPath, Region.Op.INTERSECT);        }        super.dispatchDraw(canvas);        if (this.mClipPath != null)            canvas.restore();    }     public void setCorner(int corner) {        this.mCorner = corner;    }     public int getCorner() {        return this.mCorner;    }     public void setBackPage(Drawable backPage) {        this.mBackPage = backPage;    }     public Drawable getBackPage() {        return this.mBackPage;    }     public void setPageBackground(Drawable background) {        this.mPageBackground = background;    }     public Drawable getPageBackground() {        return this.mPageBackground;    }     public static abstract class Callback {        public void onDrawBackPage(Canvas canvas) {            Log.v("Callback", "drawing back page");        }        public void onDrawBackground(Canvas canvas) {            Log.v("Callback2", "drawing back page");        }        public void onPageTurnFinished(Canvas canvas) {            Log.v("Callback3", "drawing back page");        }    }}

PageTurnDemo.java

import java.lang.reflect.Field;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.Shader;import android.os.Bundle;import android.util.Log;import android.view.Display;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.WindowManager;import android.view.View.OnTouchListener;import android.widget.TextView; public class PageTurnerDemo extends Activity { private PageTurnerViewP1 pageturner;private PageViewP1 page1;private static final String TAG = "RUKIDEMO";TextView text1;TextView text2;int screenWidth;int screenHeight;String content1;String content2;String currcontent;private boolean marktest = true;private int startX;private int mMaxStep=30;private int mAnimaStepLen=mMaxStep/8; @Overridepublic void onCreate(Bundle icicle) {super.onCreate(icicle);getWH(); setContentView(R.layout.main);initPage();pageturner = (PageTurnerViewP1) findViewById(R.id.pages);pageturner.setPage(page1);pageturner.setLongClickable(true);pageturner.setOnTouchListener(pageontounchlistener);// 自动运行surfaceCreated以及surfaceChanged} private void getWH() {WindowManager windowManager = getWindowManager();Display display = windowManager.getDefaultDisplay();screenWidth = display.getWidth();screenHeight = display.getHeight();} private void initPage() { content1 =getResources().getString(R.string.content1);content2 = getResources().getString(R.string.content2);// 初始化两页内容text1 = (TextView) findViewById(R.id.page1text);// text1.setBackgroundResource(R.drawable.solopage);text1.setText(content1); text2 = (TextView) findViewById(R.id.page2text);// text2.setBackgroundResource(R.drawable.solopage);text2.setText(content2); page1 = (PageViewP1) findViewById(R.id.page1);// page1.setBackPage(this.getResources().getDrawable(R.drawable.solopage));// page1.setPageBackground(this.getResources()// .getDrawable(R.drawable.page));page1.setCallback(pageturncallback);page1.setCorner(PageViewP1.CORNER_TOP_LEFT);// /++++++++++++++++++++++++++++++++++++++++++++///} PageViewP1.Callback pageturncallback = new PageViewP1.Callback() {public void onDrawBackPage(Canvas canvas1) {// apparently this gets called after every animation// so if we wanted to we can draw the back page hereLog.v(TAG, "drawing back page");// Paint mpaint = new Paint();// mpaint.setColor(Color.BLUE);// canvas1.drawText(// "testtesttesttesttesttesttesttesttesttesttesttesttest",// 150, 150, mpaint); // canvas1.drawCircle(0,0,200,p); //参数3为画圆的半径,类型为float型。 // Shader setShader(Shader shader); // text1.draw(canvas1);} public void onDrawBackground(Canvas canvas1) {// apparently this gets called after every animation// so if we wanted to we can draw the background hereLog.v(TAG, "drawing background"); // Paint mpaint = new Paint();// Path path = new Path();// mpaint.setColor(Color.BLACK);// TextUtil mTextUtil;// String string =// "12345678910111213 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29\n"// +"12345678910111213 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29\n"// +"12345678910111213 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29\n"// +"12345678910111213 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29\n"// +"12345678910111213 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29\n";// mTextUtil = new TextUtil(string, 15, 15, 350, 80, 0x000000,// 0xff00ff,// 235, 16);// mTextUtil.InitText();// mTextUtil.DrawText(canvas1);// mpaint.setTextSize(textSize)// canvas1.drawt// page2.draw(canvas1); canvas1.save();// Paint p=new Paint();// LinearGradient lg=new LinearGradient(0,0,100,100,Color.BLACK,Color.WHITE,Shader.TileMode.MIRROR);// //参数一为渐变起初点坐标x位置,参数二为y轴位置,参数三和四分辨对应渐变终点,最后参数为平铺方式,这里设置为镜像// p.setShader(lg);//// canvas1.translate(200, 200);// canvas1.skew(5, 5);text2.draw(canvas1);// myonDraw(canvas1);canvas1.restore(); } public void onPageTurnFinished(Canvas canvas1) {// this gets called after the animation is done// perphaps this is where we should change view to the new// 在这里在换当前页内容到下一页的内容,这里假设text1是当前页内容if (marktest) {text1.setText(content2);text2.setText(content1);marktest = !marktest;} else {text2.setText(content2);text1.setText(content1);marktest = !marktest;} }}; OnTouchListener pageontounchlistener = new OnTouchListener() { @Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubfinal int action = event.getAction();final int x = (int) event.getX();final int y = (int) event.getY();final float px = event.getX();int itemLen = screenWidth / mMaxStep;switch (action) {case MotionEvent.ACTION_DOWN:startX=x; // LEFTif (x < screenWidth / 2) {// LTif (y < screenHeight / 2) {page1.setCorner(PageTurnerViewP1.CORNER_TOP_RIGHT);// LB} else {page1.setCorner(PageTurnerViewP1.CORNER_BOTTOM_RIGHT);}// RIGHT} else {// RTif (y < screenHeight / 2) {page1.setCorner(PageTurnerViewP1.CORNER_TOP_RIGHT);// RB} else {page1.setCorner(PageTurnerViewP1.CORNER_BOTTOM_RIGHT);}}break;case MotionEvent.ACTION_MOVE:// pageturner.setPivotX(screenWidth-px);// pageturner.invalidate();//左侧起if (startX pageturner.setmStepLen(-2);pageturner.setmTimeStep((screenWidth-x) / itemLen);pageturner.mPivotX=(screenWidth-x);pageturner.stepPageTurn();//右侧起} else {pageturner.setmStepLen(2);pageturner.setmTimeStep((screenWidth-x) / itemLen);pageturner.mPivotX=(screenWidth-x);pageturner.stepPageTurn();} break;case MotionEvent.ACTION_UP:pageturner.setmStepLen(2);pageturner.setmStepping(false);//左侧起if (startX screenWidth / 3){pageturner.setmStepLen(-2);}//左松pageturner.startPageTurn((screenWidth-x) / itemLen);//右侧起} else {pageturner.setmStepLen(2);//左松if(x < (screenWidth *2)/ 3){pageturner.setmStepLen(2);}else {//右松pageturner.setmStepLen(-2);}pageturner.startPageTurn((screenWidth-x) / itemLen);} break;case MotionEvent.ACTION_CANCEL:} return true;} }; }

更多相关文章

  1. Android之控件阴影模糊效果死磕Paint.setShadowLayer()
  2. 不用线程做Android软件欢迎界面,透明效果,完成后自动跳转
  3. android:theme 与 setTheme()设置透明效果并不同
  4. android v7兼容包RecyclerView的使用(三)——布局管理器的使用
  5. Android(安卓)SwipeMenuListView
  6. ym—— Android(安卓)5.0学习之感想篇(含Demo)
  7. 仿MIUI的Toast动画效果实现
  8. 关于GridView宽高的问题(转载rain的文章)
  9. android 组件动画(一)——球的进入效果

随机推荐

  1. 深入理解java中的package关键字
  2. android人脸识别——HowOld测测你的年龄
  3. Android(安卓)TextView ClickSpan与onCli
  4. Android(安卓)动画框架详解,第 1 部分
  5. android基础回顾(三)基础UI组件
  6. Android(安卓)RxJava:细说 线程控制(切换 /
  7. 应用程序的目录结构解析
  8. Android(安卓)AccessibilityService ---
  9. Android•缘
  10. Android产品研发(二十二)-->Android实用调