Home Menu

Menu



Programación y Desarrollo para Android Subforo exclusivo para temas de programación de software para PDAs y desarrollo de aplicaciones, interfaces, etc bajo Android


 
Herramientas
  #1  
Viejo 17/01/16, 20:49:17
Avatar de Godlike
Godlike Godlike no está en línea
Miembro del foro
Mensajes: 101
 
Fecha de registro: jul 2015
Mensajes: 101
Modelo de smartphone: LG G5
Tu operador: Vodafone
Mencionado: 0 comentarios
Tagged: 0 hilos
interrogacion Editar atributo de campo dentro de un ArrayAdapter

Invoco a @kriogeN y @mocelet !! jaja

Buenas tardes compañeros,

hace un tiempo me ayudásteis mucho en el hilo:

http://www.htcmania.com/showthread.php?t=1052875


Me han pedido un pequeño cambio pero me cuesta tanto que llevo todo el día modificando cosas y no logro hacerlo funcionar. El problema que encuentro es que tengo un custom ArrayAdapter, gracias al cual creo una línea con varios campos cada vez que el usuario pulsa un botón para añadir "Conceptos".

Todo esto se basa en algo que me enseñásteis, y es en el modelo vista controlador, así que tengo un xml que es el que modela los campos que se muestran, luego el adapter en sí que controla la lógica, y un array donde se contienen realmente los datos.

Esta es la parte donde se maneja el comportamiento de uno de los campos, el que contiene el nombre del concepto:

[php]final AutoCompleteTextView concepto = (AutoCompleteTextView) item.findViewById(R.id.conceptoId);
item.setTag(concepto);
concepto.setText(datos.get(pos).getNombre());
concepto.addTextChangedListener(new TextWatcher() {
@override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@override
public void onTextChanged(CharSequence s, int start, int before, int count) {

}

@override
public void afterTextChanged(Editable s) {
datos.get(pos).setNombre(concepto.getText().toStri ng());
if (datos.get(pos).getNombre().equals("")) {
if (datos.size() > 1) {
datos.remove(pos);
notifyDataSetChanged();
}
}
}
});
[/php]No tengo problemas en editar el adapter para manejar los datos como quiera, de hecho tengo un AutoCompleteTextView en uno de los campos y al seleccionar un item de la lista autocompleto otros campos recuperando datos de una base de datos. Sin embargo lo sé cómo actar sobre el campo en sí mismo.

Esta es la lógica que controla esto último

[php]//Catch selected producto to fill details
concepto.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@override
//ATTENTION: This position variable can easily confuse with the main one. "pos" is the position from main getView, "position" is the relative to this function
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Getting the selected item to seek for other information of the producto
String producto = adapter.getItem(position);

//Log.d(TAG, "Estoy dentro del click!!");

Cursor cursorProducto = db.getFromProducto(producto);

if (cursorProducto != null && cursorProducto.moveToFirst()) {
datos.get(pos).setId(Integer.parseInt(cursorProduc to.getString(cursorProducto.getColumnIndex("id"))) );
datos.get(pos).setCantidad(1);
datos.get(pos).setNombre(cursorProducto.getString( cursorProducto.getColumnIndex("nombre")));
datos.get(pos).setDescripcion(cursorProducto.getSt ring(cursorProducto.getColumnIndex("nombre"))); //Copying nombre to descripcion by default
datos.get(pos).setPrecio(Double.parseDouble(cursor Producto.getString(cursorProducto.getColumnIndex(" precio_publico"))));
notifyDataSetChanged();
}

}
});

return(item);
}[/php]
Qué quiero conseguir:
Tras seleccionar uno de los items, y por tanto autocompleto otros datos, bloquear ese campo para que ya no sea editable.

He tratado en la parte del programa que véis al final hacer:

Código:
concepto.setEnabled(false);
Y funciona... pero me bloquea TODOS los campos de concepto, y no sé cómo aplicarlo sólamente a la línea que estoy editando y no a todos, es decir, poder diferenciar ese campo de ese mismo campo en otras "líneas", pero claro su "id" es el mismo porque en el XML sólo tengo la plantilla por así decirlo.

