2011-11-10 9 views
7

Le mie righe contengono un pulsante che ha il proprio listener di clic impostato nel getView del mio adattatore. Sono in grado di distinguere tra i clic sui miei pulsanti e i clic effettivi delle righe utilizzando Android: descendantFocusability = "blocksDescendants" nel parent della riga.Android: pulsante Cambia sfondo in ListView Row con onClick

Quando faccio clic su un pulsante, esso imposta correttamente lo sfondo del pulsante, il mio problema è che mentre scorro l'elenco lo imposto anche per righe diverse. Presumo che il loro sia un problema da qualche parte con il riciclaggio delle visualizzazioni.

Ecco il mio codice:

@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); 

} 

Quindi, se clicco sul pulsante in posizione di riga 1 lo sfondo del pulsante cambia come dovrebbe. Ma poi mentre scorro verso il basso la lista casuale vengono impostati anche altri pulsanti. A volte, quando ritorna alla posizione 1, lo sfondo del pulsante ritorna di nuovo all'originale.

Cosa mi manca qui? So che sono proprio qui, è solo qualcosa di minore che non sto facendo.

+0

Quando si passa a if (true || convertView == null) {... (quindi è sempre gonfiato), funziona bene allora? Non una soluzione, voglio solo sapere se il problema non appare più. –

+0

Sì, che impedisce lo sfondo di cambiare su altre righe casuali. Ovviamente non è la soluzione come hai detto tu, ma sì, si ferma il problema finché non faccio scorrere il backup e il pulsante ritorna allo sfondo originale. – askilondz

risposta

8

Sì, hai ragione, le viste sono riciclate. Dovrai tenere traccia delle posizioni su cui è stato fatto clic e aggiornare la risorsa di background nel tuo metodo getView. Per esempio, ho esteso il codice per aggiungere sfondo conversazione alternata:

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

Perfetto grazie! Ho appena dovuto cambiare lo 0 in setBackgroundResource (0) all'altro mio drawable e tutto funziona come previsto. Grazie mille! – askilondz

+0

@Chase, per favore aiutatemi http://stackoverflow.com/questions/17482001/change-imageview-backgroundresource-in-listview-onitemselected-android – yakusha

+0

Amico, mi risparmi la vita – 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

Potresti anche aggiungere una spiegazione? – Robert

1

ho trovato una soluzione perfetta, corte e pulite per questo utilizzo 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; 
} 

Questo funziona ancora perfetto insieme OnClickListener dove puoi fare le tue cose importanti.