编程知识 购物 网址 新闻 笑话 | 软件 日历 阅读 图书馆 China 头条阅读 学淘股 China Travel
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程 CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流
站长资讯 .NET新手 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA VisualStudio ASP.NET-MVC .NET控件开发 EntityFramework WinRT-Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动 Html-Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP OracleERP DynamicsCRM K2 BPM 信息安全 企业信息 Android开发 iOS开发 WindowsPhone WindowsMobile 其他手机 敏捷开发 项目管理 软件工程 SQLServer Oracle MySQL NoSQL 其它数据库 Windows7 WindowsServer Linux
   -> Android开发 -> Android Launcher拖拽事件详解【android4.0 -> 正文阅读

[Android开发]Android Launcher拖拽事件详解【android4.0

AndroidICS4.0版本的launcher拖 拽的流程,基本和2.3的相似。就是比2.3写的封装的接口多了一些,比如删除类的写法就多了个类。等等。4.0的改变有一些,但是不是特别大。这个月一 直在改动Launcher的缩略图的效果,4.0的缩略图的功能没有实现,还得从2.3的Launcher中摘出来。通过做这个缩略图对Launcher 的模块有一点点了解,拿来分享一下Launcher拖拽的工作流程。
有图有真相!

                (1) 先来看看类之间的继承关系
                     


       
                                                          图(1)
                                                                                                                                               
               (2)再来看看Launcher拖拽流程的时序图
               


                                                                       图(2)
下面咱们分步来解析Launcher拖拽的详细过程:
step 1 :先来看看Launcher.java这个类的onCreate()方法中的setupViews()方法中的一部分代码:
Java代码  

// Setup the workspace   mWorkspace.setHapticFeedbackEnabled(false);   mWorkspace.setOnLongClickListener(this);   mWorkspace.setup(dragController);   dragController.addDragListener(mWorkspace);  
Workspace设置长按事件的监听交给了Launcher.java这个类了。所以在主屏上长按事件会走到Launcher.java----->onLongClick()这个方法中去;
step 2 :接着我们来看看Launcher.java中onLongClick()的代码:
Java代码  

public boolean onLongClick(View v) {            ··············    // The hotseat touch handling does not go through Workspace, and we always allow long press           // on hotseat items.           final View itemUnderLongClick = longClickCellInfo.cell;           boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress();           if (allowLongPress && !mDragController.isDragging()) {               if (itemUnderLongClick == null) {                   // User long pressed on empty space                   mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,                           HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);                   startWallpaper();               } else {                   if (!(itemUnderLongClick instanceof Folder)) {                       // User long pressed on an item                       mWorkspace.startDrag(longClickCellInfo);                   }               }           }           return true;       }  
通过itemUnderLongClick == null 来判断,在屏幕上触发长按事件是否选中了shortcut或者widget。如果为空,就启动桌面的壁纸,else,就把拖拽事件往Workspace.java这个类传递。
Step 3 :通过mWorkspace.startDrag(longClickCellInfo),把长按事件传递给workspace来处理,具体来看代码:
Java代码  

void startDrag(CellLayout.CellInfo cellInfo) {        View child = cellInfo.cell;           // Make sure the drag was started by a long press as opposed to a long click.        if (!child.isInTouchMode()) {            return;        }           mDragInfo = cellInfo;        //隐藏拖拽的child        child.setVisibility(GONE);           child.clearFocus();        child.setPressed(false);           final Canvas canvas = new Canvas();           // We need to add extra padding to the bitmap to make room for the glow effect        final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;           // The outline is used to visualize where the item will land if dropped        mDragOutline = createDragOutline(child, canvas, bitmapPadding);        beginDragShared(child, this);    }  
上面的代码主要做的工作是:把正在拖拽的这个view隐藏掉,在主屏幕上绘制一个蓝色的,大小和图标相似的一个边框,以表示能在主屏的这个位置放置。
Step 4 :接着调用beginDragShared(child, this)这个方法,代码如下:
Java代码  

 public void beginDragShared(View child, DragSource source) {       ··· ···   // Clear the pressed state if necessary           if (child instanceof BubbleTextView) {               BubbleTextView icon = (BubbleTextView) child;               icon.clearPressedOrFocusedBackground();           }              mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),                   DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect);           b.recycle();       }  
这个方法做的工作是:开始进行拖拽,绘制正在拖拽的图片,把拖拽的事件交给DragController来处理。
Step 5 :接 着来看看mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(), DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect)这个方法,代码如下:
Java代码  

 public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,               DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion) {   ··· ···    mDragObject.dragComplete = false;           mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);           mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);           mDragObject.dragSource = source;           mDragObject.dragInfo = dragInfo;   mVibrator.vibrate(VIBRATE_DURATION);              final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,                   registrationY, 0, 0, b.getWidth(), b.getHeight());              if (dragOffset != null) {               dragView.setDragVisualizeOffset(new Point(dragOffset));           }           if (dragRegion != null) {               dragView.setDragRegion(new Rect(dragRegion));           }              dragView.show(mMotionDownX, mMotionDownY);           handleMoveEvent(mMotionDownX, mMotionDownY);       }  
这 个方法的作用是:计算要拖拽的view的大小,显示在workspace上,dragView.show(mMotionDownX, mMotionDownY);这个show()会根据手指的移动而移动的。然后在通过handleMoveEvent()方法来分发拖拽的目标到底在哪个 目标上。DropTarget一共有3个:workspace,ButtonDropTarget(删除类),Folder;他们分别实现了 DropTarget这个接口。
下面来看看这个接口有一下几个方法:
Java代码  

