在上一篇文章中,我们学习了Camera的基本用法,并借助它们编写了一个例子,实现了类似于API Demos里的图片中轴旋转功能。不过那个例子的核心代码是来自于API Demos中带有的Rotate3dAnimation这个类,是它帮助我们完成了所有的三维旋转操作,所有Matrix和Camera相关的代码也是封装在这个类中。
这样说来的话,大家心里会不会痒痒的呢?虽然学习了Camera的用法,但却没有按照自己的理解来实现一套非常炫酷的3D效果。不要着急,今天我就带着大家一起来实现一种3D推拉门式的滑动菜单,而且完全不会借助任何API Demos里面的代码。
当然如果你还不是很了解Camera的使用方式,可以先去阅读我的上一篇文章 http://www.fengfly.com/plus/view-215100-1.html 。
关于滑动菜单的文章我也已经写过好几篇了,相信看过的朋友对滑动菜单的实现方式应该都已经比较熟悉了,那么本篇文章的重点就在于,如何在传统滑动菜单的基础上加入推拉门式的立体效果。还不了解滑动菜单如何实现的朋友,可以去翻一翻我之前的文章。
下面还是回到正题,首先来讲一下这次的实现原理吧,其实传统的滑动菜单功能就是把菜单部分放在了下面,主布局放在了上面,然后根据手指滑动的距离来偏移主布局,让菜单部分得以显示出来就行了。不过我们这次既然要做推拉门式的立体效果,就需要将传统的思维稍微转变一下,可以先让菜单部分隐藏掉,但却复制一个菜单的镜像并生成一张图片,然后在手指滑动的时候对这张图片进行三维操作,让它产生推拉门式的效果,等滑动操作结束的时候,才让真正的菜单显示出来,然后将这个图片隐藏。原理示意图如下所示:
那么下面我们就开始动手实现吧,首先新建一个Android项目,起名叫做ThreeDSlidingLayoutDemo。
然后新建一个Image3dView类继承自View,用于生成镜像图片,以及完成三维操作,代码如下所示:
- public class Image3dView extends View {
- /**
- * 源视图,用于生成图片对象。
- */
- private View sourceView;
- /**
- * 根据传入的源视图生成的图片对象。
- */
- private Bitmap sourceBitmap;
- /**
- * 源视图的宽度。
- */
- private float sourceWidth;
- /**
- * Matrix对象,用于对图片进行矩阵操作。
- */
- private Matrix matrix = new Matrix();
- /**
- * Camera对象,用于对图片进行三维操作。
- */
- private Camera camera = new Camera();
- /**
- * Image3dView的构造函数
- *
- * @param context
- * @param attrs
- */
- public Image3dView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- /**
- * 提供外部接口,允许向Image3dView传入源视图。
- *
- * @param view
- * 传入的源视图
- */
- public void setSourceView(View view) {
- sourceView = view;
- sourceWidth = sourceView.getWidth();
- }
- /**
- * 清除掉缓存的图片对象。
- */
- public void clearSourceBitmap() {
- if (sourceBitmap != null) {
- sourceBitmap = null;
- }
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (sourceBitmap == null) {
- getSourceBitmap();
- }
- // 计算图片需要旋转的角度
- float degree = 90 - (90 / sourceWidth) * getWidth();
- camera.save();
- camera.rotateY(degree);
- camera.getMatrix(matrix);
- camera.restore();
- // 将旋转的中心点移动到屏幕左边缘的中间位置
- matrix.preTranslate(0, -getHeight() / 2);
- matrix.postTranslate(0, getHeight() / 2);
- canvas.drawBitmap(sourceBitmap, matrix, null);
- }
- /**
- * 获取源视图对应的图片对象。
- */
- private void getSourceBitmap() {
- if (sourceView != null) {
- sourceView.setDrawingCacheEnabled(true);
- sourceView.layout(0, 0, sourceView.getWidth(), sourceView.getHeight());
- sourceView.buildDrawingCache();
- sourceBitmap = sourceView.getDrawingCache();
- }
- }
- }
可以看到,Image3dView中提供了一个setSourceView()方法,用于传递源视图进来,我们稍后复制镜像就是对它进行复制。然后在onDraw()方法里对sourceBitmap进行判断,如果为空,则去调用getSourceBitmap()方法来生成一张镜像图片,getSourceBitmap()方法的细节大家自己去看。在获得了镜像图片之后,接下来就是要计算图片的旋转角度了,这里根据Image3dView当前的宽度和源视图的总宽度进行对比,按比例算出旋转的角度。然后调用Camera的rotateY()方法,让图片团练Y轴进行旋转,并将旋转的中心点移动到屏幕左边缘的中间位置,这几行代码我们在上篇文章中已经见过了,算是挺熟悉了吧!最后调用Canvas的drawBitmap()方法把图片绘制出来。
本文地址 : http://www.fengfly.com/plus/view-215101-1.html
标签: Android |