【问题标题】:PopupWindow doesn't respond to drag and drop eventsPopupWindow 不响应拖放事件
【发布时间】:2017-05-03 10:16:38
【问题描述】:

我的应用程序中有一个菜单图标。当我在上面拖放一些东西时,它会显示一个弹出窗口。我需要将我的拖放扩展到这个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,但也没有用。 任何帮助表示赞赏。

提前致谢。

【问题讨论】:

    标签: android drag-and-drop android-popupwindow


    【解决方案1】:

    PopupWindowadd the View on WindowManager instance,而不是当前布局。而in the docs 是指定的:

    系统向当前布局中的所有视图对象的拖动事件监听器发送一个动作类型为ACTION_DRAG_STARTED的拖动事件。

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

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


    实施

    ghost 视图添加到布局中:

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

    onCreate()设置幽灵视图

    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; } }); }

    我们确实希望 ghost view 可见,这就是我们将其 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 具有上述功能。

    【讨论】:

    • 感谢您的回复。我需要的和你提出的不同。我添加了一个 gif 来更好地定义它。再次感谢您的编辑。
    • 如果我理解正确,您拖的是Button,而不是PopupWindow。为什么您希望为PopupWindow 触发拖动回调?你没有拖着PopupWindow,对吧?
    • 是的,我没有拖动 PopupWindow... 我需要在 PopupWindow 中获取 dropevent。
    • 根据文档,developer.android.com/reference/android/view/…, android.view.View.DragShadowBuilder, java.lang.Object, int),它说“一旦系统有拖动阴影,它就开始拖放通过向应用程序中当前可见的所有 View 对象发送拖动事件来进行操作。”...这意味着它可以被拖放到拖动开始时可见的视图...
    • 只要在拖动按钮时出现DragEvent.ACTION_DRAG_ENDED,就执行contentView.dispatchDragEvent(dragEvent);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 2020-05-10
    • 1970-01-01
    • 2018-06-23
    相关资源
    最近更新 更多