`

【转】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"

)

;


		}


	}


}

分享到:
评论

相关推荐

    android电子书翻页效果

    在Android平台上,为电子书实现逼真的翻页效果是一项常见的需求,这能为用户带来更加沉浸式的阅读体验。本文将详细探讨如何在Android应用中创建这样的翻页效果,包括技术原理、实现方法以及可能遇到的问题。 首先,...

    android 电子书翻页效果

    在Android平台上开发电子书应用时,为用户提供逼真的翻页效果是提升阅读体验的重要一环。"android 电子书翻页效果"这个话题涉及到的是如何在Android应用中实现类似纸质书翻页的动画效果,让电子阅读更加生动有趣。...

    Android仿照iReader电子书翻页效果实现

    本例子详细讲解怎么在Android中使用java实现翻页效果,就像电子阅读器那样。翻页效果在Android日常开发中已经非常普遍,机密不再是机密,现在来展示两年前写的Demo程序,希望对大家理解这篇文章有一定帮助

    Android 翻页效果源代码demo

    【Android 翻页效果源代码demo】是一个专注于实现Android平台上仿纸质翻页效果的应用示例,它提供了类似于电子书的用户体验。这个项目由"5度空间"开发,旨在帮助开发者理解和实现动态、自然的翻页动画,为阅读类应用...

    android 翻页电子书代码

    在Android平台上,开发一款能实现翻页效果的电子书应用是一项技术挑战,涉及到多个关键知识点。这个"android 翻页电子书代码"项目显然旨在提供一个这样的解决方案,让用户能够像翻阅实体书籍一样,享受流畅、逼真的...

    Android翻页电子书效果

    综上所述,实现“Android翻页电子书效果”需要掌握Android动画系统、自定义View绘图、触摸事件处理等技术,并可能涉及性能优化和用户体验设计。通过不断的实践和学习,开发者可以创建出令人满意的电子书阅读应用。

    android翻页效果(阅读器)

    这个项目名为"android翻页效果(阅读器)",它提供了一个完整的解决方案,允许用户通过手势来移动页眉和页脚,营造出逼真的阅读体验。下面我们将深入探讨实现这种翻页效果的关键技术和步骤。 首先,我们要理解翻页...

    android实现电子书翻页效果完整源码

    在Android平台上开发一款阅读软件,实现电子书的翻页效果是一项常见的需求,它能为用户提供更接近纸质书的阅读体验。本项目名为“android实现电子书翻页效果完整源码”,提供了一套完整的解决方案,包括卷轴翻页和四...

    Android 电子书翻页效果(增强了翻页效果,算法可以参考)

    在Android平台上开发电子书应用时,提供一个逼真的翻页效果是提升用户体验的关键因素之一。本文将深入探讨如何实现Android电子书的翻页效果,尤其是通过贝塞尔曲线算法来增强这种效果。 首先,我们需要理解贝塞尔...

    Android 3D特效相册+电子书翻页效果

    在Android开发中,3D特效相册和电子书翻页效果是提高用户体验的重要技术手段,尤其是在多媒体应用和阅读类应用中。本项目聚焦于这两项技术的实现,为用户提供更加生动且互动性强的视觉体验。 首先,让我们深入探讨...

    Android 翻页效果实现源码

    下面我们将深入探讨这个主题,介绍Android翻页效果的基本原理、实现方法以及可能遇到的关键技术点。 一、翻页效果的基本概念 翻页效果,又称为“仿真翻书”或“卷轴效果”,模拟了纸质书籍翻页的动态过程,使得...

    Android 电子书(翻页)

    电子书应用的核心功能之一是翻页效果。在Android中,这通常通过自定义View或使用动画库来实现。开发者可能利用Canvas绘制页面,通过平移、旋转等变换模拟纸张翻动的视觉效果。此外,他们可能还会结合触摸事件,让...

    android电子书的翻页

    3. **兼容性**:考虑到Android设备的多样化,我们需要确保翻页效果在不同分辨率、屏幕尺寸和Android版本的设备上都能正常工作。 4. **资源管理**:电子书通常包含大量文字和图像,因此加载和缓存策略的优化至关重要...

    Android电子书翻页效果

    在Android应用开发中,创建一个逼真的电子书翻页效果是一项常见的需求,它可以极大地提升用户的阅读体验。在本文中,我们将深入探讨如何实现这一效果,主要聚焦于使用线性渐变来模拟纸张翻页的视觉过渡。 首先,...

    Android网络图片仿电子书翻页效果

    在Android开发中,实现网络图片的电子书翻页效果是一项挑战性的任务,它涉及到多个技术领域的结合,包括网络请求、图像处理、动画效果等。这个项目"Android网络图片仿电子书翻页效果"旨在为用户提供一种类似真实书籍...

    Android卷曲翻页效果

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

Global site tag (gtag.js) - Google Analytics