PDA

Ver la versión completa : [Programación] [Android] Arrastrar una View/Image para borrar/enviar



IronArthur
13/10/2011, 09:06
Hola,

Ando ahora mismo programando un prototipo para Android en el curro, quiero darle un par de detalles de chorradas que se pueden hacer y quiero hacer 2 cosas "candy":

Tengo un Tablelayout con un artículos que se añaden en tablerows, quiero arrastrar a una "papelera" para borrar esa linea (igual que el escritorio de Android)

Quiero seleccionar y arrastrar un elemento de una lista (Un pedido) a un "carrito/casa" para dejarlo en cola para enviar al servidor.


En si en las 2 cosas tengo el mismo problema, cuando detecto el touch down en el tablerow, he probado a crear una Imagen del elemento, la añado a un framelayout que engloba la interfaz e intento desplazarla por el layout. Sólo he encontrado como hacer modificando el padding de la imagen pero no me tira bien la verdad.

He encontrado como lo hacen con una View y moviendolo por el Framelayout con TopMargin y LeftMargin pero en mi caso del tablerow me da error pq no puedo usar los LayoutParams del Frame al estar dentro de un Table.

Lo estoy haciendo en MonoDroid, pero bueno es lo de menos pq traducir de un lenguaje a otro es trivial.

Supongo que me explicado como el culo....



PD:
layout :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:background="#fffdf1" a:id="@+id/frame" a:layout_height="fill_parent" a:layout_width="fill_parent"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linearLayout1" android:weightSum="1"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<TextView android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#333333" android:layout_width="wrap_content"
android:text="TextView" android:layout_height="wrap_content" android:id="@+id/txtTitulo"></TextView>
<RelativeLayout android:layout_width="match_parent" android:id="@+id/relativeLayout1" android:layout_weight="0"
android:layout_height="wrap_content">
<TextView android:text="@string/txtTitClientes" android:textColor="#333333" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:id="@+id/txtTitCliente"></TextView>

<-blablablabla mogollon de cosas->

</RelativeLayout>
<ScrollView android:id="@+id/scrollView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1">
<TableLayout android:id="@+id/tblListaArt" android:background="#EAEAEA" android:layout_height="wrap_content" android:layout_width="match_parent">
</TableLayout>
</ScrollView>
<RelativeLayout android:layout_width="fill_parent" android:id="@+id/relativeLayout2" android:layout_height="wrap_content">
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnGrabar" android:text="@string/btnGrabar"></Button>
<-blablablablabla->
</RelativeLayout>
</LinearLayout>
</FrameLayout>

Evento de Move con View que no me tira

case MotionEventActions.Move:
{
Log.Info("Drag", "DRAGGING");
FrameLayout.LayoutParams par = (FrameLayout.LayoutParams)v.LayoutParameters;
par.TopMargin = (int)e.RawY - (v.Height);
par.LeftMargin = (int)e.RawX - (v.Width / 2);
view.LayoutParameters = (par);
break;
}//inner case MOVE
Evento de Move con Imagen del objeto a mover:

imageDrag.SetPadding((int)e.RawX - imageDrag.Width, (int)e.RawY - imageDrag.Height, (int)e.RawX - 10, (int)e.RawY - 10);//

imageDrag.Invalidate();

Supongo q es dificil q alguien me pueda ayudar pero ya me estoy volviendo un poco loco con el tema....

Salu2

