notificaciones - Ventana emergente discreta que no bloqueará arrastrar y soltar en Android
spam chrome android (2)
Encuentra la posición de LinerLayout (que arrastra) en Gridview usando targetItem.pointToPosition(..)
.
Desliza LinerLayout usando el siguiente código:
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);
El código no está probado. Espero que te ayude :)
He estado trabajando en la aplicación launcher para android similar al nova launcher. Configuré OnItemLongClickListener y OnDragListener. Cuando hago clic largo en un ícono, aparece una ventana emergente con un menú como "Eliminar", "Cambiar ícono", etc. La siguiente figura muestra el progreso de la aplicación con la ventana emergente abierta mientras hace un clic largo.
El problema es que cuando se abre la ventana emergente, el arrastre funciona, pero dejar de funcionar no funciona. Parece que no puedo registrar la posición x, y una vez que la ventana emergente está abierta. Además, cuando se realiza la caída, se muestra el siguiente mensaje en logcat.
I/ViewRootImpl: Reporting drop result: false
Mi código es algo así en 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
}
}
Pero parece que después de abrir la ventana emergente no puedo registrar x o y; tampoco se puede ejecutar el código que determina si la acción fue diseñada para "arrastrar" o "abrir ventana emergente".
Entonces, ¿cómo resuelvo este problema? Quiero cerrar la ventana emergente una vez que la cantidad de arrastre sea suficiente para saber que el usuario quiere arrastrar. Y si no detiene el arrastre y muestra la ventana emergente solamente.
Editar
Resolví el problema con la ventana emergente usando OnTouchListner y OnDragListner. A continuación, se muestra mi código para 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;
}
});
Ahora el problema es que estoy obteniendo el objetivo de soltar "Gridview" ya que estoy eliminando LinearLayout en "Gridview". También este "LinearLayout es hijo de la" Gridview ". Y quiero que el drop target sea otro" LinearLayout "dentro de la misma" GridView ". De modo que pueda intercambiar datos o reordenarlos. Como en la figura a continuación.
Por lo que entiendo, hay dos cosas que quieres hacer. 1) Reordenar las vistas después de arrastrar. y 2) Cambie los tipos de vista después del reordenamiento.
Para el problema 1, ya que es una vista de cuadrícula, parece que realmente solo queremos reordenar los datos en el adaptador, y posiblemente cambiar los datos para hacer que se muestren de manera diferente. Pero debemos determinar la posición del artículo original y la posición de destino del destino.
podemos extender el GridView para hacer eso:
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;
}
}
}
}
}
Eso nos deja con llamar a handleMoveMethod. Hacemos eso desde el método 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;
Por último (problema 2) parece que desea cambiar el contenido del objeto en la posición o el tipo de vista en el que está contenido. Sugeriría usar los métodos getItemViewType y getItemViewTypeCount si necesita tener diferentes tipos de puntos de vista. Por ejemplo, algo similar a lo siguiente:
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;
}
Puede haber errores con esto así que por favor prueba a fondo