Ayuda con los problemas de ListView de la interfaz de usuario de Android

Para entender esta pregunta, primero lea cómo funciona este método.

Estoy tratando de implementar un arrastrar y soltar ListView , va bien, pero se han ejecutado en un bloque de carretera. Así que no tengo que manejar todo, estoy interceptando (pero devolviendo false) MotionEvents enviado a ListView, dejándolo manejar desplazamiento y cosas. Cuando deseo comenzar a arrastrar un artículo, entonces vuelvo verdadero y manejé todas las cosas que arrastran. Todo está funcionando bien excepto por una cosa. La arrastrar (arrastrar y soltar) se inicia cuando se determina que se ha producido una pulsación larga como en (en onInterceptTouchEvent). Consigo el mapa de bits para la imagen que arrastrar alrededor como así. ItemPositition es el índice del elemento que fue seleccionado.

(Omitiendo partes irrelevantes)

... View dragItem = mListView.getChildAt(itemPosition); dragItem.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(dragItem.getDrawingCache()); mDragImage = new ImageView(mContext); mDragImage.setImageBitmap(bitmap); ... 

El problema es que mDragImage es un negro sólido como este. Un mapa de bits posterior sólido

Pero, si no dejo que ListView maneje nada. Como en, comienzo el arrastrar en ACTION_DOWN y paro en ACTION_UP , miradas de mDragImage ha esperado (pero obviamente pierdo capacidades de desplazamiento).

Un buen mapa de bits

Puesto que el arrastre se inicia con una pulsación larga, el ListView se da la oportunidad de hacer las cosas antes de la prensa larga. Esta es mi suposición de por qué esto está sucediendo. Cuando se presiona un elemento, se resalta mediante el ListView. En algún lugar de hacerlo, se está jugando con el mapa de bits. Así que cuando voy a conseguirlo, está en un estado extraño (todo negro).

Veo dos opciones para arreglar esto, ninguno de los cuales sé cómo hacer.

  1. Cree una imagen desde cero.

  2. Manejo el resaltado yo mismo (si ese es el problema).

La opción dos me parece mejor, excepto que miré la documentación y el código fuente y no pude averiguar cómo hacerlo. Aquí hay algunas cosas que he hecho / probado.

  • Defino setOnItemClickListener (…) y setOnItemSelectedListener (…) con un método vacío (resaltando todavía sucede). (Antes de que nadie lo sugiera, llamar a setOnClickListener da como resultado un error de ejecución.)

  • También miré en intentar conseguir el ListView para hacer un nuevo artículo (para la opción 2), pero no podría encontrar una manera.

  • Pasé 45 minutos minutos mirando a través del código fuente y la documentación tratando de identificar dónde estaba ocurriendo el resaltado (nunca lo encontré).

Cualquier ayuda que solucione esto sería apreciada.

(EDIT1 START)

Así que en realidad no sé si onLongClickListener está funcionando, he cometido un error antes de pensarlo. Estoy tratando de configurarlo ahora mismo, se actualizará cuando descubra si lo hace.

(EDIT1 END)

Última hora editar antes de publicar. Intenté usar onLongClickListener justo ahora, y la imagen es buena. Todavía me gustaría saber si hay otra manera. Cómo tengo que usar onLongClickListener para que las cosas funcionen es feo, pero funciona. También pasé mucho tiempo tratando de resolver esto, sería bueno para encontrar la respuesta. Todavía quiero ser capaz de cambiar / manejar el color de resaltado, el color naranja predeterminado no es bonito. Oh, y lo siento por la longitud de la entrada. No podía pensar en la forma de hacerlo más corto, mientras que el suministro de toda la información que yo pensaba que era necesario.

