PopupWindow 不响应拖放事件

PopupWindow doesn't respond to drag and drop events

我的应用程序中有一个菜单图标。当我在上面拖放某些东西时,它会显示一个弹出窗口。我需要将拖放扩展到此 PopupWindow.

我正在这样做。

如图所示创建了一个 PopupWindow

View popupView = View.inflate(anchorView.getContext(), R.layout.layout_popup, null);

PopupWindow popUpWindow = new PopupWindow(popupView, WindowManager.LayoutParams.WRAP_CONTENT,
                                                  WindowManager.LayoutParams.WRAP_CONTENT);

并如图所示设置 dragListener

popupView.setOnDragListener(new OnDragListener() {
            @Override
            public boolean onDrag(View view, DragEvent dragEvent) {



                    switch (dragEvent.getAction()) {
                    case DragEvent.ACTION_DRAG_STARTED:
                        Log.d("Drag", "ACTION_DRAG_STARTED");
                        break;
                    case DragEvent.ACTION_DRAG_ENDED:
                        Log.d("Drag", "ACTION_DRAG_ENDED");
                        break;
                    case DragEvent.ACTION_DRAG_ENTERED:
                        Log.d("Drag", "ACTION_DRAG_ENTERED");
                        break;
                    case DragEvent.ACTION_DRAG_EXITED:
                        Log.d("Drag", "ACTION_DRAG_EXITED");
                        break;
                    case DragEvent.ACTION_DROP:
                        Log.d("Drag", "ACTION_DROP");
                        break;
                    default:
                        break;
                    }

                return true;
            }
        });

下面的视频显示了我想要实现的目标。

但是 popupView 没有响应任何拖动事件。我也尝试使用 DialogFragment,但它也没有帮助。 感谢任何帮助。

提前致谢。

PopupWindowadd the View on WindowManager instance, and not to the current layout. Whereas in the docs指定为:

The system sends a drag event with action type ACTION_DRAG_STARTED to the drag event listeners for all the View objects in the current layout.

注意加粗的“在当前布局”。 PopupWindow 的内容视图不被视为在当前布局中,这就是为什么这些事件不会分派到 PopupWindow 的内容视图。

作为解决方法,您可以将具有相同坐标的 View 添加到当前布局,这将充当 PopupWindow 的幽灵,并监听此 View 的拖动事件.


实施

ghost 视图 添加到布局中:

<include android:id="@+id/ghost"
         layout="@layout/layout_popup"/>

onCreate():

设置 ghost 视图


    private void setupGhostView() {
        ghost = findViewById(R.id.ghost);
        ghost.setAlpha(0.0f);
        ghost.findViewById(R.id.txt_append).setOnDragListener(new OnDragListener() {
            @Override
            public boolean onDrag(View v, DragEvent event) {
                if (event.getAction() == DragEvent.ACTION_DROP) {
                    Toast.makeText(MainActivity.this, "Settings 1", Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        });
        ghost.findViewById(R.id.txt_replace).setOnDragListener(new OnDragListener() {
            @Override
            public boolean onDrag(View v, DragEvent event) {
                if (event.getAction() == DragEvent.ACTION_DROP) {
                    Toast.makeText(MainActivity.this, "Settings 2", Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        });
    }


我们希望幻影视图可见,这就是我们将它的 alpha 设置为零的原因。

然后我们设置 PopupWindow 具有锚点视图:



    private void preparePopup(View anchorView) {
        final View popupView = View.inflate(anchorView.getContext(), R.layout.layout_popup, null);
        popupView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

        popupWindow = new PopupWindow(popupView, WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT);
        popupWindow.setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
        popupWindow.setTouchable(false);

        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                popupView.getMeasuredWidth(), popupView.getMeasuredHeight());
        params.gravity = Gravity.END;
        ghost.setLayoutParams(params);
        ghost.invalidate();
        ghost.requestLayout();
    }


我们需要执行setTouchable(false),否则PopupWindow会消耗触摸事件。此外,我们将 ghost view 的位置设置在 PopupWindow 将显示的位置。

然后我们在适当的拖动事件中显示和关闭 PopupWindow



    menuView.setOnDragListener(new OnDragListener() {
        @Override
        public boolean onDrag(View v, DragEvent event) {
            int dragEvent = event.getAction();
            switch (dragEvent) {

                case DragEvent.ACTION_DRAG_ENTERED:
                    popupWindow.showAsDropDown(anchorView);
                    break;

                case DragEvent.ACTION_DRAG_ENDED:
                    popupWindow.dismiss();
                    break;
            }

            return true;
        }
    }); 


结果

您的仓库中的拉取请求 is opened 具有上述功能。