【Android】 禁止首屏时钟AppWidget拖动到其他屏


活动地址:CSDN21天学习挑战赛

Android 10.0 Launcher3 禁止首屏时钟AppWidget拖动到其他屏:在日常开发中,屏幕第一屏默认会放一个时钟AppWidget,但是这个时钟可以被任意拖动到其他屏,这样拖动到其他屏显得很不好看,所以我们根据需求改成不能拖动时钟去其他屏,这就需要去分析拖拽整个流程。这也是禁止拖动的实现,相关实现还有播放在线音频时,需求是不能拖动进度条,让音频自然播放。以及英语听力考试时要求自然播放不得倒放等。

1、首先分析Workspace.java 看拖拽流程

packages/apps/Launcher3/src/com/android/launcher3/Workspace.java
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
if (TestProtocol.sDebugTracing) {
android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"onDragStart 1");
}
if (ENFORCE_DRAG_EVENT_ORDER) {
enforceDragParity("onDragStart", 0, 0);
}
    if (mDragInfo != null && mDragInfo.cell != null && mDragInfo.cell.getParent() != null) {
        CellLayout layout = (CellLayout) mDragInfo.cell.getParent().getParent();
        if (layout != null) layout.markCellsAsUnoccupiedForView(mDragInfo.cell);
    }

    if (mOutlineProvider != null) {
        if (dragObject.dragView != null) {
            Bitmap preview = dragObject.dragView.getPreviewBitmap();

            // The outline is used to visualize where the item will land if dropped
            mOutlineProvider.generateDragOutline(preview);
        }
    }

    updateChildrenLayersEnabled();

    // Do not add a new page if it is a accessible drag which was not started by the workspace.
    // We do not support accessibility drag from other sources and instead provide a direct
    // action for move/add to homescreen.
    // When a accessible drag is started by the folder, we only allow rearranging withing the
    // folder.
    boolean addNewPage = !(options.isAccessibleDrag && dragObject.dragSource != this);

    if (addNewPage) {
        mDeferRemoveExtraEmptyScreen = false;
        addExtraEmptyScreenOnDrag();

        if (dragObject.dragInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
                && dragObject.dragSource != this) {
            // When dragging a widget from different source, move to a page which has
            // enough space to place this widget (after rearranging/resizing). We special case
            // widgets as they cannot be placed inside a folder.
            // Start at the current page and search right (on LTR) until finding a page with
            // enough space. Since an empty screen is the furthest right, a page must be found.
            int currentPage = getPageNearestToCenterOfScreen();
            for (int pageIndex = currentPage; pageIndex < getPageCount(); pageIndex++) {
                CellLayout page = (CellLayout) getPageAt(pageIndex);
                if (page.hasReorderSolution(dragObject.dragInfo)) {
                    setCurrentPage(pageIndex);
                    break;
                }
            }
        }
    }

    // Always enter the spring loaded mode
    if (TestProtocol.sDebugTracing) {
        android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                "onDragStart 2");
    }
    mLauncher.getStateManager().goToState(SPRING_LOADED);
}

2、解析

onDragStart()处理的是开始拖拽的事件
onDrop()处理的是拖拽完成后的事件

