版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Android launcher 的平滑和立体翻页效果我们这里把 Android launcher 程序的 Workspace 相关的代码抽取出来,以一个比较简单的代码来展示 launcher 程序是如何实现多页以及不同页面之间的切换效果。本示例代码在 SDK 2.1 中运行,设置的是 WVGA 的屏幕大小。首先我们来看一下程序运行的效果来一些感性的认识。图 1:平滑移动效果 图 2:立体翻页效果 窗口页面的布局接着我们来看一下程序 UI(即 View 和 ViewGroup)的布局,Activity 的 ContentView 是 layout 中的 main.xml。它
2、的内容如下:清单 1. 其中 FlatWorkspace 的基类是 Workspace,它继承自 ViewGroup,是一个容器类,其中包含三个子 View,子 View 是 ImageView。三个 ImageView 就是三个页面。这三个 ImageView 的创建是在 WorkspaceActivity 的 onCreate 函数中调用 Workspace 的 initScreens 函数完成的,代码如下:清单 2 ViewGroup.LayoutParams p = new iewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_P
3、ARENT,ViewGroup.LayoutParams.FILL_PARENT); for (int i = 0; i < 3; i+) this.addView(new 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
4、).setImageResource(R.drawable.image_top); 图 3:Workspace 和页面布局图 为了让三个页面达到上图的窗口布局,我们对 Workspace 的 onMeasure 和 onLayout 函数进行了重载,重点在 onLayout 代码中。onLayout 函数调用 layoutScreens 函数完成布局,FlatWorkspace 中的 layoutScreens 实现如下:清单 3 protected void layoutScreens() int childLeft = 0; final int count = getChildC
5、ount(); for (int i = 0; i < count; i+) final View child = getChildAt(i); if (child.getVisibility() != View.GONE) final int childWidth = child.getMeasuredWidth(); child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight(); childLeft += childWidth; 上面 child.layout 部分的代码把三个页面分别布局到了
6、 X 和 Y 坐标系中的(0,0)-(ScreenWidth,ScreenHeight)和(ScreenWidth,0)-(2*ScreenWidth,ScreenHeight)以及(2*ScreenWidth,0)-(3*ScreenWidth,ScreenHeight)三个矩形区域中,这里用矩形区域的左上角顶点坐标和右下角的顶点坐标来表示矩阵。至此我们已经完成了整个窗口页面的布局,窗口页面的布局大小是实际可视屏幕宽度的三倍,所以要显示所有页面需要让页面滚动。页面的平滑移动的实现下面来看用户 touch move 的时候程序如何让页面进行滑动,并且绘制他们。页面的滑动可以调用 View 的
7、scrollBy 或 ScrollTo 函数,在 Workspace 的 onTouchEvent 函数中取得用户的手指移动的距离,然后调用 scrollBy(它的参数就是 X 和 Y 轴上需要移动的距离)来让 Workspace 这个 View(也是 ViewGroup)移动用户手指移动的距离,当然 View 移动之前得判断一下用户手指移动的距离和速度是否足够才进行移动,以此减少用户的误操作。这部分代码简单就不进行深入分析了,请大家自己看看代码。当 Workspace 这个 View 调用 scrollBy 进行 View 的滚动时,必然导致这个 View 无效,从而被系统重新绘制,所以它的
8、 dispatchDraw 函数会被调用来进行子 View(ImageView)的绘制,它本身没有什么东西要绘制,所以就不用关心 Workspace 的 onDraw 函数了。dispatchDraw 函数会调用 drawScreens(canvas) 来对子 View 进行绘制。我们来看一下 FlatWorkspace 的实现:清单 4 protected void drawScreens(Canvas canvas) final long drawingTime = getDrawingTime(); final int count = getChildCount(); for (int
9、i = 0; i < count; i+) drawChild(canvas, getChildAt(i), drawingTime); 这里的 canvas 宽高就是屏幕可视范围的大小(如 HVGA 屏幕的 320 × 480 大小),而三个子 ImageView 的布局要超出屏幕的范围,不在屏幕可视范围之内的部分是不会被绘制的。这个绘制三个子 ImageView 的函数很重要,是制作立方体翻页等特效的关键地方,FlatWorkspace 实现的是平滑滑动效果,所以我们直接绘制三个子 ImageView。如果要实现立方体的效果,在绘制三个子 ImageView 的时候就要让它
10、们被绘制的时候有立体感,这个在 android 中我们可以通过上文提到的 Camera 类沿 Y 轴旋转一定的角度实现。程序让用户进行 touch move 操作的目的是让用户选择一个页面,如果按照上面的实现,当用户最后抬起手指时,页面切换不会很彻底,而是象图 1 一样停留在两个页面之间。所以当用户抬起手指时程序需判断一下移动到下一个完整的页面还有多大距离,然后让 Workspace 这个 View 再移动这个距离一遍完整的切换到下一页。在这个移动的过程中,为了给用户一个平滑的感觉,不能一下就移动这个距离,而是需要给一定的时间间隔,在这个时间段里逐渐的移动到位,所以这里我们使用 Scrolle
11、r 类的方法实现逐渐的移动。具体过程是在 Workspace 的 onTouchEvent 函数中检测到用户 touch up(抬起手指)时进行应该调整到哪个页面的判断,然后调用 snapToScreen(targetScreen) 跳转到需要目的页面,然后它调用 scrollToScreen(screen) 让 Workspace 这个 View 进行需要的滚动,这个函数在 FlatWorkspace 中的实现如下:清单 5 public void scrollToScreen(int screen) final int newX = screen * getWidth(); final i
12、nt deltaX = newX - getScrollX(); Log.e("FlatWorkspace","scrollToScreen call mScroller.startScroll"); mScroller.startScroll(getScrollX(), getScrollY(), deltaX, getScrollY(), Math.abs(deltaX) * 2); invalidate(); 这里的重点是 mScroler.startScroll 部分的代码,它让 Workspace view 在时间段 Math.abs(delt
13、aX) * 2 里移动下一个目标页面可视化需要移动的距离 deltaX(及目的页面的坐标减去目前已经移动的距离),大家请好好看一下这个 deltaX 的计算,这里不细说了。这个 mScroller.startScroll 并不会导致 Workspace 立即进行移动,它只会导致当前 View 无效,从而重新绘制,在 Workspace 被它的父亲 View 调用绘制的时候,它的 computeScroll 函数会被调用,所以会在这个函数中让 Workspace 调用 scrollTo 函数进行实际的移动。代码如下:清单 6 public void computeScroll() if (mSp
14、uteScrollOffset() scrollTo(mScroller.getCurrX(), mScroller.getCurrY(); /postInvalidate(); else if (mNextScreen != INVALID_SCREEN) mCurrentScreen = mNextScreen; mNextScreen = INVALID_SCREEN; 至此,我们对 Workspace 的整个运行机制和平滑移动的效果是如何实现的已经介绍完成了。下面我们来具体谈谈立体翻页效果是如何实现的。立体翻页效果的实现通过前面的分析可知,立体翻页效果可以在平滑翻页效果的基础上通过改写
15、三个子 ImageView 的绘制来完成。同时可知,翻页时用户操作过程分为三步:放下手指触摸屏幕,移动手指,抬起手指。手指触摸屏幕表示页面之间的滑动要开始了;移动手指的时候页面应该跟着用户手指的移动距离进行对应距离的移动,同时系统会根据页面的移动位置对 Workspace 里面的三个子 View(即页面)进行绘制;抬起手指的时候判断应该移动到哪个页面,还需要移动多少距离,然后平滑的移动需要的距离来跳转到目的页面上。为了显示立体效果,对每个子 ImageView 的绘制时得想办法让它沿 Y 轴旋转一定的角度,前面已经提到 android 通过 Camera 这个类提供了这个功能,不需要使用 op
16、engl ES 的东西,当然如果要做出更好的 3D 效果,我们就需要 opengl ES 的强大功能了。既然要旋转一定的角度,那这个角度怎么计算呢?我们把这个角度和用户手指移动的距离关联起来。因为这个立方体只会沿着 Y 轴旋转,我们只看这三个面的立方体的顶部就够了,它的顶部沿着 Y 轴的往其箭头指示的方向看是一个等边三角形,每个面相对于手机屏幕的沿着 Y 轴旋转的角度的计算方法如下图所示:图 4:初始屏幕位置示意图 下图为屏幕 1 沿 Y 轴旋转 45 读后其他两个屏幕需要沿 Y 轴旋转的角度。图 5:旋转 45 度后屏幕位置示意图这个变换的部分请看代码 CubeWorkspace
17、中函数 drawScreen 的代码,如下:清单 7 protected void drawScreen(Canvas canvas, int screen, long drawingTime) final int width = getWidth(); final int scrollWidth = screen * width; final int scrollX = this.getScrollX(); if(scrollWidth > scrollX + width | scrollWidth + width < scrollX) return; final View ch
18、ild = getChildAt(screen); final int faceIndex = screen; final float faceDegree = currentDegree - faceIndex * preFaceDegree; if(faceDegree > 90 faceDegree < -90) return; final float centerX = (scrollWidth < scrollX)?scrollWidth + width:scrollWidth; final float centerY = getHeight()/2; final
19、Camera camera = mCamera; final Matrix matrix = mMatrix; canvas.save(); camera.save(); camera.rotateY(-faceDegree); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); canvas.concat(matrix); drawChild(canvas, child, drawingTime); child.setBackgroundColor(Color.TRANSPARENT); canvas.restore(); 上面函数
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年安徽国防科技职业学院马克思主义基本原理概论期末考试模拟试卷
- 2026年金融投资经理面试题详解
- 2026年光大银行金融市场部总经理管理能力考试题含答案
- 玉林师范学院《中国近代史纲要》2023-2024学年第一学期期末试卷
- 广东龙岗安全员培训课件
- 2026年某项目安全监理实施细则例文(三篇)
- 幼师法制教育培训课件
- 中医诊所医疗垃圾处理制度
- 外卖实习合同模板(3篇)
- 20XX年医疗器械销售年终总结报告
- 果园防草布采购合同范本
- 《黄土原位测试规程》
- 冀教版(2024)三年级上册《称量物体》单元测试(含解析)
- 数学-湖南长郡中学、杭州二中、南师附中三校2025届高三4月联考试题+答案
- 医学三维可视化与虚拟现实技术:革新肝癌腹腔镜手术的探索与实践
- 统编版(2024)八年级上册历史新教材全册知识点复习提纲
- 水平定向钻施工技术应用与管理
- 风险金管理办法
- 校长在食堂从业人员培训会上的讲话
- (高清版)DBJ∕T 13-91-2025 《福建省房屋市政工程安全风险分级管控与隐患排查治理标准》
- 美育视域下先秦儒家乐教思想对舞蹈教育的当代价值研究
评论
0/150
提交评论