`

Android实现书籍翻页效果--扩展版(转)

 
阅读更多

转载自:http://blog.csdn.net/xu_fu/article/details/7769740

 

最近由于需要实现Android上的书籍翻页效果,于是就在CSDN上找到了何明桂(http://blog.csdn.net/hmg25)的一个系列文章,在此感谢大神的无私奉献。具体原理何大神已经将的很清楚了,具体请看

Android 实现书籍翻页效果----原理篇

Android 实现书籍翻页效果----完结篇

Android 实现书籍翻页效果----升级篇

Android 实现书籍翻页效果---番外篇之光影效果

在此基础上我做了一些修改,

1、将其改写为一个FrameLayout,可以通过BaseAdapter添加其他的布局文件;

2、从中间分页,采用两页的结构;

效果如下


具体的思路还是通过计算翻页过程中各个视图的显示区域,然后控制canvas的绘制过程。何大神实现了将文字转化为相应的图片,之后交给canvas绘制在屏幕上。那么控件或者布局该如何绘制呢?其实控件和布局本质都是view,他们的绘制过程最终都是通过canvas的draw方法绘制在屏幕上的,而且view的绘制是通过调用draw(canvas)方法实现,(view视图绘制原理请看->http://blog.csdn.net/qinjuning/article/details/7110211),因此就可以通过控制canvas来绘制不同的显示区域。

分析一下:

首先,FramLayout绘制过程会调用onDraw(),在onDraw里会调用dispatchDraw()用于绘制子视图,在dispatchDraw里又会调用drawChild()来分别绘制各个子视图,因此我们需要在这里控制一下canvas。

 

[java] view plaincopy
 
  1. protected boolean drawChild(Canvas canvas, View child, long drawingTime) {  
  2.         // TODO Auto-generated method stub  
  3.         if(child.equals(currentView)) {  
  4.             drawCurrentPageArea(canvas, child, mPath0);  
  5.         } else {  
  6.             drawNextPageAreaAndShadow(canvas, child);  
  7.         }  
  8.               
  9.         return true;  
  10.     }  


其中在drawCurrentPageArea和drawNextPageArea里都会对canvas进行处理,如下

 

 

[java] view plaincopy
 
  1. private void drawCurrentPageArea(Canvas canvas, View child, Path path) {  
  2.         mPath0.reset();  
  3.         mPath0.moveTo(mBezierStart1.x, mBezierStart1.y);  
  4.         mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x,  
  5.                 mBezierEnd1.y);  
  6.         mPath0.lineTo(mTouch.x, mTouch.y);  
  7.         mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y);  
  8.         mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x,  
  9.                 mBezierStart2.y);  
  10.         mPath0.lineTo(mCornerX, mCornerY);  
  11.         mPath0.close();  
  12.   
  13.         canvas.save();  
  14.         canvas.clipPath(path, Region.Op.XOR);//这里即裁剪出了当前页应该绘制的区域  
  15.         child.draw(canvas);//这里再将canvas交给子视图绘制  
  16.         canvas.restore();  
  17.     }  

 

[java] view plaincopy
 
  1. private void drawNextPageAreaAndShadow(Canvas canvas, View child) {  
  2.         mPath1.reset();  
  3.         mPath1.moveTo(mBezierStart1.x, mBezierStart1.y);  
  4.         mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);  
  5.         mPath1.lineTo(mBeziervertex2.x, mBeziervertex2.y);  
  6.         mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);  
  7.         mPath1.lineTo(mCornerX, mCornerY);  
  8.         mPath1.close();  
  9.   
  10.         mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x  
  11.                 - mCornerX, mBezierControl2.y - mCornerY));  
  12.         int leftx;  
  13.         int rightx;  
  14.         GradientDrawable mBackShadowDrawable;  
  15.         if (mIsRTandLB) {  
  16.             leftx = (int) (mBezierStart1.x);  
  17.             rightx = (int) (mBezierStart1.x + mTouchToCornerDis / 4);  
  18.             mBackShadowDrawable = mBackShadowDrawableLR;  
  19.         } else {  
  20.             leftx = (int) (mBezierStart1.x - mTouchToCornerDis / 4);  
  21.             rightx = (int) mBezierStart1.x;  
  22.             mBackShadowDrawable = mBackShadowDrawableRL;  
  23.         }  
  24.         canvas.save();  
  25.         canvas.clipPath(mPath0);  
  26.         canvas.clipPath(mPath1, Region.Op.INTERSECT);//这里裁剪出下一页应该绘制的区域  
  27.         child.draw(canvas);//这里子视图开始绘制  
  28.         canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);//这里旋转是用来画阴影的  
  29.         mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx,  
  30.                 (int) (mMaxLength + mBezierStart1.y));  
  31.         mBackShadowDrawable.draw(canvas);  
  32.         canvas.restore();  
  33.     }  

还有对当前页背面的绘制过程是一样的,除了裁剪出指定的区域,还有就是对绘制图像的旋转操作,想深入分析的可以看源代码。

其他相关说明:

1、这里为什么采用FrameLayout?

因为FramLayout布局是上下叠加的,这样就可以同时添加几个子视图而只显示其中的一个,如果用LinearLayout子视图只能垂直或者平行布置,无法完成上下同时显示的效果,这里换成RelativeLayout应该也是可以的,感兴趣的同学可以试一下。

2、关于添加子视图的问题。

我在FrameLayout里添加了3个子视图

 

[java] view plaincopy
 
  1. private View currentView = null;//当前显示视图  
  2. private View nextView = null;//翻页后显示视图  
  3. private View nextViewTranscript = null;//翻页后显示视图副本,用于翻页过程中当前页背面的显示  

之后在加载BaseAdapter的时候对着三个视图实例化并添加到FramLayout里,代码如下

 

 

[java] view plaincopy
 
  1. public void setAdapter(BaseAdapter adapter) {  
  2.         mAdapter = adapter;  
  3.         itemCount = mAdapter.getCount();  
  4.         currentView = null;  
  5.         nextView = null;  
  6.         nextViewTranscript = null;  
  7.         removeAllViews();  
  8.         if(itemCount != 0) {  
  9.             currentPosition = 0;  
  10.             currentView = mAdapter.getView(currentPosition, nullnull);//取得实例  
  11.             addView(currentView);//添加到父视图里  
  12.             if(itemCount > 1) {  
  13.                 nextView = mAdapter.getView(currentPosition+1nullnull);//取得实例,添加  
  14.                 nextViewTranscript = mAdapter.getView(currentPosition+1nullnull);  
  15.                 addView(nextView);  
  16.                 addView(nextViewTranscript);  
  17.             }  
  18.         } else {  
  19.             currentPosition = -1;  
  20.         }  
  21.           
  22.         mTouch.x = 0.01f;  
  23.         mTouch.y = 0.01f;  
  24.         mCornerX = 0;  
  25.         mCornerY = 0;  
  26.         postInvalidate();  
  27.           
  28.     }  

因为三个显示的视图只在这里添加一次,因此当翻页改变内容是需要对这三个视图进行复用,也就是在mAdapter.getView()时只改变内容,而不返回新的实例,BaseAdapter的getView()方法如下

 

 

[java] view plaincopy
 
  1. @Override  
  2.     public View getView(int position, View convertView, ViewGroup parent) {  
  3.         // TODO Auto-generated method stub  
  4.         ViewGroup layout;  
  5.         if(convertView == null) {//convertView即传入的当前要改变内容的视图,这里判断是否已创建  
  6.             layout = (ViewGroup) inflater.inflate(R.layout.item_layout, null);//创建实例  
  7.         } else {  
  8.             layout = (ViewGroup) convertView;//复用实例  
  9.         }  
  10.         setViewContent(layout, position);//这里来改变现实内容  
  11.           
  12.         return layout;  
  13.     }  

这样就会产生2点限制,1、不同页的内容结构是必须是一样的,也就是用的同一个布局;2、baseAdapter的getview方法需要对convertView进行判断是否进行复用。

 

Bug修正:

2012.7.23     从右向左翻页时阴影绘制不正确,原因:扩展的时候没有修改mMaxLength,导致阴影长度计算出错;

       修正方法:在onMeasure()函数中添加mMaxLength的计算,如下

 

[java] view plaincopy
 
  1. @Override  
  2.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  3.         // TODO Auto-generated method stub  
  4.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  5.           
  6.         mWidth = getWidth();  
  7.         mHeight = getHeight();  
  8.         mMaxLength = (float) Math.hypot(mWidth, mHeight);               //添加在这里  
  9.           
  10.     }  



 

 

示例Demo源码下载->http://download.csdn.net/detail/xu_fu/4443142

Bug修正:

2012.11.17    修复了不能点击按钮的问题,因为视图上下叠加,上下层的按钮重叠后会使按钮点击无响应或出错,解决方法是在动画结束后将下层的视图隐藏。

修正控件下载->http://download.csdn.net/detail/xu_fu/4776029

分享到:
评论

相关推荐

    Android 实现书籍翻页效果----升级

    这个主题,"Android 实现书籍翻页效果----升级",着重关注的是如何通过编程来模拟真实的纸张翻页动画,使用户在触摸屏幕时能感受到如同翻阅实体书一样的视觉和交互体验。下面我们将深入探讨这一技术的各个方面。 ...

    Android 实现书籍翻页效果----完结篇

    在Android开发中,实现书籍翻页效果是一种常见的增强用户...总之,实现Android书籍翻页效果是一个结合图形绘制、触摸事件处理、动画和性能优化的综合过程。通过不断迭代和优化,我们可以创建出既美观又高效的翻页体验。

    BookPage-Android自定义View实现翻页效果,并附带实现教程.zip

    仿真书籍翻页效果BookPageView简介:实现了仿真翻页效果,教程完整地描述了翻页原理分析到性能优化的过程教程博客:Android自定义View——从零开始实现书籍翻页效果(一) Android自定义View——从零开始实现书籍...

    Android 实现书籍翻页效果TXT阅读器

    综上所述,实现一个Android书籍翻页效果的TXT阅读器是一个涉及多个技术层面的综合项目,涵盖文本处理、UI设计、动画编程和性能优化等多个领域。通过这样的实践,开发者不仅可以提升Android开发技能,还能深入理解...

    Android 真实书籍翻页效果-IT计算机-毕业设计.zip

    在Android平台上进行应用程序开发时,实现真实的书籍翻页效果是一个常见的需求,特别是在教育、阅读类应用中。这个毕业设计项目提供了这样一个功能的源码示例,可以帮助学生或开发者更好地理解和实现这种高级交互...

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

    本项目“Android 实现书籍翻页效果(升级版)”提供了一种优化的实现方法,旨在提升视觉效果和性能。 在Android中,书籍翻页效果通常通过自定义View或者使用第三方库来实现。这个升级版可能包含了一些优化的算法和...

    Android 实现书籍翻页效果

    本教程将详细介绍如何在Android应用中实现书籍翻页效果,通过实际的代码示例帮助开发者理解和实践。 首先,"翻页"效果在Android中通常通过使用视图动画或属性动画来实现。视图动画主要改变视图的视觉属性,而属性...

    Android 逼真翻页效果-IT计算机-毕业设计.zip

    在Android开发领域,实现逼真的翻页效果是提升用户体验的重要一环,特别是在电子书阅读、杂志展示等应用中。这份名为“Android 逼真翻页效果”的资源包,旨在为学习Android编程的学生提供一个毕业设计的参考案例。...

    Android中用ViewPage实现真实翻页效果

    "Android中用ViewPage实现真实翻页效果"这个主题就是关于如何在Android应用中创建类似真实书籍翻页的效果。这种效果通常被用于电子书阅读器或者滑动浏览多页面内容的应用中,给用户带来更生动和自然的互动体验。 `...

    Android_实现书籍翻页效果

    总的来说,Android书籍翻页效果的实现是一个涉及图形学、动画和几何计算的综合过程。理解每个步骤的原理并熟练运用Android的图形API是实现这一效果的关键。开发者需要具备扎实的数学基础,熟悉Canvas和Path的使用,...

    Android 实现书籍翻页效果t

    Android 实现书籍翻页效果t.rarAndroid 实现书籍翻页效果t.rarAndroid 实现书籍翻页效果t.rarAndroid 实现书籍翻页效果t.rarAndroid 实现书籍翻页效果t.rarAndroid 实现书籍翻页效果t.rarAndroid 实现书籍翻页效果t....

    Android程序研发源码Android 实现书籍翻页效果(升级版).zip

    本项目“Android程序研发源码Android 实现书籍翻页效果(升级版)”提供了一个实现这一功能的示例代码,可以帮助开发者深入理解如何在Android平台上创建逼真的翻页动画。 1. **Android动画系统** - Android提供了...

    Android应用源码之android 仿真翻页效果-IT计算机-毕业设计.zip

    本项目“Android应用源码之android 仿真翻页效果”提供了一个完整的示例,帮助开发者理解和实现这一功能。这个源码适用于毕业设计的学习,能够让学生深入理解Android应用程序的开发流程,并且掌握高级UI特效的实现。...

    android pdf 的翻页效果

    在Android平台上实现PDF的翻页效果是一项常见的任务,特别是在开发阅读类应用时。这个话题涉及到多个技术点,包括PDF解析、动画渲染以及用户交互。以下是对这个主题的详细阐述: 1. **PDF解析**:首先,我们需要一...

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

    这个"Android实现书籍翻页效果升级版.zip"压缩包很可能是包含了一个更新的、优化过的书籍翻页动画的代码示例。让我们深入探讨一下如何在Android中实现这种高级的用户界面效果。 首先,书籍翻页效果通常是通过使用...

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

    本项目“Android 实现书籍翻页效果(升级版)”提供了一个实用的解决方案,适用于多个场景,如软著参考、实际项目开发、教学案例、毕业设计、出书项目实例等,对于开发者提升技能和获取高薪职位具有重要意义。...

Global site tag (gtag.js) - Google Analytics