android 8.1 Launcher3 横屏状态长按图标 弹框位置居中分析

问题:MTK android 8.1 Launcher3 横屏状态长按图标 弹框位置居中分析.

现象:竖屏状态下正常,横屏状态下,长按最右边的apk图标弹出的信息框会显示在屏幕中间的位置.

期望:参考竖屏,应该显示在apk上方或者下方,方向偏向左边.

问题如图:android 8.1 Launcher3 横屏状态长按图标 弹框位置居中分析_第1张图片

分析:

1.从Launcher3长按开始分析.

Luancher.java

 @Override
    public boolean onLongClick(View v) {
        if (!isDraggingEnabled()) return false;
        if (isWorkspaceLocked()) return false;
        if (mState != State.WORKSPACE) return false;

        boolean ignoreLongPressToOverview =
                mDeviceProfile.shouldIgnoreLongPressToOverview(mLastDispatchTouchEventX);

        if (v instanceof Workspace) {
            if (!mWorkspace.isInOverviewMode()) {
                if (!mWorkspace.isTouchActive() && !ignoreLongPressToOverview) {
                    getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
                            Action.Direction.NONE, ContainerType.WORKSPACE,
                            mWorkspace.getCurrentPage());
                    showOverviewMode(true);
                    mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                            HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }

        CellLayout.CellInfo longClickCellInfo = null;
        View itemUnderLongClick = null;
        if (v.getTag() instanceof ItemInfo) {
            ItemInfo info = (ItemInfo) v.getTag();
            longClickCellInfo = new CellLayout.CellInfo(v, info);
            itemUnderLongClick = longClickCellInfo.cell;
            mPendingRequestArgs = null;
        }

        // The hotseat touch handling does not go through Workspace, and we always allow long press
        // on hotseat items.
        if (!mDragController.isDragging()) {
            if (itemUnderLongClick == null) {
                // User long pressed on empty space
                if (mWorkspace.isInOverviewMode()) {
                    mWorkspace.startReordering(v);
                    getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
                            Action.Direction.NONE, ContainerType.OVERVIEW);
                } else {
                    if (ignoreLongPressToOverview) {
                        return false;
                    }
                    getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
                            Action.Direction.NONE, ContainerType.WORKSPACE,
                            mWorkspace.getCurrentPage());
                    showOverviewMode(true);
                }
                mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                        HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
            } else {
                final boolean isAllAppsButton =
                        !FeatureFlags.NO_ALL_APPS_ICON && isHotseatLayout(v) &&
                                mDeviceProfile.inv.isAllAppsButtonRank(mHotseat.getOrderInHotseat(
                                        longClickCellInfo.cellX, longClickCellInfo.cellY));
                if (!(itemUnderLongClick instanceof Folder || isAllAppsButton)) {
                    // User long pressed on an item
                    mWorkspace.startDrag(longClickCellInfo, new DragOptions());
                }
            }
        }
        return true;
    }

经过打Log,确认跑了这个代码  mWorkspace.startDrag(longClickCellInfo, new DragOptions());

startDrag()-->beginDragShared()

   if (child instanceof BubbleTextView && !dragOptions.isAccessibleDrag) {
            PopupContainerWithArrow popupContainer = PopupContainerWithArrow
                    .showForIcon((BubbleTextView) child);
            if (popupContainer != null) {
                dragOptions.preDragCondition = popupContainer.createPreDragCondition();

                mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
            }
        }

调用了PopupContainerWithArrow.java的showForIcon().

showForIcon()-->populateAndShow().

