1、android动画框架详解第2部分Android动画框架详解第2部分来源:IBM developerWorks简介:这是由两部分组成的 Android 动画框架详解的第二部分实例篇。在阅读本篇之前,建议您首先阅读本系列的第一部分 Android 动画框架详解之原理篇。原理篇详细介绍了 Android 动画框架的实现原理,同时介绍了一个绕 Y 轴旋转的动画示例。本篇是在原理篇的基础上介绍一个较复杂的 Android launcher 的平滑和立体翻页效果动画的实现。Android launcher 的平滑和立体翻页效果我们这里把 Android launcher 程序的 Workspace 相关
2、的代码抽取出来,以一个比较简单的代码来展示 launcher 程序是如何实现多页以及不同页面之间的切换效果。本示例代码在 SDK 2.1 中运行,设置的是 WVGA 的屏幕大小。首先我们来看一下程序运行的效果来一些感性的认识。图 1:平滑移动效果图 2:立体翻页效果窗口页面的布局接着我们来看一下程序 UI(即 View 和 ViewGroup)的布局,Activity 的 ContentView 是 layout 中的 main.xml。它的内容如下:清单 1.其中 FlatWorkspace 的基类是 Workspace,它继承自 ViewGroup,是一个容器类,其中包含三个子 View,
3、子 View 是 ImageView。三个 ImageView 就是三个页面。这三个 ImageView 的创建是在 WorkspaceActivity 的 onCreate 函数中调用 Workspace 的 initScreens 函数完成的,代码如下:清单 2 ViewGroup.LayoutParams p = new iewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.FILL_PARENT); for (int i = 0; i 3; i+) this.addView(new
4、 ImageView(this.getContext(), i, p); (ImageView)this.getChildAt(0).setImageResource(R.drawable.image_search); (ImageView)this.getChildAt(1).setImageResource(R.drawable.image_system); (ImageView)this.getChildAt(2).setImageResource(R.drawable.image_top); 图 3:Workspace 和页面布局图为了让三个页面达到上图的窗口布局,我们对 Worksp
5、ace 的 onMeasure 和 onLayout 函数进行了重载,重点在 onLayout 代码中。onLayout 函数调用 layoutScreens 函数完成布局,FlatWorkspace 中的 layoutScreens 实现如下:清单 3 protected void layoutScreens() int childLeft = 0; final int count = getChildCount(); for (int i = 0; i count; i+) final View child = getChildAt(i); if (child.getVisibility(
6、) != View.GONE) final int childWidth = child.getMeasuredWidth(); child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight(); childLeft += childWidth; 上面 child.layout 部分的代码把三个页面分别布局到了 X 和 Y 坐标系中的(0,0)-(ScreenWidth,ScreenHeight)和(ScreenWidth,0)-(2*ScreenWidth,ScreenHeight)以及(2*Screen
7、Width,0)-(3*ScreenWidth,ScreenHeight)三个矩形区域中,这里用矩形区域的左上角顶点坐标和右下角的顶点坐标来表示矩阵。至此我们已经完成了整个窗口页面的布局,窗口页面的布局大小是实际可视屏幕宽度的三倍,所以要显示所有页面需要让页面滚动。页面的平滑移动的实现下面来看用户 touch move 的时候程序如何让页面进行滑动,并且绘制他们。页面的滑动可以调用 View 的 scrollBy 或 ScrollTo 函数,在 Workspace 的 onTouchEvent 函数中取得用户的手指移动的距离,然后调用 scrollBy(它的参数就是 X 和 Y 轴上需要移动的
8、距离)来让 Workspace 这个 View(也是 ViewGroup)移动用户手指移动的距离,当然 View 移动之前得判断一下用户手指移动的距离和速度是否足够才进行移动,以此减少用户的误操作。这部分代码简单就不进行深入分析了,请大家自己看看代码。当 Workspace 这个 View 调用 scrollBy 进行 View 的滚动时,必然导致这个 View 无效,从而被系统重新绘制,所以它的 dispatchDraw 函数会被调用来进行子 View(ImageView)的绘制,它本身没有什么东西要绘制,所以就不用关心 Workspace 的 onDraw 函数了。dispatchDraw
9、 函数会调用 drawScreens(canvas) 来对子 View 进行绘制。我们来看一下 FlatWorkspace 的实现:清单 4 protected void drawScreens(Canvas canvas) final long drawingTime = getDrawingTime(); final int count = getChildCount(); for (int i = 0; i scrollX + width | scrollWidth + width 90 faceDegree -90) return; final float centerX = (scr
10、ollWidth scrollX)?scrollWidth + width:scrollWidth; final float centerY = getHeight()/2; final Camera camera = mCamera; final Matrix matrix = mMatrix; canvas.save(); camera.save(); camera.rotateY(-faceDegree); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix
11、.postTranslate(centerX, centerY); canvas.concat(matrix); drawChild(canvas, child, drawingTime); child.setBackgroundColor(Color.TRANSPARENT); canvas.restore(); 上面函数中的 currentDegree 变量是变化的,不是一个固定的值,改变这个变量值的方法比较隐蔽,在 AngelBaseWorkspace 的 scrollTo 函数中。AngelBaseWorkspace 中的 scrollTo 函数把 View 类中的函数重载了,这个函数
12、会被 View 中的 scrollBy 函数调用,所以每次 touch 屏幕并且 move 的时候 AngelBaseWorkspace 中的 scrollTo 函数会被调用(onTouchEvent 调用 scrollBy,scrollBy 调用 scrollTo),它会根据用户 touch move 移动的距离来更改当前页面的角度,即变量 currentDegree 的值。具体请看如下代码: 清单 8 public void scrollTo(int x, int y) if (getScrollX() != x | getScrollY() != y) int oldX = getScr
13、ollX(); int oldY = getScrollY(); super.scrollTo(x, y); /x is the touch action X direction move distance currentDegree = x * degreeOffset; onScrollChanged(x, y, oldX, oldY); invalidate(); 这个立方体特效部分的代码介绍到这里。结束语本文介绍了 Android launcher 的平滑和立体翻页效果实现,可以帮助开发者深入理解 Android 的动画框架原理,从而能够充分利用 android 现有框架来做出够眩、够酷的动画效果。千锋3G学院:http:/www.mobiletrain.org/千锋嵌入式学院:http:/www.embedtrain.org
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1