ChUKii
13/10/2011, 09:50
Entiendo lo que quieres hacer pero no tengo ni zorra de como se podría hacer :(



:brindis::brindis:

^MiSaTo^
13/10/2011, 09:51
No estoy segura de que eso que quieres se pueda hacer tan alegremente. No tengo ni dea de MonoTouch, pero en principio cuando mueves un objeto, realmente mueves su layout pero el elemento sigue estando ahí ocupando su sitio anterior.

Sería cuestión de que lo que tengas en el tablerow esté metido en un layout (cualquiera) y animes eso según se mueva el dedo. Y luego tendrás que destruir ese tablerow porque aunque no lo veas, seguirá estando ahí.

La verdad que lo que buscas es un poquito rebuscado xD No estoy 100% segura de que se pueda hacer

IronArthur
13/10/2011, 10:06
No es cuestión de Monotouch/droid, pq en android con java tampoco he conseguido hacerlo bien.

La cuestión es que en una interfaz con layout y multitud de objetos (tables, texview y demás) no vacia como en los ejemplos de internet. quiero que unos objetos concretos pueda arrastrarlos a una papelera, exactamente como se hace en el escritorio de android con los widgets y acesos directos.

Me explico fatal lo se... he encontrado ejemplos que hacen cosas similares como esto http://www.anddev.org/post102083.html#p102083, pero sólo sirve si no esta dentro de otro layout. Este otro p.e. es lo q pensaba usar que no mueve el objeto en si sino una imagen del mismo http://techdroid.kbeanie.com/2010/04/simple-drag-n-drop-on-android.html , pero me hace cosas raras al mover el padding de la imagen.

Supogno q estaré intentando algo que está al limite de lo actual en android, por lo menos para 2.2, pq creo que para las versiones más nuevas a un control "estandar" de dragndrop.

Voy a seguir buscando a ver si saco algo.

salu2

^MiSaTo^
13/10/2011, 10:10
No es cuestión de Monotouch/droid, pq en android con java tampoco he conseguido hacerlo bien.

La cuestión es que en una interfaz con layout y multitud de objetos (tables, texview y demás) no vacia como en los ejemplos de internet. quiero que unos objetos concretos pueda arrastrarlos a una papelera, exactamente como se hace en el escritorio de android con los widgets y acesos directos.

Me explico fatal lo se... he encontrado ejemplos que hacen cosas similares como esto http://www.anddev.org/post102083.html#p102083, pero sólo sirve si no esta dentro de otro layout. Este otro p.e. es lo q pensaba usar que no mueve el objeto en si sino una imagen del mismo http://techdroid.kbeanie.com/2010/04/simple-drag-n-drop-on-android.html , pero me hace cosas raras al mover el padding de la imagen.

Supogno q estaré intentando algo que está al limite de lo actual en android, por lo menos para 2.2, pq creo que para las versiones más nuevas a un control "estandar" de dragndrop.

Voy a seguir buscando a ver si saco algo.

salu2
Yo creo que no se puede hacer tal cual, nosotros ahora mismo movemos vistas con el dedo pero es más movimiento de scrool que mover líbremente las views.

Creo que ese control no existe en Android 2.2 vaya. Aparte como te digo, en CUALQUIER animación, cuando muevas una view que sepas que mueves la imagen, el contenido sigue en su posición original. Eso te puede crear muchos problemas como que detectes el onClick donde no debes y similares XD

IronArthur
13/10/2011, 10:22
Haciendo trampa con uno de los ejemplos puedo mover una view por la interfaz como pongo en el adjunto que el icono verde es una View que esta dentro del framelayout que engloba el resto, el problema es que funciona pq esta originalmente dentro del frame, el boton p.e que esta abajo le adjunto el mismo evento y el programa peta, entiendo pq le estoy metiendo los layoutparams de un frame y esta dentro de otro tipo de layout.

Se me está ocurriendo que igual puedo meter una imagen que esté todo el rato en el frame y mostrarla con el evento que quiero mover e ir cambiandole el src de la imagen.

Voy a probar.

salu2

IronArthur
14/10/2011, 12:09
Bueno, ya lo he conseguido de momento. Ahora estoy intentando hacerlo también en la opción del ListView, pero es más dificil pq hay que interceptar el evento del touch antes de los eventos por defecto del Listview.

A ver si tengo un momento luego, y limpio el código y lo pongo aquí por si alguien tiene la misma duda.

salu2

ChUKii
14/10/2011, 12:35
Bueno, ya lo he conseguido de momento. Ahora estoy intentando hacerlo también en la opción del ListView, pero es más dificil pq hay que interceptar el evento del touch antes de los eventos por defecto del Listview.

A ver si tengo un momento luego, y limpio el código y lo pongo aquí por si alguien tiene la misma duda.

salu2

Genial tio, me alegro de que ya lo tengas y si pones aqui un mini how to seria la 0stia! :D :D

:brindis::brindis:

IronArthur
14/10/2011, 12:50
Genial tio, me alegro de que ya lo tengas y si pones aqui un mini how to seria la 0stia! :D :D

:brindis::brindis:

A ver si luego lo puedo poner, que lo tengo hecho en Mono (C#) y lo tengo q traducir a Java que al final es lo que os puede servir a vosotros. La traducción de sintaxis es muy parecida/fácil pero no todo el mundo tiene pq saberlo.

Aparte en mi ejemplo es algo más complicado pq a la vez tengo un gesturelistener para detectar más tipos de touchevent aparte del de dragndrop. y no sé si merece la pena poner eso tb.

Salu2

ChUKii
14/10/2011, 13:03
A ver si luego lo puedo poner, que lo tengo hecho en Mono (C#) y lo tengo q traducir a Java que al final es lo que os puede servir a vosotros. La traducción de sintaxis es muy parecida/fácil pero no todo el mundo tiene pq saberlo.

Aparte en mi ejemplo es algo más complicado pq a la vez tengo un gesturelistener para detectar más tipos de touchevent aparte del de dragndrop. y no sé si merece la pena poner eso tb.

Salu2

Probablemente no merezca la pena poner lo del gesturelistener. Al final los ejemplos cuanto más sencillos mejor se entienden ;) ;)

Gracias!

:brindis::brindis:

IronArthur
14/10/2011, 13:35
Lo primero Layout:



<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#0106000d"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/Board"
android:layout_gravity="top">



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linearLayout1"
android:weightSum="1" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="vertical">
..............................lo que se quiera añadir...............................
<TableLayout android:id="@+id/tblListaArt"
android:layout_height="100px" android:layout_width="match_parent">
<TableRow android:id="@+id/tableRow2"
android:background="#FFFFFF"
android:layout_width="wrap_content" android:layout_height="wrap_content">
</TableRow>

</TableLayout>
................. más cosas
</LinearLayout>

<ImageView android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/img" android:layout_gravity="top">
</ImageView>

</FrameLayout>




Sobre el layout tenemos que englobar todo en un Framelayout, luego añadir un layout con nuestra UI, y por último un Imageview. Importante el orden pq en Android el orden del eje Z va en función de arriba-abajo = atras-adelante.

En código vamos a añadir el evento Ontouch del tablerow que se ve en el layout ( en el OnCreate de la Activity) y además activamos la DrawingCache para poder coger una "screenshot" de la row.




row = (TableRow)findViewById(R.id.tableRow2);
row.setDrawingCacheEnabled(true);
row.setOnTouchListener(dragt);

TextView txtNombreArt = new TextView(this);
txtNombreArt.setText("asd");
row.addView(txtNombreArt); // AÑADO UN TEXTO AL ROW PARA QUE SE VEA



Y defino el listener del TouchEvent:



OnTouchListener dragt = new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
FrameLayout.LayoutParams par = (LayoutParams) img.getLayoutParams();
switch(v.getId())
{//What is being touched
case R.id.tableRow2:
{//Which action is being taken
switch(event.getAction())
{
case MotionEvent.ACTION_MOVE:
{

par.topMargin = (int)event.getRawY() - 50;
par.leftMargin = (int)event.getRawX() - (v.getWidth()/4);
img.setLayoutParams(par);
break;
}//inner case MOVE
case MotionEvent.ACTION_UP:
{

img.setImageDrawable(null); //BORRO LA FUENTE DE LA IMAGEN PARA QUE DESAPAREZCA
break;
}//inner case UP
case MotionEvent.ACTION_DOWN:
{
img.setImageBitmap(v.getDrawingCache(true)); //COJO LA SCREENSHOOT DE LA ROW


par.topMargin = (int)event.getRawY() -50 ;
par.leftMargin = (int)event.getRawX() - (v.getWidth()/4);;

par.height = v.getHeight()*2; //LA HAGO UN POCO MÄS GRANDE O PEQUEÑA
par.width = v.getWidth();


img.setLayoutParams(par);
break;
}//inner case UP
case MotionEvent.ACTION_CANCEL:
{
img.setImageDrawable(null);
break;
}

}//inner switch
break;
}//case pawn

}//switch
return true;
}//onTouch
};//dragt