boolean isDropEnabled();   void onDrop(DragObject dragObject);          void onDragEnter(DragObject dragObject);          void onDragOver(DragObject dragObject);          void onDragExit(DragObject dragObject);   DropTarget getDropTargetDelegate(DragObject dragObject);   boolean acceptDrop(DragObject dragObject);          // These methods are implemented in Views       void getHitRect(Rect outRect);       void getLocationInDragLayer(int[] loc);       int getLeft();       int getTop();  
这些方法不是每个类继承了DropTarget的接口,都要把每个方法都实现,这要看具体的需要来定。
另外这个接口中有个内部类-----DragObject:如下
Java代码  

class DragObject {           public int x = -1;           public int y = -1;              /** X offset from the upper-left corner of the cell to where we touched.  */           public int xOffset = -1;              /** Y offset from the upper-left corner of the cell to where we touched.  */           public int yOffset = -1;              /** This indicates whether a drag is in final stages, either drop or cancel. It           * differentiates onDragExit, since this is called when the drag is ending, above           * the current drag target, or when the drag moves off the current drag object.           */           public boolean dragComplete = false;              /** The view that moves around while you drag.  */           public DragView dragView = null;              /** The data associated with the object being dragged */           public Object dragInfo = null;              /** Where the drag originated */           public DragSource dragSource = null;              /** Post drag animation runnable */           public Runnable postAnimationRunnable = null;              /** Indicates that the drag operation was cancelled */           public boolean cancelled = false;              public DragObject() {           }       }  
这个类的作用是存储一些坐标,拖拽点距离整个view左上角x轴上的距离,y轴上的距离,还有一些拖拽的信息都保存在这个类中,还有动画线程类等等。在拖拽过程中这些信息都是会用到的。
Step 6 :接 着来看看handleMoveEvent()这个类,这个类频繁被调用,因为在DragLayer.java这个类中onTouchEvent()方法, 最后调用的是 mDragController.onTouchEvent(ev)这个方法,长按后,移动的事件就传递到了DragController中的 onTouchEvent()方法中,先来看看mDragController.onTouchEvent(ev)这个方法,代码如下:
Java代码  

/**       * Call this from a drag source view.       */       public boolean onTouchEvent(MotionEvent ev) {           if (!mDragging) {               return false;           }              final int action = ev.getAction();           final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());           final int dragLayerX = dragLayerPos[0];           final int dragLayerY = dragLayerPos[1];              switch (action) {           case MotionEvent.ACTION_DOWN:               // Remember where the motion event started               mMotionDownX = dragLayerX;               mMotionDownY = dragLayerY;                  if ((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) {                   mScrollState = SCROLL_WAITING_IN_ZONE;                   mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);               } else {                   mScrollState = SCROLL_OUTSIDE_ZONE;               }               break;           case MotionEvent.ACTION_MOVE:               handleMoveEvent(dragLayerX, dragLayerY);               break;           case MotionEvent.ACTION_UP:               // Ensure that we've processed a move event at the current pointer location.               handleMoveEvent(dragLayerX, dragLayerY);                  mHandler.removeCallbacks(mScrollRunnable);               if (mDragging) {                   drop(dragLayerX, dragLayerY);               }               endDrag();               break;           case MotionEvent.ACTION_CANCEL:               cancelDrag();               break;           }              return true;       }  
在这个方法中清楚的可以看见handleMoveEvent()这个方法会在move,up的时候频繁地调用。
现在再来看看这个handleMoveEvent()方法,看看它的庐山真面目:
Java代码  

private void handleMoveEvent(int x, int y) {           mDragObject.dragView.move(x, y);              // Drop on someone?           final int[] coordinates = mCoordinatesTemp;           DropTarget dropTarget = findDropTarget(x, y, coordinates);           mDragObject.x = coordinates[0];           mDragObject.y = coordinates[1];           if (dropTarget != null) {               DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);               if (delegate != null) {                   dropTarget = delegate;               }                  if (mLastDropTarget != dropTarget) {                   if (mLastDropTarget != null) {                       mLastDropTarget.onDragExit(mDragObject);                   }                   dropTarget.onDragEnter(mDragObject);               }               dropTarget.onDragOver(mDragObject);           } else {               if (mLastDropTarget != null) {                   mLastDropTarget.onDragExit(mDragObject);               }           }           mLastDropTarget = dropTarget;      ··· ···   }  
   
这 个方法的作用:通过findDropTarget(x, y, coordinates),来判断在哪个拖拽目标里面,然后通过下面的if判断来执行不同的onDragOver,onDragExit等的方法。这样就 在相应的类中去做处理,以后的事情就明朗了。这就是Launcher的拖拽事件的分发与处理,用到了MVC的思想,代码阅读起来还是比较顺利的。有图有真 相。
欢迎大家留言讨论相关问题。
  Android开发 最新文章
Android动态权限申请
使用Kotlin,抛弃findViewById
.net程序员做的第一个安卓APP
Android学习笔记
计算机毕业设计源码分享
计算机毕业设计源码分享
ELF Format 笔记(一)—— 概述
Fragment学习笔记
Android复制Assets目录下的文件到指定目录
Android网络请求框架AsyncHttpClient实例详
上一篇文章      下一篇文章      查看所有文章
加:2015-03-30 07:50:33  更:2017-05-16 20:32:48 
 
360图书馆 软件开发资料 购物精选 新闻资讯 Chinese Culture 三丰软件 开发 中国文化 阅读网 头条阅读 学淘股 China Travel 日历 万年历 2020年7日历
2020-7-3 20:46:44
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  编程知识