Android(安卓)4.0 Launcher2源码分析——Workspace切换AllApps流程
本文来自http://blog.csdn.net/chenshaoyang0011转载请申明文章出处!
文中如有纰漏之处,望不吝指教~~~欢迎讨论,共同学习~~~
进入AllApps界面是通过点击Hotseat中的allAppsButton触发事件,通过前面的分析,已经知道在setupViews()方法中,就为button设置好了onTouchListener:
[java] view plain copy- privatevoidsetupViews(){
- ......
- //Gettheallappsbutton
- mAllAppsButton=findViewById(R.id.all_apps_button);
- if(mAllAppsButton!=null){
- mAllAppsButton.setOnTouchListener(newView.OnTouchListener(){
- @Override
- publicbooleanonTouch(Viewv,MotionEventevent){
- //(MotionEvent.ACTION_POINTER_1_DOWN&MotionEvent.ACTION_MASK)
- //(MotionEvent.ACTION_POINTER_2_DOWN&MotionEvent.ACTION_MASK)
- //(MotionEvent.ACTION_POINTER_3_DOWN&MotionEvent.ACTION_MASK)
- //==MotionEvent.ACTION_DOWN
- if((event.getAction()&MotionEvent.ACTION_MASK)==MotionEvent.ACTION_DOWN){
- onTouchDownAllAppsButton(v);
- }
- returnfalse;
- }
- });
- }
- ......
- }
这里简单说明下,为什么在判断事件的时候不直接使用event.getAction()==MotionEvent.ACTION_DOWN,而是采用(event.getAction()&MotionEvent.ACTION_MASK)==MotionEvent.ACTION_DOWN呢?查看文档,我们可以发现ACTION_MASK的值为0x000000ff,二进制的值为11111111。ACTION_DOWN的值为0x00000000,二进制为00000000。在真实的设备中通常支持多点触控,但根据直观的判断,多指“按下”和单指“按下”都属于“按下”。Android中ACTION_MASK恰恰是为了解决这个问题而存在的因为(MotionEvent.ACTION_POINTER_1_DOWN&MotionEvent.ACTION_MASK)==MotionEvent.ACTION_DOWN,(MotionEvent.ACTION_POINTER_2_DOWN&MotionEvent.ACTION_MASK)==MotionEvent.ACTION_DOWN,(MotionEvent.ACTION_POINTER_3_DOWN&MotionEvent.ACTION_MASK)==MotionEvent.ACTION_DOWN。这就是为什么要先“与”再判断的原因了。ACTION_DOWN被触发后,onTouchDownAllAppsButton()被调用。
[java] view plain copy
- publicvoidonTouchDownAllAppsButton(Viewv){
- //Providethesamehapticfeedbackthatthesystemoffersforvirtualkeys.
- v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
- }
接着,顺着启动的过程,进入到了Hotseat.resetLayout()方法中
[java] view plain copy- voidresetLayout(){
- ......
- allAppsButton.setOnClickListener(newView.OnClickListener(){
- @Override
- publicvoidonClick(android.view.Viewv){
- if(mLauncher!=null){
- mLauncher.onClickAllAppsButton(v);
- }
- }
- });
- ......
- }
- /**
- *Eventhandlerforthe"grid"buttonthatappearsonthehomescreen,which
- *entersallappsmode.
- *
- *@paramvTheviewthatwasclicked.
- */
- publicvoidonClickAllAppsButton(Viewv){
- showAllApps(true);
- }
- voidshowAllApps(booleananimated){
- if(mState!=State.WORKSPACE)return;
- //显示apps_customize也就是AllApps页面,切换时有缩放和渐显的动画
- cameraZoomOut(State.APPS_CUSTOMIZE,animated,false);
- mAppsCustomizeTabHost.requestFocus();
- //Hidethesearchbarandhotseat
- //将searchBar隐藏起来
- mSearchDropTargetBar.hideSearchBar(animated);
- //Changethestate*after*we'vecalledallthetransitioncode
- //将状态mState从WORKSPACE切换到APPS_CUSTOMIZE
- mState=State.APPS_CUSTOMIZE;
- //Pausetheauto-advanceofwidgetsuntilweareoutofAllApps
- //停止对AppWidget的自动更新
- mUserPresent=false;
- updateRunning();
- //将桌面上打开的文件夹关闭
- closeFolder();
- //Sendanaccessibilityeventtoannouncethecontextchange
- getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
- }
进入方法后可以看到,最主要的功能是在cameraZoomOut()方法中,以动画的方式来显示AllApps页。接着隐藏了SearchDropTargetBar和Hotseat。为了节省资源,关闭了AppWidget的自动更新。下面进入cameraZoomOut():
[java] view plain copy- /**
- *Zoomthecameraoutfromtheworkspacetoreveal'toView'.
- *Assumesthattheviewtoshowisanchoredateithertheverytoporverybottom
- *ofthescreen.
- *@paramtoStateThestatetozoomoutto.MustbeAPPS_CUSTOMIZE.
- */
- privatevoidcameraZoomOut(StatetoState,booleananimated,finalbooleanspringLoaded){
- ......
- //设置缩放时的轴心
- setPivotsForZoom(toView,toState,scale);
- //ShrinkworkspacesawayifgoingtoAppsCustomizefromworkspace
- //缩小workspaces然后让它消失。
- mWorkspace.changeState(Workspace.State.SMALL,animated);
- if(animated){
- //如果需要动画,就是用scaleAnim来实现缩放的动画效果
- finalValueAnimatorscaleAnim=ValueAnimator.ofFloat(0f,1f).setDuration(duration);
- scaleAnim.setInterpolator(newWorkspace.ZoomOutInterpolator());
- scaleAnim.addUpdateListener(newLauncherAnimatorUpdateListener(){
- publicvoidonAnimationUpdate(floata,floatb){
- ((View)toView.getParent()).invalidate();
- toView.fastInvalidate();
- toView.setFastScaleX(a*scale+b*1f);
- toView.setFastScaleY(a*scale+b*1f);
- }
- });
- toView.setVisibility(View.VISIBLE);
- toView.setFastAlpha(0f);
- //使用alphaAnim来实现渐显的动画效果
- ValueAnimatoralphaAnim=ValueAnimator.ofFloat(0f,1f).setDuration(fadeDuration);
- alphaAnim.setInterpolator(newDecelerateInterpolator(1.5f));
- alphaAnim.addUpdateListener(newLauncherAnimatorUpdateListener(){
- publicvoidonAnimationUpdate(floata,floatb){
- //don'tneedtoinvalidatebecausewedosoabove
- toView.setFastAlpha(a*0f+b*1f);
- }
- });
- alphaAnim.setStartDelay(startDelay);
- alphaAnim.start();
- if(toViewinstanceofLauncherTransitionable){
- //切换开始时,调用AppsCustomizeTabHost.onLauncherTransitionStart()方法
- ((LauncherTransitionable)toView).onLauncherTransitionStart(instance,scaleAnim,
- false);
- }
- scaleAnim.addListener(newAnimatorListenerAdapter(){
- booleananimationCancelled=false;
- @Override
- publicvoidonAnimationStart(Animatoranimation){
- updateWallpaperVisibility(true);
- //Preparetheposition
- toView.setTranslationX(0.0f);
- toView.setTranslationY(0.0f);
- toView.setVisibility(View.VISIBLE);
- toView.bringToFront();
- }
- @Override
- publicvoidonAnimationEnd(Animatoranimation){
- //Ifwedon'tsetthefinalscalevalueshere,ifthisanimationiscancelled
- //itwillhavethewrongscalevalueandsubsequentcameraPananimationswill
- //notfixthat
- toView.setScaleX(1.0f);
- toView.setScaleY(1.0f);
- if(toViewinstanceofLauncherTransitionable){
- //当切换过程完成时,调用AppsCustomizeTabHost.onLauncherTransitionEnd()方法
- ((LauncherTransitionable)toView).onLauncherTransitionEnd(instance,
- scaleAnim,false);
- }
- ......
- }
- @Override
- publicvoidonAnimationCancel(Animatoranimation){
- animationCancelled=true;
- }
- });
- //toViewshouldappearrightattheendoftheworkspaceshrinkanimation
- if(mStateAnimation!=null)mStateAnimation.cancel();
- mStateAnimation=newAnimatorSet();
- mStateAnimation.play(scaleAnim).after(startDelay);
- mStateAnimation.start();
- }else{
- //不需要动画效果
- ......
- }
这里演示了使用ValueAnimator来实现动画效果的方式。动画结束之后,页面的切换就完成了。
更多相关文章
- android 下 数据持久化
- android调用python脚本
- Android(安卓)值动画一(ObjectAnimator)
- 浏览Butter Knife源码收获
- 关于android消息处理的个人理解
- android webView调用js函数的几种方法
- Android应用开发提高系列——Android动态加载(下)——加载已安装AP
- Android中关联源码的方法
- android onMeasure 实现