2011-11-10 11 views
7

Moje wiersze zawierają przycisk, który ma własny odbiornik kliknięć ustawiony w funkcji getView mojego adaptera. Rozróżniam kliknięcia przycisków i faktyczne kliknięcia elementów wiersza przy użyciu Androida: descendantFocusability = "blocksDescendants" w rodzicu wiersza.Android: Zmień tło przycisku w wierszu ListView z onClick

Po kliknięciu przycisku ustawia on prawidłowo tło przycisku, moim problemem jest to, że przewijam listę, ustawiając go również dla różnych wierszy. Zakładam, że jest to problem związany z recyklingiem widoków.

Oto mój kod:

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

} 

Więc jeśli kliknięciu na przycisk w pozycji rzędu 1 przycisk zmiany tła, jak powinien. Ale kiedy przewijam listę losowo, inne przyciski również się ustawiają. Czasami, gdy przewijam z powrotem do pozycji 1, tło przycisku powraca do oryginału.

Czego mi tu brakuje? Wiem, że mam rację, to jest coś małego, czego nie robię.

+0

Po zmianie na jeśli (true || convertView == null) {... (więc zawsze jest zawyżone), czy to działa dobrze? Nie jest to rozwiązanie, ale chcesz się dowiedzieć, czy problem nie pojawia się już wtedy. –

+0

Tak, to powoduje, że tło nie zmienia się w innych losowych wierszach. Oczywiście nie takie rozwiązanie, jak mówiłaś, ale tak, zatrzymaj problem, dopóki nie przewiń do góry, a przycisk powróci do pierwotnego tła. – askilondz

Odpowiedz

8

Tak, masz rację, widoki są ponownie przetwarzane. Będziesz musiał sprawdzić, które pozycje zostały kliknięte i zaktualizować zasób tła w swojej metodzie getView. Na przykład, rozszerzony kod, aby dodać tło przełączanie:

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

Doskonałe dzięki! Właśnie musiałem zmienić 0 w setBackgroundResource (0) na mój inny drawable i wszystko działa zgodnie z przeznaczeniem. Dzięki za tonę! – askilondz

+0

@Chase pomóż mi http://stackoverflow.com/questions/17482001/change-imageview-backgroundresource-in-listview-onitemselected-android – yakusha

+0

Dude, uratujesz mi życie – 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

Czy możesz również dodać wyjaśnienie? – Robert

1

znalazłam idealny, krótkie i czyste rozwiązanie tego używając 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; 
} 

Działa to nadal doskonały wraz z OnClickListener gdzie możesz zrobić swoje ważne rzeczy.

Powiązane problemy