2011-11-10 22 views
7

Mis filas contienen un botón que tiene su propio oyente de clic establecido en getView de mi adaptador. Puedo distinguir entre los clics de mi botón y los clics reales de elementos de fila usando android: descenddantFocusability = "blocksDescendants" en el elemento primario de la fila.Android: cambiar el fondo del botón en la fila de ListView con onClick

Cuando hago clic en un botón, establece el fondo del botón correctamente, mi problema es que me desplazo por la lista y también lo configura para diferentes filas. Supongo que es un problema en algún lugar con el reciclaje de vistas.

Aquí está mi código:

@Override 
public View getView(int position, View convertView, ViewGroup parent){ 

    if(convertView == null){ 

     holder = new ViewHolder(); 

     convertView = inflater.inflate(R.layout.todays_sales_favorite_row, null); 
     holder.favCatBtn = (Button)convertView.findViewById(R.id.favCatBtn);    

     convertView.setTag(holder); 

    } else { 
     holder = (ViewHolder)convertView.getTag(); 
    } 

     holder.favCatBtn.setTag(position); 
     holder.favCatBtn.setOnClickListener(this); 

    return convertView; 
} 

@Override 
public void onClick(View v) { 
    int pos = (Integer) v.getTag(); 
    Log.d(TAG, "Button row pos click: " + pos); 
    RelativeLayout rl = (RelativeLayout)v.getParent(); 
    holder.favCatBtn = (Button)rl.getChildAt(0); 
    holder.favCatBtn.setBackgroundResource(R.drawable.icon_yellow_star_large); 

} 

Así que si hago clic en el botón en posición de la fila 1 los cambios botón de fondo como debería. Pero a medida que me desplazo hacia abajo en la lista, al azar se establecen otros botones. Entonces, a veces, cuando me desplazo hacia atrás a la posición 1, el fondo del botón vuelve a volver al original.

¿Qué me falta aquí? Sé que estoy allí, es solo algo menor que no estoy haciendo.

+0

Cuando cambia a if (true || convertView == null) {... (por lo que siempre está inflado), ¿funciona bien entonces? No es una solución, solo quiero saber si el problema ya no aparece. –

+0

Sí, eso evita que el fondo cambie en otras filas aleatorias. Obviamente no es la solución como dijiste, pero sí, detiene el problema hasta que retroceda y el botón vuelva a su fondo original. – askilondz

Respuesta

8

Sí, tienes razón, las vistas se reciclan. Deberá realizar un seguimiento de las posiciones en las que se ha hecho clic y actualizar el recurso de fondo en su método getView. Por ejemplo, he ampliado su código para agregar fondo alternancia:

private final boolean[] mHighlightedPositions = new boolean[NUM_OF_ITEMS]; 

@Override 
public View getView(int position, View convertView, ViewGroup parent){ 

    if(convertView == null){ 
     holder = new ViewHolder(); 
     convertView = inflater.inflate(R.layout.todays_sales_favorite_row, null); 
     holder.favCatBtn = (Button)convertView.findViewById(R.id.favCatBtn); 
     holder.favCatBtn.setOnClickListener(this); 
     convertView.setTag(holder); 
    }else { 
     holder = (ViewHolder)convertView.getTag(); 
    } 

    holder.favCatBtn.setTag(position); 

    if(mHighlightedPositions[position]) { 
     holder.favCatBtn.setBackgroundResource(R.drawable.icon_yellow_star_large); 
    }else { 
     holder.favCatBtn.setBackgroundResource(0); 
    } 

    return convertView; 
} 

@Override 
public void onClick(View view) { 
    int position = (Integer)view.getTag(); 
    Log.d(TAG, "Button row pos click: " + position); 

    // Toggle background resource 
    RelativeLayout layout = (RelativeLayout)view.getParent(); 
    Button button = (Button)layout.getChildAt(0); 
    if(mHighlightedPositions[position]) { 
     button.setBackgroundResource(0); 
     mHighlightedPositions[position] = false; 
    }else { 
     button.setBackgroundResource(R.drawable.icon_yellow_star_large); 
     mHighlightedPositions[position] = true; 
    } 
} 
+0

Perfecto gracias! Solo tuve que cambiar el 0 en setBackgroundResource (0) a mi otro drawable y todo funciona según lo previsto. ¡Gracias una tonelada! – askilondz

+0

@Chase ayúdeme por favor http://stackoverflow.com/questions/17482001/change-imageview-backgroundresource-in-listview-onitemselected-android – yakusha

+0

Amigo, me salvó la vida – Harry

-1
holder.btnUnLock.setOnClickListener(new OnClickListener() { 

    @Override 
    public void onClick(View v) { 
// TODO Auto-generated method stub 
// Button btn = Button(v); 
    holder = (ViewHolder) v.getTag(); 
    holder.btnSetLock.setBackgroundResource(R.drawable.btn_lock_bg_right); 
holder.btnUnLock.setBackgroundResource(R.drawable.btn_unlock_bg_left); 

} 
}); 
+0

¿Podría también agregar una explicación? – Robert

1

he encontrado una solución perfecta, cortas y limpias para esta usando StateListDrawable:

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    currentPosition = position; 
    holder = null; 
    if (convertView == null) { 
     holder = new Holder(); 
     LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = vi.inflate(R.layout.grid_item, null); 
     holder.imageView = (ImageView) convertView.findViewById(R.id.gridItemBtn); 

     StateListDrawable states = new StateListDrawable(); 
     states.addState(new int[] {android.R.attr.state_pressed}, 
       ContextCompat.getDrawable(context, R.drawable.pressed_state)); 
     states.addState(new int[] {android.R.attr.state_focused}, 
       ContextCompat.getDrawable(context, R.drawable.focused_state)); 
     states.addState(new int[]{}, 
       ContextCompat.getDrawable(context, R.drawable.default_state)); 
     holder.imageView.setImageDrawable(states); 
    } 

    return convertView; 
} 

Esto funciona aún perfecta junto con OnClickListener donde puedes hacer tus cosas importantes.

Cuestiones relacionadas