`
triple_zhao
  • 浏览: 7456 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

android 翻页卷曲效果 电子书翻页

阅读更多

转载请注明来自: 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");
		}
	}
}
      转载请注明来自: 5进制空间-android区

如果这两个view类没研究明白怎么用的话,可以去android 翻页卷曲效果里面寻找获取pageDemo.java,获得使用方法。

分享到:
评论

相关推荐

    Android卷曲翻页效果

    "Android卷曲翻页效果"是一种常见的动画特效,常用于电子书、杂志或图册类应用,为用户提供更真实的阅读体验。这种效果模拟了纸质书翻页时纸张卷曲的动态过程,增加了互动性和趣味性。 要实现这种效果,开发者通常...

    Android 翻页卷曲 电子书源代码

    在Android平台上,开发一款具有翻页卷曲效果的电子书应用是一项常见的需求,这不仅可以提升用户的阅读体验,也能增加应用的吸引力。标题“Android 翻页卷曲 电子书源代码”暗示了我们将深入讨论如何实现这样一个功能...

    android 卷曲电子书(可读100M文件)

    测试卷曲DEMO环境:三星T959 手机一部 系统 android 2.3 测试txt文件位置:请自行将z8806c.txt放置SDcard 根目录,进行测试 测试txt文件大小:98.5 MB(103,387,040 字节)电子书文件一个(为了复制出这么大的文本文件,...

    android 翻页特效

    翻页效果使得移动设备上的屏幕转换更具动态感,模拟了纸质书本翻页的真实触感。 实现Android翻页特效主要涉及到以下几个技术点: 1. **OpenGL ES**:为了实现高度定制和性能优化的翻页效果,开发者可能需要借助于...

    卷曲翻页效果

    而"Book"这个文件名可能代表与书籍或电子书相关的内容,或许包含了实现卷曲翻页效果的具体代码示例或设计思路。 学习并实现卷曲翻页效果,不仅可以提升用户的阅读体验,也是提升开发者图形处理和交互设计能力的良好...

    android翻页

    - 除了`ViewPager`,还有一些第三方库提供了更丰富的翻页效果,如`android-viewpager-indicator`用于指示当前页面,`android-pagecurl`实现了类似卷曲纸张的翻页效果,`android-paging-library`则支持大数据集的...

    Android 实现书籍翻页效果(升级版).zip

    在Android平台上,为应用程序添加真实的书籍翻页效果可以极大地提升用户体验,尤其是在开发电子书阅读器或者杂志类应用时。这个“Android实现书籍翻页效果(升级版)”的压缩包可能包含了一个完整的示例项目,旨在...

    android_page_curl翻书效果.zip

    《Android页面卷曲效果——OpenGL实现的电子书翻页特效》 在移动设备上,用户界面的交互体验是至关重要的,而动态的翻页效果无疑能为应用增添一份独特的魅力。"android_page_curl"项目就是一个专为Android平台设计...

    Android版电子书开发模板源码及成品

    本资源中包含了android电子书制作的一个模板,其中也有卷曲的翻页效果,对于那些想制作电子书但又不知如何下手的初学者来说很有帮助。为了发扬资源共享的意识,0资源分无偿分享给大家,资源中还有一个成型的APK,...

    android 网上集合的9种不同经典效果

    1. **卷曲翻页效果**:这种效果常见于电子书阅读器或相册应用,通过模拟真实的纸张翻页动作,增加用户操作的真实感。实现时可以利用OpenGL ES或者自定义View来绘制页面的弯曲和翻转动画,调整页面的透明度和位置,使...

    android书籍APK源码

    这涉及到Android动画框架的使用,如PageTransformer类,可以实现平滑滑动、卷曲等翻页效果。此外,还要考虑到性能优化,避免过度消耗资源。 5. **模式切换**:模式切换通常包括日间模式和夜间模式,源码会包含主题...

    AndroidPageCurl_20844

    标题“AndroidPageCurl_20844”所指的是一个特定的Android开发项目,它实现了翻页卷曲(Page Curl)特效。在移动设备上,这种特效常用于电子书应用,模拟纸质书页翻动时的真实感。下面将详细讨论Android开发中的Page...

    页面 曲卷 page curls

    在IT行业中,页面曲卷(Page Curl)是一种视觉效果,常用于数字出版物、电子书、杂志或应用程序中,模拟真实书籍翻页时纸张卷起的动态效果。这种技术可以使用户界面更具吸引力,提高用户体验,给人一种更接近实体...

    Book - Page Curl Pro 2.1.zip

    在游戏开发和虚拟现实应用中,模拟真实的书籍翻页效果往往能提升用户体验,为项目增添独特的艺术风格。Unity3D作为一款强大的跨平台游戏引擎,提供了丰富的资源和工具来实现这种效果。"Book - Page Curl Pro 2.1.zip...

Global site tag (gtag.js) - Google Analytics