PDA

Ver la Versión Completa : Problema con scroll Listview y Background de items


LuPaSs
23/10/13, 10:57:22
muy buenas pongo aqui el codigo XML de mi listview:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="schemas.android.com/apk/res/android"
android:layout_width="fill_parent"

android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@drawable/footer_background"

>
<LinearLayout

android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp" >
<ListView

android:cacheColorHint="#00000000"
android:scrollingCache="false"
android:id="@+id/listviewArchivos"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#b5b5b5"
android:dividerHeight="1dp">
</ListView>
</LinearLayout>
<RelativeLayout

android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/idTextRutaArchivoFooter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:textColor="@color/white" />

<ImageView android:id="@+id/imgIdSave"
android:layout_width="50dp"
android:layout_height="50dip"
android:src="@drawable/save"
android:layout_alignParentRight="true" />

<ImageView android:id="@+id/imgIdOpen"
android:layout_width="50dp"
android:layout_height="50dip"
android:src="@drawable/open"
android:layout_alignParentRight="true" />


</RelativeLayout>

</LinearLayout>


de acuerdo con esto es un listview con un ArrayAdapter<File>. He implementado una seleccion multiple basada en un mapa de <Integer,Boolean>. dependiendo de las posiciones que esten a true cambio el View del Item por otro backGround.

El problema viene que si hago scroll a mi lista, el color del elemento seleccionado se traslada a otro item sin ejecutarse nada de codigo. ¿ Por que puede estar pasando esto?

He probado ya con ponerle al listview:
android:cacheColorHint="#00000000"
y tambien:
android:scrollingCache="false"


y sigue igual.¿ Que está ocurriendo? ¿ Como puedo resolverlo¿? Gracias y Un saludo!!

kriogeN
23/10/13, 12:08:13
Por la reutilización de vista de los ListView (y GridView y algunos más).

Si se muestran 3 elementos a la vez en la pantalla, el 1º y el 5º son el mismo elemento, esto quiere decir que si en el getView() no modificas el fondo, si no que lo estableces en un código fuera, cuando se muestre el 5º tendrá el mismo fondo que tenía el 1º en su momento.

¿Cómo resolverlo? En el getView() tienes que cambias el fondo según el mapa siempre.

LuPaSs
23/10/13, 13:41:01
Gracias por la respuesta, llevaba toda la mañana intentando resolverlo y ahora me he metido para responder la solucion.

En efecto tienes razón.Lo voy a explicar detalladamente por si le pasa a alguien.

* Primero dejar claro que hay que entender bien el funcionamiento del getView() y del evento Onclick del listviewItem.

buscando por google encontre esto:
http://stackoverflow.com/questions/9188201/list-view-position-is-getting-changed-when-scrolling-on-android

me vino muy bien la respuesta donde dice:
que el getView el convertView siempre debe ejecutarse la rama de null.
View view = null; convertView = null; in the get view and comments the else part of if (convertView == null) { } /*else{ } */Con esto consegui que los elementos al hacer scroll no se trasladara los background, ya que buscando en mas sitios encontre que era un problema de la cache del scroll y a pesar de cambiar estos valores en el XML a null no funcionaba.

* El segundo problema que me dio fue que el getView siempre representaba las posiciones que el scroll le daba, con lo cual si haciamos scroll hacia abajo representaria los siguientes elementos que se han mostrado: por ejemplo del 23-27, hasta aqui todo es correcto, el problema viene cuando haciemos CLICK en un elemento.

public void onItemClick(AdapterView<?> adapter, View view, int position,
long arg3) {}

la posicion que nos devuelve siempre es de la vista actual del ListView; me explico:
tu listview cuando necesita hacer scroll, significa que la lista del adapter es mas grande que lo que el listView puede mostrar. Con lo cual si nuestra lista era de 30 elementos y solo podemos mostrar 25, tu listview va a tener una vista de 0 a 25 elementos.