Utilizar este código, que permite la operación de drogas y la gota en ListView:

 public class DraggableListView extends ListView { private static final String LOG_TAG = "tasks365"; private static final int END_OF_LIST_POSITION = -2; private DropListener mDropListener; private int draggingItemHoverPosition; private int dragStartPosition; // where was the dragged item originally private int mUpperBound; // scroll the view when dragging point is moving out of this bound private int mLowerBound; // scroll the view when dragging point is moving out of this bound private int touchSlop; private Dragging dragging; private GestureDetector longPressDetector; public DraggableListView(Context context, AttributeSet attrs) { this(context, attrs, android.R.attr.listViewStyle); } public DraggableListView(final Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); longPressDetector = new GestureDetector(getContext(), new SimpleOnGestureListener() { @Override public void onLongPress(final MotionEvent e) { int x = (int) e.getX(); final int y = (int) e.getY(); int itemnum = pointToPosition(x, y); if (itemnum == AdapterView.INVALID_POSITION) { return; } if (dragging != null) { dragging.stop(); dragging = null; } final View item = getChildAt(itemnum - getFirstVisiblePosition()); item.setPressed(false); dragging = new Dragging(getContext()); dragging.start(y, ((int) e.getRawY()) - y, item); draggingItemHoverPosition = itemnum; dragStartPosition = draggingItemHoverPosition; int height = getHeight(); mUpperBound = Math.min(y - touchSlop, height / 3); mLowerBound = Math.max(y + touchSlop, height * 2 / 3); } }); setOnItemLongClickListener(new OnItemLongClickListener() { @SuppressWarnings("unused") public boolean onItemLongClick(AdapterView<?> paramAdapterView, View paramView, int paramInt, long paramLong) { // Return true to let AbsListView reset touch mode // Without this handler, the pressed item will keep highlight. return true; } }); } /* pointToPosition() doesn't consider invisible views, but we need to, so implement a slightly different version. */ private int myPointToPosition(int x, int y) { if (y < 0) { return getFirstVisiblePosition(); } Rect frame = new Rect(); final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); child.getHitRect(frame); if (frame.contains(x, y)) { return getFirstVisiblePosition() + i; } } if ((x >= frame.left) && (x < frame.right) && (y >= frame.bottom)) { return END_OF_LIST_POSITION; } return INVALID_POSITION; } @Override public boolean onTouchEvent(MotionEvent ev) { if (longPressDetector.onTouchEvent(ev)) { return true; } if ((dragging == null) || (mDropListener == null)) { // it is not dragging, or there is no drop listener return super.onTouchEvent(ev); } int action = ev.getAction(); switch (ev.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: dragging.stop(); dragging = null; if (mDropListener != null) { if (draggingItemHoverPosition == END_OF_LIST_POSITION) { mDropListener.drop(dragStartPosition, getCount() - 1); } else if (draggingItemHoverPosition != INVALID_POSITION) { mDropListener.drop(dragStartPosition, draggingItemHoverPosition); } } resetViews(); break; case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: int x = (int) ev.getX(); int y = (int) ev.getY(); dragging.drag(x, y); int position = dragging.calculateHoverPosition(); if (position != INVALID_POSITION) { if ((action == MotionEvent.ACTION_DOWN) || (position != draggingItemHoverPosition)) { draggingItemHoverPosition = position; doExpansion(); } scrollList(y); } break; } return true; } private void doExpansion() { int expanItemViewIndex = draggingItemHoverPosition - getFirstVisiblePosition(); if (draggingItemHoverPosition >= dragStartPosition) { expanItemViewIndex++; } // Log.v(LOG_TAG, "Dragging item hovers over position " + draggingItemHoverPosition + ", expand item at index " // + expanItemViewIndex); View draggingItemOriginalView = getChildAt(dragStartPosition - getFirstVisiblePosition()); for (int i = 0;; i++) { View itemView = getChildAt(i); if (itemView == null) { break; } ViewGroup.LayoutParams params = itemView.getLayoutParams(); int height = LayoutParams.WRAP_CONTENT; if (itemView.equals(draggingItemOriginalView)) { height = 1; } else if (i == expanItemViewIndex) { height = itemView.getHeight() + dragging.getDraggingItemHeight(); } params.height = height; itemView.setLayoutParams(params); } } /** * Reset view to original height. */ private void resetViews() { for (int i = 0;; i++) { View v = getChildAt(i); if (v == null) { layoutChildren(); // force children to be recreated where needed v = getChildAt(i); if (v == null) { break; } } ViewGroup.LayoutParams params = v.getLayoutParams(); params.height = LayoutParams.WRAP_CONTENT; v.setLayoutParams(params); } } private void resetScrollBounds(int y) { int height = getHeight(); if (y >= height / 3) { mUpperBound = height / 3; } if (y <= height * 2 / 3) { mLowerBound = height * 2 / 3; } } private void scrollList(int y) { resetScrollBounds(y); int height = getHeight(); int speed = 0; if (y > mLowerBound) { // scroll the list up a bit speed = y > (height + mLowerBound) / 2 ? 16 : 4; } else if (y < mUpperBound) { // scroll the list down a bit speed = y < mUpperBound / 2 ? -16 : -4; } if (speed != 0) { int ref = pointToPosition(0, height / 2); if (ref == AdapterView.INVALID_POSITION) { //we hit a divider or an invisible view, check somewhere else ref = pointToPosition(0, height / 2 + getDividerHeight() + 64); } View v = getChildAt(ref - getFirstVisiblePosition()); if (v != null) { int pos = v.getTop(); setSelectionFromTop(ref, pos - speed); } } } public void setDropListener(DropListener l) { mDropListener = l; } public interface DropListener { void drop(int from, int to); } class Dragging { private Context context; private WindowManager windowManager; private WindowManager.LayoutParams mWindowParams; private ImageView mDragView; private Bitmap mDragBitmap; private int coordOffset; private int mDragPoint; // at what offset inside the item did the user grab it private int draggingItemHeight; private int x; private int y; private int lastY; public Dragging(Context context) { this.context = context; windowManager = (WindowManager) context.getSystemService("window"); } /** * @param y * @param offset - the difference in y axis between screen coordinates and coordinates in this view * @param view - which view is dragged */ public void start(int y, int offset, View view) { this.y = y; lastY = y; this.coordOffset = offset; mDragPoint = y - view.getTop(); draggingItemHeight = view.getHeight(); mDragView = new ImageView(context); mDragView.setBackgroundResource(android.R.drawable.alert_light_frame); // Create a copy of the drawing cache so that it does not get recycled // by the framework when the list tries to clean up memory view.setDrawingCacheEnabled(true); mDragBitmap = Bitmap.createBitmap(view.getDrawingCache()); mDragView.setImageBitmap(mDragBitmap); mWindowParams = new WindowManager.LayoutParams(); mWindowParams.gravity = Gravity.TOP; mWindowParams.x = 0; mWindowParams.y = y - mDragPoint + coordOffset; mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; mWindowParams.format = PixelFormat.TRANSLUCENT; mWindowParams.windowAnimations = 0; windowManager.addView(mDragView, mWindowParams); } public void drag(int x, int y) { lastY = this.y; this.x = x; this.y = y; mWindowParams.y = y - mDragPoint + coordOffset; windowManager.updateViewLayout(mDragView, mWindowParams); } public void stop() { if (mDragView != null) { windowManager.removeView(mDragView); mDragView.setImageDrawable(null); mDragView = null; } if (mDragBitmap != null) { mDragBitmap.recycle(); mDragBitmap = null; } } public int getDraggingItemHeight() { return draggingItemHeight; } public int calculateHoverPosition() { int adjustedY = (int) (y - mDragPoint + (Math.signum(y - lastY) + 2) * draggingItemHeight / 2); // Log.v(LOG_TAG, "calculateHoverPosition(): lastY=" + lastY + ", y=" + y + ", adjustedY=" + adjustedY); int pos = myPointToPosition(0, adjustedY); if (pos >= 0) { if (pos >= dragStartPosition) { pos -= 1; } } return pos; } } } 
  • OnDragListener - ¿hay alguna biblioteca de compatibilidad para niveles de Android <11?
  • Arrastrar y soltar en android 3.x causa illegalStateException después de pequeño número en arrastra
  • ¿Es posible arrastrar el elemento fuera de RecyclerView?
  • Cómo puedo arrastrar y soltar vistas en Android RelativeLayout
  • android arrastrar y soltar ImageView onTouchListener
  • Después de onLongPress, la primera vista en gridview obtiene NullPointerException en startDrag
  • Arrastre de elementos en la vista de cuadrícula
  • Detenga OnLongClickListener disparando mientras arrastra
  • Android: Problema de arrastrar y soltar
  • Programaticamente finaliza un Android DragEvent
  • Android imageView: configuración de los parámetros de arrastrar y comprimir el zoom
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.