Agradezco de antemano cualquier ayuda

Última edición por Godlike Día 24/01/16 a las 16:36:52
Responder Con Cita


  #2  
Viejo 18/01/16, 11:21:54
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
Cuando en Android buscas por identificador solo te devuelve una view. Y si buscas dentro de una fila (item.findView...) no te va a devolver views que estén en otras filas.

Así que el concepto.setEnabled(false) que mencionas se estará ejecutando en todas las filas porque la comprobación de la condición para que esté enabled o no será incorrecta.
Responder Con Cita
Gracias de parte de:
  #3  
Viejo 18/01/16, 11:54:39
Avatar de Godlike
Godlike Godlike no está en línea
Miembro del foro
Mensajes: 101
 
Fecha de registro: jul 2015
Mensajes: 101
Modelo de smartphone: LG G5
Tu operador: Vodafone
Mencionado: 0 comentarios
Tagged: 0 hilos
Cita:
Originalmente Escrito por mocelet Ver Mensaje
Cuando en Android buscas por identificador solo te devuelve una view. Y si buscas dentro de una fila (item.findView...) no te va a devolver views que estén en otras filas.

Así que el concepto.setEnabled(false) que mencionas se estará ejecutando en todas las filas porque la comprobación de la condición para que esté enabled o no será incorrecta.
Buenas Mocelet, muchas gracias por responder.

El problema que me encuentro es exactamente el que mencionas, me he explicado quizá un poco mal pero has comprendido el problema perfecto.

¿De qué manera podría entonces acceder a ese campo en concreto? porque entiendo que se debe poder no? no sé cómo harán si no muchos juegos Android jaja

Gracias de nuevo
Responder Con Cita
  #4  
Viejo 19/01/16, 14:25:48
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
Me pierdo un poco entre conceptos, items y campos.

Ya que haces un notifyDataSetChanged() al autocompletar los datos a partir de la base de datos, se va a ejecutar otra vez el getView del adaptador. Es ahí donde tendrás que ver si llamar al setEnabled con true o con false. Esto es igual que cuando pones el texto, no buscas el campo, actualizas los datos y el campo refleja la información.

Si no tienes información suficiente en el array de datos para determinar si hay que habilitar o no la edición tendrás que añadir otro método del tipo setAutocompleted(true/false) para saber si esos datos los ha metido el usuario o se han generado automáticamente y no pueden editarse. Cuando sea por autogeneración haces un datos.get(pos).setAutocompleted(true) y cuando sea por el usuario lo mismo con false.

Así cuando tengas que pintar la celda en getView después de autocompletar lees el valor del boolean y ya sabes si hay que habilitar la edición o no.
Responder Con Cita
Gracias de parte de:
  #5  
Viejo 21/01/16, 14:54:09
Avatar de Godlike
Godlike Godlike no está en línea
Miembro del foro
Mensajes: 101
 
Fecha de registro: jul 2015
Mensajes: 101
Modelo de smartphone: LG G5
Tu operador: Vodafone
Mencionado: 0 comentarios
Tagged: 0 hilos
Cita:
Originalmente Escrito por mocelet Ver Mensaje
Me pierdo un poco entre conceptos, items y campos.

Ya que haces un notifyDataSetChanged() al autocompletar los datos a partir de la base de datos, se va a ejecutar otra vez el getView del adaptador. Es ahí donde tendrás que ver si llamar al setEnabled con true o con false. Esto es igual que cuando pones el texto, no buscas el campo, actualizas los datos y el campo refleja la información.

Si no tienes información suficiente en el array de datos para determinar si hay que habilitar o no la edición tendrás que añadir otro método del tipo setAutocompleted(true/false) para saber si esos datos los ha metido el usuario o se han generado automáticamente y no pueden editarse. Cuando sea por autogeneración haces un datos.get(pos).setAutocompleted(true) y cuando sea por el usuario lo mismo con false.