populateAndShow()中有两个方法orientAboutIcon()和addArrowView()相关.

 private void orientAboutIcon(BubbleTextView icon, int arrowHeight) {
        int width = getMeasuredWidth();
        int height = getMeasuredHeight() + arrowHeight;

        DragLayer dragLayer = mLauncher.getDragLayer();
        dragLayer.getDescendantRectRelativeToSelf(icon, mTempRect);
        Rect insets = dragLayer.getInsets();

        // Align left (right in RTL) if there is room.
        int leftAlignedX = mTempRect.left + icon.getPaddingLeft();
        int rightAlignedX = mTempRect.right - width - icon.getPaddingRight();
        int x = leftAlignedX;
        boolean canBeLeftAligned = leftAlignedX + width + insets.left
                < dragLayer.getRight() - insets.right;
        boolean canBeRightAligned = rightAlignedX > dragLayer.getLeft() + insets.left;
        if (!canBeLeftAligned || (mIsRtl && canBeRightAligned)) {
            x = rightAlignedX;
        }
        mIsLeftAligned = x == leftAlignedX;
        if (mIsRtl) {
            x -= dragLayer.getWidth() - width;
        }

        // Offset x so that the arrow and shortcut icons are center-aligned with the original icon.
        int iconWidth = icon.getWidth() - icon.getTotalPaddingLeft() - icon.getTotalPaddingRight();
        iconWidth *= icon.getScaleX();
        Resources resources = getResources();
        int xOffset;
        if (isAlignedWithStart()) {
            // Aligning with the shortcut icon.
            int shortcutIconWidth = resources.getDimensionPixelSize(R.dimen.deep_shortcut_icon_size);
            int shortcutPaddingStart = resources.getDimensionPixelSize(
                    R.dimen.popup_padding_start);
            xOffset = iconWidth / 2 - shortcutIconWidth / 2 - shortcutPaddingStart;
        } else {
            // Aligning with the drag handle.
            int shortcutDragHandleWidth = resources.getDimensionPixelSize(
                    R.dimen.deep_shortcut_drag_handle_size);
            int shortcutPaddingEnd = resources.getDimensionPixelSize(
                    R.dimen.popup_padding_end);
            xOffset = iconWidth / 2 - shortcutDragHandleWidth / 2 - shortcutPaddingEnd;
        }
        x += mIsLeftAligned ? xOffset : -xOffset;


        // Open above icon if there is room.
        int iconHeight = icon.getIcon() != null
                ? icon.getIcon().getBounds().height()
                : icon.getHeight();
        int y = mTempRect.top + icon.getPaddingTop() - height;
        mIsAboveIcon = y > dragLayer.getTop() + insets.top;
        if (!mIsAboveIcon) {
            y = mTempRect.top + icon.getPaddingTop() + iconHeight;
        }

        // Insets are added later, so subtract them now.
        if (mIsRtl) {
            x += insets.right;
        } else {
            x -= insets.left;
        }
        y -= insets.top;

        mGravity = 0;
        if (y + height > dragLayer.getBottom() - insets.bottom) {
            // The container is opening off the screen, so just center it in the drag layer instead.
            mGravity = Gravity.CENTER_VERTICAL;
            // Put the container next to the icon, preferring the right side in ltr (left in rtl).
            int rightSide = leftAlignedX + iconWidth - insets.left;
            int leftSide = rightAlignedX - iconWidth - insets.left;
            if (!mIsRtl) {
                if (rightSide + width < dragLayer.getRight()) {
                    x = rightSide;
                    mIsLeftAligned = true;
                } else {
                    x = leftSide;
                    mIsLeftAligned = false;
                }
            } else {
                if (leftSide > dragLayer.getLeft()) {
                    x = leftSide;
                    mIsLeftAligned = false;
                } else {
                    x = rightSide;
                    mIsLeftAligned = true;
                }
            }
            mIsAboveIcon = true;
        }

        setX(x);
        setY(y);
    }

在orientAboutIcon()经过一些方法的计算,最终确认setX(x)和setY(y).打印这两个值,未发现异常.均是长按图标的位置.

但是实际效果却是x,y的值不对.即显示位置不对,那么应该用其他地方重新设置了位置坐标x,y.经过搜索setX和setY.

PopupContainerWithArrow.java中,有enforceContainedWithinScreen()方法,很明显是这里修改了x,y的值.

    private void enforceContainedWithinScreen(int left, int right) {
        DragLayer dragLayer = mLauncher.getDragLayer();
        if (getTranslationX() + left < 0 ||
                getTranslationX() + right > dragLayer.getWidth()) {
            // If we are still off screen, center horizontally too.
            mGravity |= Gravity.CENTER_HORIZONTAL;
        }

        if (Gravity.isHorizontal(mGravity)) {
            setX(dragLayer.getWidth() / 2 - getMeasuredWidth() / 2);
        }
        if (Gravity.isVertical(mGravity)) {
            setY(dragLayer.getHeight() / 2 - getMeasuredHeight() / 2);
        }
    }

经过打印Log:getTranslationX() + right>dragLayer.getWidth().

屏蔽enforceContainedWithinScreen()的setX(dragLayer.getWidth() / 2 - getMeasuredWidth() / 2);

长按位置正确,但是方向不对.且屏蔽的改法是有风险的,当显示的信息框超出屏幕显示位置的时候,有部分不显示.这个跟屏幕的分辨率,Launcher桌面布局有关,所以不能在这里修改.

那么在这个判断之前,应该做的是让信息框整体不超过屏幕分辨率,如同竖屏那样.在apk图标的左边.

那么修改的地方应在populateAndShow()的两个方法orientAboutIcon()和addArrowView().

查看orientAboutIcon()方法,mIsLeftAligned这个变量经过翻译是:左对齐.

打印Log,显示横屏状态下,这个值一直为true.而在竖屏时,长按最右边的apk按钮是false,其他为true.

分析上面的判断,根据弹出框的大小,位置,显示屏的大小判断的.

原有的代码逻辑没有变动,我在这里增加了一个判断.

         }
         x += mIsLeftAligned ? xOffset : -xOffset;
 
+       //Add Begin :Modify the long click icon to display the    
+       //information position.
+       int shortcutItemWidth =    
+           resources.getDimensionPixelSize(R.dimen.bg_popup_item_width);
+       if( x +  shortcutItemWidth > dragLayer.getWidth()){
+           mIsLeftAligned = false;
+       x = x - shortcutItemWidth + xOffset;
+       }
+       //Add End
+
         // Open above icon if there is room.
         int iconHeight = icon.getIcon() != null
                 ? icon.getIcon().getBounds().height()

 这个判断为:x +  shortcutItemWidth > dragLayer.getWidth().点击apk的位置的x值加上弹出框的宽度大于屏幕显示宽度时:

左对齐mIsLeftAligned为false,即为右对齐.同时需要重新调整x的位置.x = x - shortcutItemWidth + xOffset;

经过测试,问题解决.

如有更好的修改方法,欢迎交流.

 

 

 

 

 

 

你可能感兴趣的:(android,java)