public void onDrop(final DragObject d, DragOptions options) {
mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
CellLayout dropTargetLayout = mDropToLayout;
    // We want the point to be mapped to the dragTarget.
    if (dropTargetLayout != null) {
        mapPointFromDropLayout(dropTargetLayout, mDragViewVisualCenter);
    }

    boolean droppedOnOriginalCell = false;

    int snapScreen = -1;
    boolean resizeOnDrop = false;
    if (d.dragSource != this || mDragInfo == null) {
        final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
                (int) mDragViewVisualCenter[1] };
        onDropExternal(touchXY, dropTargetLayout, d);
    } else {
        AbstractFloatingView.closeOpenViews(mLauncher, false, AbstractFloatingView.TYPE_WIDGET_RESIZE_FRAME);
        final View cell = mDragInfo.cell;
        boolean droppedOnOriginalCellDuringTransition = false;
        Runnable onCompleteRunnable = null;

         //DragObject对象是对拖拽对象的封装 dragInfo是他的一些详细信息,而包名类名也是可以通过 providerName来获取的
        //只要获取到包名的相关信息 可以对包名进行判断就可以了 ,如果是这个包名就不会移动到其他屏,当拖动放开后会回到以前的位置
        // add code start
        ItemInfo iteminfo = d.dragInfo;
	String packagename = "";
	if(iteminfo!=null && iteminfo instanceof LauncherAppWidgetInfo){
		ComponentName componentName = ((LauncherAppWidgetInfo)iteminfo).providerName;
		if(componentName!=null){
			packagename = componentName.getPackageName();
		}
	}
        // add code end
      - if (dropTargetLayout != null && !d.cancelled ) {
      +  if (dropTargetLayout != null && !d.cancelled && !packagename.equals("com.android.deskclock")) {
            // Move internally
            boolean hasMovedLayouts = (getParentCellLayoutForView(cell) != dropTargetLayout);
            boolean hasMovedIntoHotseat = mLauncher.isHotseatLayout(dropTargetLayout);
            int container = hasMovedIntoHotseat ?
                    LauncherSettings.Favorites.CONTAINER_HOTSEAT :
                    LauncherSettings.Favorites.CONTAINER_DESKTOP;
            int screenId = (mTargetCell[0] < 0) ?
                    mDragInfo.screenId : getIdForScreen(dropTargetLayout);
            int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
            int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
            // First we find the cell nearest to point at which the item is
            // dropped, without any consideration to whether there is an item there.

            mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], (int)
                    mDragViewVisualCenter[1], spanX, spanY, dropTargetLayout, mTargetCell);
            float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],
                    mDragViewVisualCenter[1], mTargetCell);

            // If the item being dropped is a shortcut and the nearest drop
            // cell also contains a shortcut, then create a folder with the two shortcuts.
            if (createUserFolderIfNecessary(cell, container,
                    dropTargetLayout, mTargetCell, distance, false, d.dragView) ||
                    addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
                            distance, d, false)) {
                mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
                return;
            }

            // Aside from the special case where we're dropping a shortcut onto a shortcut,
            // we need to find the nearest cell location that is vacant
            ItemInfo item = d.dragInfo;
            int minSpanX = item.spanX;
            int minSpanY = item.spanY;
            if (item.minSpanX > 0 && item.minSpanY > 0) {
                minSpanX = item.minSpanX;
                minSpanY = item.minSpanY;
            }

            droppedOnOriginalCell = item.screenId == screenId && item.container == container
                    && item.cellX == mTargetCell[0] && item.cellY == mTargetCell[1];
            droppedOnOriginalCellDuringTransition = droppedOnOriginalCell && mIsSwitchingState;

            // When quickly moving an item, a user may accidentally rearrange their
            // workspace. So instead we move the icon back safely to its original position.
            boolean returnToOriginalCellToPreventShuffling = !isFinishedSwitchingState()
                    && !droppedOnOriginalCellDuringTransition && !dropTargetLayout
                    .isRegionVacant(mTargetCell[0], mTargetCell[1], spanX, spanY);
            int[] resultSpan = new int[2];
            if (returnToOriginalCellToPreventShuffling) {
                mTargetCell[0] = mTargetCell[1] = -1;
            } else {
                mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0],
                        (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, cell,
                        mTargetCell, resultSpan, CellLayout.MODE_ON_DROP);
            }

            boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;

            // if the widget resizes on drop
            if (foundCell && (cell instanceof AppWidgetHostView) &&
                    (resultSpan[0] != item.spanX || resultSpan[1] != item.spanY)) {
                resizeOnDrop = true;
                item.spanX = resultSpan[0];
                item.spanY = resultSpan[1];
                AppWidgetHostView awhv = (AppWidgetHostView) cell;
                AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0],
                        resultSpan[1]);
            }

            if (foundCell) {
                if (getScreenIdForPageIndex(mCurrentPage) != screenId && !hasMovedIntoHotseat) {
                    snapScreen = getPageIndexForScreenId(screenId);
                    snapToPage(snapScreen);
                }

                final ItemInfo info = (ItemInfo) cell.getTag();
                if (hasMovedLayouts) {
                    // Reparent the view
                    CellLayout parentCell = getParentCellLayoutForView(cell);
                    if (parentCell != null) {
                        parentCell.removeView(cell);
                    } else if (FeatureFlags.IS_DOGFOOD_BUILD) {
                        throw new NullPointerException("mDragInfo.cell has null parent");
                    }
                    addInScreen(cell, container, screenId, mTargetCell[0], mTargetCell[1],
                            info.spanX, info.spanY);
                }

                // update the item's position after drop
                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
                lp.cellX = lp.tmpCellX = mTargetCell[0];
                lp.cellY = lp.tmpCellY = mTargetCell[1];
                lp.cellHSpan = item.spanX;
                lp.cellVSpan = item.spanY;
                lp.isLockedToGrid = true;

                if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
                        cell instanceof LauncherAppWidgetHostView) {
                    final CellLayout cellLayout = dropTargetLayout;
                    // We post this call so that the widget has a chance to be placed
                    // in its final location

                    final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
                    AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
                    if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE
                            && !d.accessibleDrag) {
                        onCompleteRunnable = new Runnable() {
                            public void run() {
                                if (!isPageInTransition()) {
                                    AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
                                }
                            }
                        };
                    }
                }

                mLauncher.getModelWriter().modifyItemInDatabase(info, container, screenId,
                        lp.cellX, lp.cellY, item.spanX, item.spanY);
            } else {
                if (!returnToOriginalCellToPreventShuffling) {
                    onNoCellFound(dropTargetLayout);
                }

                // If we can't find a drop location, we return the item to its original position
                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
                mTargetCell[0] = lp.cellX;
                mTargetCell[1] = lp.cellY;
                if (cell.getParent() != null) {
                    CellLayout layout = (CellLayout) cell.getParent().getParent();
                    layout.markCellsAsOccupiedForView(cell);
                }
            }
        }

        final CellLayout parent =
                cell.getParent() == null ? null : (CellLayout) cell.getParent().getParent();
        if (d.dragView.hasDrawn()) {
            if (droppedOnOriginalCellDuringTransition) {
                // Animate the item to its original position, while simultaneously exiting
                // spring-loaded mode so the page meets the icon where it was picked up.
                if (cell.getParent() != null) {
                    mLauncher.getDragController().animateDragViewToOriginalPosition(
                            onCompleteRunnable, cell, SPRING_LOADED_TRANSITION_MS);
                } else {
                    resetDragCellIfNeed(mDragInfo);
                }
                mLauncher.getStateManager().goToState(NORMAL);
                mLauncher.getDropTargetBar().onDragEnd();
                if (parent != null) {
                    parent.onDropChild(cell);
                }
                return;
            }
            final ItemInfo info = (ItemInfo) cell.getTag();
            boolean isWidget = info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
                    || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
            if (isWidget) {
                int animationType = resizeOnDrop ? ANIMATE_INTO_POSITION_AND_RESIZE :
                        ANIMATE_INTO_POSITION_AND_DISAPPEAR;
                if (parent != null) {
                    animateWidgetDrop(info, parent, d.dragView, null, animationType, cell, false);
                }
            } else {
                int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;
                if (cell.getParent() != null) {
                    mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
                            this);
                } else {
                    d.deferDragViewCleanupPostAnimation = false;
                    resetDragCellIfNeed(mDragInfo);
                }
            }
        } else {
            d.deferDragViewCleanupPostAnimation = false;
            if (cell.getParent() != null) {
                cell.setVisibility(VISIBLE);
            } else {
                resetDragCellIfNeed(mDragInfo);
            }
        }
        if (parent != null) {
            parent.onDropChild(cell);
        }

        mLauncher.getStateManager().goToState(
                NORMAL, SPRING_LOADED_EXIT_DELAY, onCompleteRunnable);
    }

    if (d.stateAnnouncer != null && !droppedOnOriginalCell) {
        d.stateAnnouncer.completeAction(R.string.item_moved);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值