Ненавязчивое всплывающее окно, которое не блокирует перетаскивание n в Android

Я работаю над приложением запуска для андроида, похожего на nova launcher. У меня есть настройка OnItemLongClickListener и OnDragListener. Когда я долго нажимаю на значок, появляется всплывающее меню с меню, например «Удалить», «Изменить значок» и т. Д. На следующем рисунке показано, как работает приложение с всплывающим окном, а также длительным нажатием.

Введите описание изображения здесь

Проблема заключается в том, что всплывающее окно открывается, но перетаскивание не работает. Кажется, что я не могу зарегистрировать позицию x, y, когда всплывающее окно открыто. Также при выполнении кавычек в logcat отображается следующее сообщение.

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; Также не может быть запущен код, определяющий, было ли действие предназначено для «перетаскивания» или «всплывающего окна».

Итак, как я могу решить эту проблему? Я хочу закрыть всплывающее окно, как только сумма перетаскивания в любом случае будет достаточной, чтобы знать, что пользователь хочет перетащить. И если не остановить перетаскивание и отобразить всплывающее окно.

редактировать

Я решил проблему с помощью всплывающего окна, используя как OnTouchListner, так и OnDragListner. Следующий показывает мой код для OnDragListner.

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

Теперь проблема в том, что я получаю целевой объект «Gridview», поскольку я бросаю LinearLayout в «Gridview». Кроме того, этот «LinearLayout» является дочерним элементом «Gridview». И я хочу, чтобы цель кавычки была другой «LinearLayout» внутри одного и того же «GridView», чтобы я мог менять данные или переупорядочивать. Как показано на рисунке ниже.

Введите описание изображения здесь

    Из того, что я понимаю, есть две вещи, которые вы хотите сделать. 1) Измените порядок просмотров после перетаскивания. И 2) Измените типы Вид после изменения порядка.

    Для проблемы 1, поскольку это сетка, это похоже на то, что мы действительно просто хотим изменить порядок данных в адаптере и, возможно, изменить данные, чтобы они отображались по-разному. Но нам нужно выяснить положение исходного пункта и целевой позиции назначения.

    Мы можем расширить GridView, чтобы сделать это:

     public class DragAndDropGridView extends GridView { public void handleMove(int x, int y, int originalPosition) { Rect rect = new Rect(); PushbackAdapter adapter = (PushbackAdapter) getAdapter(); for (int visiblePosition = getFirstVisiblePosition(); visiblePosition <= getLastVisiblePosition(); visiblePosition++) { // TODO verify that there are no edge cases not covered by this View view = getChildAt(visiblePosition); int left = view.getLeft(); int top = view.getTop(); getChildVisibleRect(view, rect, null); rect.offsetTo(left, top); if (rect.contains(x, y)) { // yay the user tried drop the view at this location // determine if they wanted to drop it here or after this side int centerX = rect.centerX(); if (x <= centerX) { // we want to drop it here adapter.move(originalPosition, visiblePosition); adapter.notifyDataSetInvalidated(); break; } else { // we want to drop it behind adapter.move(originalPosition, visiblePosition + 1); adapter.notifyDataSetInvalidated(); break; } } } } } 

    Это оставляет нам вызов handleMoveMethod. Мы делаем это из метода ACTION_DROP.

      case DragEvent.ACTION_DROP: handleMove((int)event.getX(), (int)event.getY(), getPositionForView(draggedItem)); Toast.makeText(mContext, "drop" + Integer.toString(targetItem.getChildCount()), Toast.LENGTH_SHORT).show(); break; 

    Наконец (проблема 2) кажется, что вы можете изменить либо содержимое объекта в позиции, либо тип вида, в котором он содержится. Я бы предложил использовать методы getItemViewType и getItemViewTypeCount, если вам нужно иметь разные типы Просмотры. Например, что-то вроде следующих:

      private static class PushbackAdapter extends ArrayAdapter { ArrayList<Object> mItems; public void move(int originalPosition, int targetPosition){ // TODO verify that this move logic is correct Object item = mItems.remove(originalPosition); item.useLinearLayoutType(true); mItems.add(targetPosition, item); } ... @Override public int getItemViewType(int i) { return mItems.get(i).isLeanearLayoutType()? 1 : 0; } 

    Там могут быть ошибки, поэтому, пожалуйста, тщательно протестируйте

    Найдите позицию LinerLayout (которая перетаскивается) в Gridview, используя targetItem.pointToPosition(..) .

    Проведите LinerLayout, используя следующий код:

     int i =targetItem.pointToPosition((int)event.getX(), (int)event.getY()); int j = Integer.parseInt(event.getClipData().getItemAt(0).getText().toString()); Collections.swap(targetItem, i, j);//swap Linerlayout Log.i(TAG, "Swapped " + i+ " with " + j); 

    Код не проверен. Надеюсь, это поможет вам. 🙂

    Intereting Posts
    Как показать доступные файлы в Android-памяти с помощью Firemonkey Тестирование JVM-модуля с помощью Mockito для тестирования Retrofit2 и RxJava для сетевых запросов Android / Java редкое и, казалось бы, невозможное исключение, вызывающее силу закрытия Удаление выбранных частей Android SDK в командной строке Стрелка влево на указателе мыши на панели инструментов Android – как передать данные в Runnable в runOnUiThread? Как создать папку в sdcard в android Живые обои с аппаратным ускорением Как настроить пользовательский загрузчик в Universal Image Loader? Будут ли бинарные файлы, созданные для ARM, работать на процессорах Intel? Веселая активность активности Android при отключении экрана? Как окрасить различные части текста, нарисованные на холсте в Android? Как сделать вид невидимым / Gone onBackPressed () в android Каковы последствия не исправления проблемы «Класс, не найденный при разборке»? И почему это не влияет на приложение? Как записывать видео прямо на Helix Server с моего устройства Android?