Cuando hacemos el scroll, lo que hace el listview es desplazar las posiciones del adapter. con lo cual; si hemos desplazado 3 posiciones, ahora el elemento que habia en la posicion 3 pasara a estar en la posicion 0.


entonces para recoger el verdadero View necesitas tener el Int posicion y restarle la posicion que tiene el texto que hemos clicado en tu adapter inicial el de 0..30. Es un poco entreversado, hay que entenderlo muy bien.

dejo aqui mi codigo de una seleccion exclusiva de elementos de un listview

pd. Seguro que hay mil maneras de hacerlo, yo estoy iniciandome y vi mas clara esta manera por que yo necesito listview con seleccion exclusiva y tambien con seleccion multiple.

codigo Manager_Archivos:
public void inicializaElementosSelectedListView(AdapterView<?> adapterAux,Integer seleccion){
this.listaItemsListView= new HashMap<Integer,Boolean>();
TextView va=(TextView) adapterAux.getChildAt(0).findViewById(R.id.txtRuta ArchivoItem);
for (int i=0;i<adapter.getData().length;i++){

this.listaItemsListView.put(i, i==seleccion?true:false);
View v = listView.getChildAt(i-adapter.getDataPos(va.getText().toString()));
if (v != null)
v.setBackgroundResource(listaItemsListView.get(i)? R.drawable.gradient_bg_hover:R.drawable.gradient_b g);

}
this.listaItemsListView.put(seleccion, true);
this.adapter.setItemsSeleccionados(listaItemsListV iew);

}
public void recargaListView(ListView listView,LayoutInflater infiltrater,Context context,File[] dataSource){
this.listView= listView;

this.adapter = new ArchivoAdapter(context,R.layout.listview_archivos_ item,dataSource);
inicializaElementosSelectedListView();
adapter.setItemsSeleccionados(this.listaItemsListV iew);
listView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> adapter, View view, int position,
long arg3) {
inicializaElementosSelectedListView(adapter,positi on);
}

});

this.listView.setAdapter(adapter);
}

Codigo ArchivoAdapter:
public class ArchivoAdapter extends ArrayAdapter<File>{
private Context context;
private Integer layoutResourceId;
private File[] data;
private Map<Integer,Boolean>itemsSeleccionados;
public ArchivoAdapter(Context context, int layoutResourceId, File[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
public ArchivoAdapter(Context context, int layoutResourceId, List<File> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = listToArray(data);
}
public Integer getDataPos(String nombre){
for (Integer i=0;i<data.length;i++)
if (data[i].getName().compareTo(nombre)==0)
return i;
return 0;
}
public void setItemsSeleccionados(Map<Integer,Boolean> mapa){
this.itemsSeleccionados=mapa;
}
public File[] getData()
{
return this.data;
}

public static File[] listToArray(List<File> data){
File[] listaAux= new File[data.size()];
Integer i=0;
for (File elemento:data){
listaAux[i]=elemento;
i++;
}
return listaAux;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ElementoHolder holder = null;
//row=null;
//if(row == null)
//{
holder = new ElementoHolder();
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);

holder.imgIconView = (ImageView)row.findViewById(R.id.imgIconFolder);
holder.rutaIconFolder = (TextView)row.findViewById(R.id.txtRutaArchivoItem );
row.setTag(holder);

row.setBackgroundResource(!itemsSeleccionados.get( position)?R.drawable.gradient_bg:R.drawable.gradie nt_bg_hover);
//}
/* else
{
holder = (ElementoHolder)row.getTag();
}*/

File file = data[position];

holder.imgIconView.setImageResource(file.isDirecto ry()?R.drawable.folder:R.drawable.text);
holder.rutaIconFolder.setText(file.getName());

return row;
}
static class ElementoHolder
{
ImageView imgIconView;
TextView rutaIconFolder;

}
}

espero que si alguien tuvo este problema, lo solucione , y si no que contacte conmigo. Un saludo!! Gracias por la respuesta!!!