【源码剖析】Launcher 8.0 源码 31---用户操作(8)拖拽模式之draglayer和结束语

本文深入解析了Android Launcher8.0中拖拽模式的工作原理,从DragEvent的处理到PinItemDragListener的onDrag方法,详细阐述了ACTION_DRAG_STARTED到ACTION_DRAG_ENDED各个阶段的操作,包括handleMoveEvent在拖拽过程中的作用,以及如何触发dropTarget的相关事件。文章总结了点击、滑动、长按和拖拽四种用户操作,并分析了它们在Launcher中的不同响应逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在完整的讲解了拖拽流程之后,或许还有一个疑问:dragOver是被谁调用的?

点击进入click,然后处理完成,长按进入onlongclick处理完成,这两者都是view的接口。

那么,drag的过程中,需要一直读取手指的位置,这些操作自然也是view的接口View.OnDragListener。Launcher8.0有一个类叫做PinItemDragListener专门用来处理drag相关的操作。其中有个类ondrag,表示view进入了drag模式。

本方法最终返回 mDragController.onDragEven;
public boolean onDrag(View view, DragEvent event) {
    if (mLauncher == null || mDragController == null) {
        postCleanup();
        return false;
    }
    if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
        if (onDragStart(event)) {
            return true;
        } else {
            postCleanup();
            return false;
        }
    }
    return mDragController.onDragEvent(mDragStartTime, event);

}

而onDragEvent实际进入mDragDriver.onDragEvent

public boolean onDragEvent(long dragStartTime, DragEvent event) {
    mFlingToDeleteHelper.recordDragEvent(dragStartTime, event);
    return mDragDriver != null && mDragDriver.onDragEvent(event);
}

而这个dragDriver的OndragEvent则是详细的记录下每次的参数


public boolean onDragEvent (DragEvent event) {
    final int action = event.getAction();

    switch (action) {

//起始的手指位置
        case DragEvent.ACTION_DRAG_STARTED:
            mLastX = event.getX();
            mLastY = event.getY();
            return true;

        case DragEvent.ACTION_DRAG_ENTERED:
            return true;
//移动时的位置
        case DragEvent.ACTION_DRAG_LOCATION:
            mLastX = event.getX();
            mLastY = event.getY();
            mEventListener.onDriverDragMove(event.getX(), event.getY());
            return true;
//松手时的位置
        case DragEvent.ACTION_DROP:
            mLastX = event.getX();
            mLastY = event.getY();
            mEventListener.onDriverDragMove(event.getX(), event.getY());
            mEventListener.onDriverDragEnd(mLastX, mLastY);
            return true;
        case DragEvent.ACTION_DRAG_EXITED:
            mEventListener.onDriverDragExitWindow();
            return true;
        case DragEvent.ACTION_DRAG_ENDED:
            mEventListener.onDriverDragCancel();
            return true;
        default:
            return false;
    }
}

 

 

我们重点关注move的方法

public void onDriverDragMove(float x, float y) {
    final int[] dragLayerPos = getClampedDragLayerPos(x, y);
    handleMoveEvent(dragLayerPos[0], dragLayerPos[1]);
}

于是我们看到一个我们非常熟悉的方法,是startdrag流程,的必备方法handleMoveEvent、这个方法里面中途的 checkTouchMove(dropTarget)就是workspace、folder、button的dragEnter、dragOver、ondrop的调用方法。而结尾的callOnDragStart(),则是ondragstart和dragonend的调用方法。

 

private void handleMoveEvent(int x, int y) {
    mDragObject.dragView.move(x, y);

    final int[] coordinates = mCoordinatesTemp;
    DropTarget dropTarget = findDropTarget(x, y, coordinates);
    mDragObject.x = coordinates[0];
    mDragObject.y = coordinates[1];
    checkTouchMove(dropTarget);

    mDistanceSinceScroll += Math.hypot(mLastTouch[0] - x, mLastTouch[1] - y);
    mLastTouch[0] = x;
    mLastTouch[1] = y;

    if (mIsInPreDrag && mOptions.preDragCondition != null
            && mOptions.preDragCondition.shouldStartDrag(mDistanceSinceScroll)) {
        callOnDragStart();
    }
}

 

 

总结:用户能够进行的事件操作一共有4种,点击,滑动,长按,拖拽。

点击主要是识别点击的目标,然后进行对应的操作。

 

滑动是在GroupView才能进行的操作。

 

长按是onlongclick,分为

长按无效(例:在overView模式,点击两个页面之间的空白,还是保留在overView模式)

长按和点击一样(例:长按allapp入口按键)

长按切换模式(例:进入overviewmode)

长按到拖拽

 

拖拽大部分拖拽都进入workspace拖拽,onlongclick进入的拖拽首先调用handleMoveEvent。而后draglistener继续监听用户的操作继续调用handleMoveEvent保证拖拽的后续完成。

 

完成了启动流程和拖拽操作,最后还剩下的部分是通知部分,也就是当其他应用变化时,Launcher跟随的一些变化,这样一个完整的Launcher就完成了。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值