Creo que se entiende más o menos. Faltaría el código de donde queramos dejarla, que seria en el MotionEvent.ACTION_UP


ImageButton btn; //EL BOTON QUE SE QUIERA O LA IMAGEN O LO Q SEA;
int[] aux = new int[2];
btn.getLocationOnScreen(aux);

if ((int)event.getRawX() > aux[0] && (int)(int)event.getRawX() < aux[0] + btn.getWidth())
{
if ((int)event.getRawY() > aux[1] && (int)event.getRawY() < aux[1] + btn.getHeight())
{
Log.i("Drag", "Dentro -" + (int)event.getRawX() + " - " + (int)event.getRawY());

Log.i("Drag", "Borrar ");
}
}


Muy optimizable todo lo que pongo. A ver si aparece nuestra experta residente en Android&Iphone y opina :D

Salu2

^MiSaTo^
14/10/2011, 15:19
Ahora no tengo tiempo de ver toodo el código pero sólo un pequeño apunte:
1) ¿Por qué usas frameLayout? Lo digo porque no es la mejor idea casi nunca, dado que se pinta en pantalla por frames (o trozos) y creeme que en según qué dispositivos se ve raruno hagas lo que hagas.

2) Cuantos menos layouts tengas mejor. Es decir que si en vez de tener el frameLayout, luego el Linear y luego dentro el TableLayout tuvieras sólo Linear y Table irá mucho mejor. La creación de layouts es realmente costosa en Android, para una aplicación chiquitita no se nota pero en cuanto tienes algo grande la cosa se nota y mucho. Esto es sólo como un consejo general, y obviamente cuando es inevitable pues tendrás que dejarlo así (que no se si en tu caso lo es).

Por lo demás, a ver si puedo echarle un ojo luego porque nunca he hecho algo como lo tuyo y me parece interesante :)

PD: hace tiempo creé una wiki sobre programación de móviles y demás, si hay mucha gente interesada en el foro puedo hacerlo más colaborativa, porque ahora está un poco abandonada y con cosas "para mi" que he ido haciendo ;)

IronArthur
14/10/2011, 15:24
El framelayout hace falta para poder mover la imagen por coordenadas con topmargin y leftmargin, pq en un linearlayout no te deja mover un objeto así (o yo no he podido).

Lo de los layout ya lo he notado pq en otra pantalla hago una listview con un adapterCustom y dentro de cada linea tengo 2 layout, 1 general y otro horizontal para 2-3 campos que están en la misma linea. Y aunque puede ser por emulador+Mono+cargar de bbdd es la pantalla q más tarda en cargar.

Salu2