Así cuando tengas que pintar la celda en getView después de autocompletar lees el valor del boolean y ya sabes si hay que habilitar la edición o no.
Hola mocelet,

muchas gracias por tu ayuda.

Siento el lío, no quiero inundarte con código porque demasiado que ayudas a tanta gente, pero por favor si lo prefieres para poder entender mejor lo que es cada cosa sólo dímelo.

De todas formas el tema es justo el que comentas, es decir, para mi el problema no es saber en qué momento lanzar la acción de establecer el campo como setEnabled(false), sino precisamente cómo actuar sobre ese campo.

Comentas que "Es ahí donde tendrás que ver si llamar al setEnabled con true o con false. Esto es igual que cuando pones el texto, no buscas el campo, actualizas los datos y el campo refleja la información."

Pero es exactamente ahí donde fallo, es decir, yo sé cómo modificar ese array "datos" porque lo tengo, y cuando leo ymodifico el valor de cualquier posición de este array de datos, la aplicación los muestra en la vista tras indicarle que se ha actualizado (notifyDataSetChanged()), pero si accedo a un dato de esta lista no puedo establecer setEnabled(false) porque no tiene sentido sobre un valor, sino sobre la vista en sí, pero no sé cómo modificar el campo, la vista (el getView) estando dentro del adapter.

Probablemente sea una chorrada pero es eso justo lo que me falla, es decir, supongamos que tengo suficiente información en los datos como para determinar el setEnabled a true o false (en principio me basta con el evento en que el usuario selecciona una opción de la lista del AutoComplete), pero no sé cómo ejecutar esta tarea:

"Así cuando tengas que pintar la celda en getView después de autocompletar lees el valor del boolean y ya sabes si hay que habilitar la edición o no"

Suponiendo que sé perfectamente si tengo que habilitar la edición o no, no sé cómo habilitarla sólo para ese campo. No sé si te refieres a que no es tipo un evento sino que cada vez que pinta tendrá que comprobar si ese campo es apto para ser establecido a setEnabled(true) o no, y no hacerlo como si fuera un evento como pretendo.

Si te refieres a esto último... comentas de hacer "datos.get(pos).setAutocompleted(true)", esto utilizará este método para cada valor de la lista y por tanto al dibujar y seguir la lógica de establecer a true o false el setEnabled para cada uno?, pensaba que al hacer esta sentencia se aplicaba a todos a la vez, pero tal vez simplemente se aplica a todos uno detrás de otro porque no hay filtro que determine qué hacer.


Muchas gracias por tanta ayuda,
un saludo!
Responder Con Cita
  #6  
Viejo 21/01/16, 18:24:02
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
Cita:
Originalmente Escrito por Godlike Ver Mensaje
No sé si te refieres a que no es tipo un evento sino que cada vez que pinta tendrá que comprobar si ese campo es apto para ser establecido a setEnabled(true) o no, y no hacerlo como si fuera un evento como pretendo.
Creo que ya hablamos de lo mismo. El evento desencadena la acción de autocompletado y desactiva una serie de campos, ¿no?

En vez de buscar la vista directamente y cambiarla, añade en algún sitio a los datos que ciertos atributos no pueden cambiarse porque han sido autogenerados. Así cuando la lista se refresque con el notifyDataSetChanged (y se llame al getView de cada fila) ya sabes para cada fila qué hay que tener activado o desactivado.

Si actualizas la vista "a pelo" pero no guardas nada en ningún sitio, con que el usuario haga scroll y se recicle una fila ya se ha liado porque pierdes el estado y aparecerán campos deshabilitados que no deberían y viceversa. El enabled a true o false de las cosas que puedan cambiar hazlo en el getView.
Responder Con Cita
Gracias de parte de:
  #7  
Viejo 22/01/16, 13:48:59
Avatar de Godlike
Godlike Godlike no está en línea
Miembro del foro
Mensajes: 101
 
