Arrastrar y soltar en un `ListView`

Estoy tratando de implementar un arrastrar y soltar en un ListView en android (Ice Cream Sandwich). Así que cuando el objeto arrastrado alcanza el borde del ListView , estoy desplazando el ListView en la dirección pertinente. El problema es que cuando nos desplácese, a veces el adaptador crea nuevas View como necesarias y estas 'nuevas' View no recibieron el evento ACTION_DRAG_STARTED anteriormente y por lo tanto no reciben las actualizaciones de DragEvent . ¿Hay alguna manera de enviar los eventos a estas vistas también?

Una forma más fácil de implementar arrastrar y soltar en listview es utilizar esta gran biblioteca. https://github.com/commonsguy/cwac-touchlist vale la pena intentarlo.

Mirando la fuente para ver, veo:

 static final int DRAG_CAN_ACCEPT = 0x00000001; int mPrivateFlags2; boolean canAcceptDrag() { return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0; } 

MPrivateFlags2 es paquete privado y no expuesto por el SDK. Sin embargo, debería ser capaz de cambiarlo en una subclase haciendo:

 try { Field mPrivateFlags2 = this.getClass().getField("mPrivateFlags2"); int currentValue = mPrivateFlags2.getInt(this); mPrivateFlags2.setInt(this, currentValue | 0x00000001); } catch (Exception e) { } 

Tengo el mismo problema . No solucioné este problema de reciclaje, pero encontré una posible solución aún utilizando el marco Drag & Drop. La idea es cambiar de perspectiva: en lugar de usar un OnDragListener en cada View de la lista, se puede utilizar directamente en el ListView .

Entonces la idea es encontrar en la parte superior del elemento que el dedo es mientras se realiza el Drag & Drop, y para escribir el código de visualización relacionados en el ListAdapter de la ListView . El truco es entonces encontrar en la parte superior de la vista del artículo que somos, y donde se hace la caída.

Para ello, establezco como id en cada vista creada por el adaptador su posición ListView – con View.setId() , para poder encontrarla más tarde usando una combinación de ListView.pointToPosition() y ListView.findViewById() .

Como un ejemplo de escucha de arrastre (que es, te lo recuerdo, aplicado en el ListView ), puede ser algo así:

 // Initalize your ListView private ListView _myListView = new ListView(getContext()); // Start drag when long click on a ListView item _myListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view); view.startDrag(null, shadowBuilder, _myListView.getItemAtPosition(position), 0); return true; } }); // Set the adapter and drag listener _myListView.setOnDragListener(new MyListViewDragListener()); _myListView.setAdapter(new MyViewAdapter(getActivity())); // Classes used above private class MyViewAdapter extends ArrayAdapter<Object> { public MyViewAdapter (Context context, List<TimedElement> objects) { super(context, 0, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { View myView = convertView; if (myView == null) { // Instanciate your view } // Associates view and position in ListAdapter, needed for drag and drop myView.setId(position); return myView; } } private class MyListViewDragListener implements View.OnDragListener { @Override public boolean onDrag(View v, DragEvent event) { final int action = event.getAction(); switch(action) { case DragEvent.ACTION_DRAG_STARTED: return true; case DragEvent.ACTION_DRAG_DROP: // We drag the item on top of the one which is at itemPosition int itemPosition = _myListView.pointToPosition((int)event.getX(), (int)event.getY()); // We can even get the view at itemPosition thanks to get/setid View itemView = _myListView.findViewById(itemPosition ); /* If you try the same thing in ACTION_DRAG_LOCATION, itemView * is sometimes null; if you need this view, just return if null. * As the same event is then fired later, only process the event * when itemView is not null. * It can be more problematic in ACTION_DRAG_DROP but for now * I never had itemView null in this event. */ // Handle the drop as you like return true; } } } 

Ahora si usted necesita tener una regeneración visual al hacer un arrastrar y soltar, hay varias estrategias. Por ejemplo, puede tener 2 variables de instancia en su actividad denominada:

 private boolean ongoingDrag = false; // To know if we are in a drag&drop state private int dragPosition = 0; // You put the itemPosition variable here 

Al hacer la MyListViewDragListener arrastrar y soltar en MyListViewDragListener , modifica estas variables y usa su estado en MyViewAdapter . Por supuesto no olvide actualizar la interfaz de usuario (en el hilo de eventos, por supuesto, utilice un Handler) con algo como.

El problema es porque listView.getPositionForView (view) devuelve -1 si la vista no está visible cuando se llama. Así que confiar en que se producirá un error cuando se desplaza la lista. Por lo tanto, en lugar de establecer un view.setOnLongClickListener () puede establecer un listView.setOnItemLongClickListener () en el elemento de lista que llama a startDrag () en el elemento. OnItemLongClick () le da la posición que puede pasar a en el parámetro myLocalState de startDrag (). Entonces usted recupera eso en onDrag () usando event.getLocalState () y el molde de él a un entero. Me gusta esto…

  listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { position -= listView.getHeaderViewsCount(); DragShadowBuilder dragShadow = new View.DragShadowBuilder(view); view.startDrag(null, dragShadow, position, 0); return true; } }); 

Entonces en su OnDragListener …

 @Override public boolean onDrag(View eventView, DragEvent event) { Integer dragViewPos = ((Integer) event.getLocalState()); int eventViewPos = listView.getPositionForView(eventView) - listView.getHeaderViewsCount(); ... } 
  • Box2D rotar un objeto, ¿cómo?
  • ¿Cómo comparte las variables con otras actividades fácilmente?
  • Problema al abrir el archivo de elementos con la ayuda del proveedor de contenido
  • ¿Cómo puedo asegurar que el controlador de otro hilo no sea nulo antes de llamarlo?
  • Cómo establecer fillColor, StrokeWidth y StrokeColor de vector drawable programatically en Android
  • ¿El cliente REST de Android, Sample?
  • ¿Cómo puedo obtener un Android TableLayout para llenar la pantalla?
  • Crear gran Jar (escritorio) de android / escritorio gdx proyecto
  • HttpResponse a la longitud de cadena 0 se devuelve
  • ¿Puede una aplicación o actividad de Android llamar a APIs en niveles de API más altos?
  • Hacer que un campo EditText acepte sólo letras y espacios en blanco en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.