我一直在为安卓打造类似于Nova Launcher的启动器应用程序。我已经设置好了OnItemLongClickListener和OnDragListener。当我长按图标时,会显示一个弹出菜单,如“删除”,“更改图标”等。下面的图片展示了弹出菜单打开时的应用程序进展情况。
问题是,当弹出菜单打开时,拖动可以工作,但是放下却无法工作。似乎一旦弹出菜单打开,我就不能记录x、y位置。而且当执行放下操作时,在logcat中会显示以下消息。
![enter image description here](https://istack.dev59.com/gdyHb.webp)
I/ViewRootImpl: Reporting drop result: false
我在OnDragListener中的代码大致如下:
public boolean onDrag(View v, DragEvent event) {
int dragEvent = event.getAction();
switch (dragEvent)
{
case DragEvent.ACTION_DRAG_LOCATION:
//Open popup here; note: its opened only once. popup.show();
//Log.i("Position x : ", Float.toString(event.getX())); log x or y
/*code to detect x any y change amount and close the popup
once user drags the icon little further and app knows that
user is trying to drag instead of opening the popup
and hence close the popup. popup.dismiss();
*/
// other case like ACTION_DROP etx goes after this
}
}
但是似乎在弹出窗口打开后,我无法记录x或y的值;并且确定行为是“拖动”还是“弹出窗口打开”的代码也无法运行。
那么我该如何解决这个问题呢?我想在任何情况下,只要拖动量足够大,就关闭弹出窗口,以此判断用户想要拖动。如果不够大,则停止拖动并仅显示弹出窗口。
编辑
我通过同时使用OnTouchListener和OnDragListener解决了弹出窗口的问题。以下是我的OnDragListener代码。
//bottomAppDrawer is a GridView
bottomAppDrawer.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
int dragEvent = event.getAction();
LinearLayout draggedItem = (LinearLayout) event.getLocalState(); //dragged LinearLayout
GridView targetItem = (GridView) v; /* How do i get this drop target as LinearLayout so that i can delete or swap data */
switch (dragEvent)
{
case DragEvent.ACTION_DRAG_LOCATION:
if(reset==false) {
dragPositionStart = event.getX();
reset= true;
}
if(Math.abs(dragPositionStart - event.getX())>=20) {
Log.i("Position close : ", Float.toString(dragPositionStart));
if(isPopupOpen) {
popupMenu.dismiss();
v.startDrag(data, dragShadow, itemView, 0);
Toast.makeText(mContext, "popup closed", Toast.LENGTH_SHORT).show();
isPopupOpen = false;
}
reset = false;
}
break;
case DragEvent.ACTION_DROP:
Toast.makeText(mContext, "drop" + Integer.toString(targetItem.getChildCount()), Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
现在的问题是,当我将LinearLayout放入“Gridview”中时,我得到的放置目标是“Gridview”。而这个“LinearLayout”是“Gridview”的子元素。我希望放置目标是同一“GridView”内的另一个“LinearLayout”,这样我就可以交换数据或重新排序。如下图所示。