Fecha de registro: jul 2015
Mensajes: 101
Modelo de smartphone: LG G5
Tu operador: Vodafone
Mencionado: 0 comentarios
Tagged: 0 hilos
Cita:
Originalmente Escrito por mocelet Ver Mensaje
Creo que ya hablamos de lo mismo. El evento desencadena la acción de autocompletado y desactiva una serie de campos, ¿no?

En vez de buscar la vista directamente y cambiarla, añade en algún sitio a los datos que ciertos atributos no pueden cambiarse porque han sido autogenerados. Así cuando la lista se refresque con el notifyDataSetChanged (y se llame al getView de cada fila) ya sabes para cada fila qué hay que tener activado o desactivado.

Si actualizas la vista "a pelo" pero no guardas nada en ningún sitio, con que el usuario haga scroll y se recicle una fila ya se ha liado porque pierdes el estado y aparecerán campos deshabilitados que no deberían y viceversa. El enabled a true o false de las cosas que puedan cambiar hazlo en el getView.

Ahora si que entiendo a lo que te refieres!

Me he puesto a ello, te comento los cambios:

Al objecto "Concepto" le he añadido un par método como el que comentabas

[php]//Others
public boolean getAutocompleted (){
return this.autoGenerated;
}
public void setAutocompleted (boolean estado){
this.autoGenerated = estado;
}[/php]
Luego en el adapter lo que tengo es
[php]
private final ArrayList <Concepto> datos;[/php]
De forma que una vez clica el usuario sobre un elemento del AutoCompleteTextView...
[php]
//Catch selected producto to fill details
concepto.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@override
//ATTENTION: This position variable can easily confuse with the main one. "pos" is the position from main getView, "position" is the relative to this function
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Getting the selected item to seek for other information of the producto
String producto = adapter.getItem(position);

//Log.d(TAG, "Estoy dentro del click!!");

Cursor cursorProducto = db.getFromProducto(producto);

if (cursorProducto != null && cursorProducto.moveToFirst()) {
datos.get(pos).setId(Integer.parseInt(cursorProduc to.getString(cursorProducto.getColumnIndex("id"))) );
datos.get(pos).setCantidad(1);
datos.get(pos).setNombre(cursorProducto.getString( cursorProducto.getColumnIndex("nombre")));
datos.get(pos).setDescripcion(cursorProducto.getSt ring(cursorProducto.getColumnIndex("nombre"))); //Copying nombre to descripcion by default
datos.get(pos).setPrecio(Double.parseDouble(cursor Producto.getString(cursorProducto.getColumnIndex(" precio_publico"))));
datos.get(pos).setAutocompleted(true);
notifyDataSetChanged();
}

}
});

[/php]


Donde se ve que hago datos.get(pos).setAutocompleted(true);

La declaración del getView es esta:

[php]public View getView(final int position, View convertView, ViewGroup parent){[/php] Bueno pues aunque a continuación, o fuera del setOnItemClickListener (pero aún dentro del getView) haga:

[php]View row = convertView;
if (datos.get(pos).getAutocompleted)
row.setEnabled(false);
[/php]


No sucede nada, no crashea pero no hace nada de lo que debería hacer... algo se me escapa, ¿podrías echarme una mano por favor? Te lo agradezco muchísimo.

Un saludo!
Responder Con Cita
  #8  
Viejo 22/01/16, 14:01:51
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
El enabled en todo caso tendrás que hacerlo a cada uno de los cuadros de texto que quieras deshabilitar, no a la convertview (row) que sólo es un grupo de vistas.

Y el estado lo tienes que actualizar siempre, tanto para true como para false. Si no se quedará un valor antiguo al reciclar la fila.

Última edición por mocelet Día 22/01/16 a las 14:04:02
Responder Con Cita
Gracias de parte de:
  #9  
Viejo 22/01/16, 14:15:52
Avatar de Godlike
Godlike Godlike no está en línea
Miembro del foro
Mensajes: 101
 
Fecha de registro: jul 2015
Mensajes: 101
Modelo de smartphone: LG G5
Tu operador: Vodafone
Mencionado: 0 comentarios
Tagged: 0 hilos
Cita:
Originalmente Escrito por mocelet Ver Mensaje
El enabled en todo caso tendrás que hacerlo a cada uno de los cuadros de texto que quieras deshabilitar, no a la convertview (row) que sólo es un grupo de vistas.
Perdona mocelet, pero es justo eso lo que no sé cómo hacer, ¿podrías darme un ejemplo de código para que vea cómo podría acceder sólo a la vista y campo de texto de la "fila" en que me encuentro?

Cita:
Originalmente Escrito por mocelet Ver Mensaje
Y el estado lo tienes que actualizar siempre, tanto para true como para false. Si no se quedará un valor antiguo al reciclar la fila.
Lo que hago en la clase, cuando instancio el objeto de Concepto, es darle por defecto el valor "false" al boolean autocompleted. Por tanto cuando sé que ha sido autocompletado le asigno el valor "true" y actualizo con el notify. Cuando dices que actualice cuando está como false, te refieres a que lo establezca como "false" después de cada introduzcción de texto antes de actualizar si no ha sido seleccionado por el complete? ¿por qué cambiaría?


Mil gracias de nuevo
Responder Con Cita
  #10  
Viejo 22/01/16, 14:23:03
Avatar de Godlike
Godlike Godlike no está en línea
Miembro del foro
Mensajes: 101
 
Fecha de registro: jul 2015
Mensajes: 101
Modelo de smartphone: LG G5
Tu operador: Vodafone
Mencionado: 0 comentarios
Tagged: 0 hilos
Funciona!!!!

Creo que esto resume lo que me decías que hiciera:

[php]
if (datos.get(pos).getAutocompleted())
concepto.setEnabled(false);
else
concepto.setEnabled(true);

notifyDataSetChanged();
[/php]
donde concepto es
[php]final AutoCompleteTextView concepto = (AutoCompleteTextView) item.findViewById(R.id.conceptoId);[/php]




Qué alegría!!! muchísimas gracias, tu ayuda es inestimable
Responder Con Cita
  #11  
Viejo 22/01/16, 19:35:39
Avatar de Dexafree
Dexafree Dexafree no está en línea
Mr. FAQMan
Mensajes: 8,021
Compra y venta: (1)
 
Fecha de registro: dic 2008
Mensajes: 8,021
Modelo de smartphone: Samsung Galaxy S i9000 + Galaxy Tab 10.1 WiFi
Versión de ROM: Android 4.1.1 Jelly Bean
Versión de Radio: KF1
Tu operador: Movistar
Mencionado: 65 comentarios
Tagged: 2 hilos
Solucionado entonces?

Si es asi puedes marcarlo como solucionado
Responder Con Cita
Gracias de parte de:
  #12  
Viejo 24/01/16, 16:36:28
Avatar de Godlike
Godlike Godlike no está en línea
Miembro del foro
Mensajes: 101
 
Fecha de registro: jul 2015
Mensajes: 101
Modelo de smartphone: LG G5
Tu operador: Vodafone
Mencionado: 0 comentarios
Tagged: 0 hilos
Cita:
Originalmente Escrito por Dexafree Ver Mensaje
Solucionado entonces?

Si es asi puedes marcarlo como solucionado
Hecho! ;)
Responder Con Cita
Gracias de parte de:
Respuesta

Estás aquí
Regresar   HTCMania > Todo sobre Android > Programación y Desarrollo para Android


Reglas de Mensajes
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Las caritas están On
Código [IMG] está On
Código HTML está Off

Saltar a Foro



Hora actual: 14:38:47 (GMT +2)

Cookies
Powered by vBulletin™
Copyright © vBulletin Solutions, Inc. All rights reserved.
 
HTCMania: líderes desde el 2007