2011-01-03 14 views
7

Ho un problema con la modifica dello sfondo di una vista in un controllo ListView.Cambia sfondo ListView - comportamento strano

Che cosa ho bisogno:
cambiare l'immagine di una fila onClick()

Cosa succede in realtà di fondo:
Lo sfondo viene cambiato (selezionato) dopo aver premuto per esempio la prima voce. Ma dopo lo scorrimento verso il basso, viene selezionata anche l'8a voce. Per tornare all'inizio, il primo non è più selezionato. La seconda voce è ora selezionata. continuare a scorrere e continua il salto ...

quello che sto dong del Codice:
ho canali, e onClick() i Spostare un attributo di canale booleano selezionato e poi cambio lo sfondo. Sto facendo questo solo onClick() questo è il motivo per cui non capisco perché sta accadendo concretamente anche su altre voci. una cosa che le comunicazioni è: Sembra essere solo la -parte "disegno" perché l'elemento che vengono selezionati "da essa sé" ha ancora il selezionato valore su falsa

Penso che sembra avere qualcosa a che fare con il riutilizzo delle viste nella ListAdapters personalizzati GetView (...)

Codice di onClick() in ListActivity:

@Override 
    protected ViewHolder createHolder(View v) { 

     // createHolder will be called only as long, as the ListView is not 
     // filled 

     TextView title = (TextView) v 
       .findViewById(R.id.tv_title_channel_list_adapter); 
     TextView content = (TextView) v 
       .findViewById(R.id.tv_content_channel_list_adapter); 

     ImageView icon = (ImageView) v 
       .findViewById(R.id.icon_channel_list_adapter); 

     if (title == null || content == null || icon == null) { 
      Log.e("ERROR on findViewById", 
        "Couldn't find Title, Content or Icon"); 
     } 
     ViewHolder mvh = new MyViewHolder(title, content, icon); 

     // We make the views become clickable 
     // so, it is not necessary to use the android:clickable attribute in 
     // XML 

     v.setOnClickListener(new ChannelListAdapter.OnClickListener(mvh) { 

      public void onClick(View v, ViewHolder viewHolder) { 
       // we toggle the enabled state and also switch the the 
       // background 
       MyViewHolder mvh = (MyViewHolder) viewHolder; 
       Channel ch = (Channel) mvh.data; 
       ch.setSelected(!ch.getSelected()); // toggle 

       if (ch.getSelected()) { 
        v.setBackgroundResource(R.drawable.row_blue_selected); 
       } else { 
        v.setBackgroundResource(R.drawable.row_blue); 
       } 
       // TESTING 
       Log.d("onClick() Channel", "onClick() Channel: " 
         + ch.getTitle() + " selected: " + ch.getSelected()); 
      } 
     }); 
return mvh; 
    } 

Codice di GetView (...):

@Override 
public View getView(int position, View view, ViewGroup parent) { 
    ViewHolder holder; 

    // When view is not null, we can reuse it directly, there is no need 
    // to reinflate it. 
    // We only inflate a new View when the view supplied by ListView is 
    // null. 
    if (view == null) { 
     view = mInflater.inflate(mViewId, null); 

     // call own implementation 
     holder = createHolder(view); 

     // TEST 
     // we set the holder as tag 
     view.setTag(holder); 

    } else { 
     // get holder back...much faster than inflate 
     holder = (ViewHolder) view.getTag(); 
    } 

    // we must update the object's reference 
    holder.data = getItem(position); 

      // <EDIT SOLUTION> 

    if(getItem(position).get_id() == channelList.get(position).get_id()){ 
     if(getItem(position).getSelected()) 
     { 
      view.setBackgroundResource(R.drawable.row_blue_selected); 
     } 
     else{ 
      view.setBackgroundResource(R.drawable.row_blue); 
     } 
    } 

      // </EDIT SOLUTION> 

    // call the own implementation 
    bindHolder(holder); 

    return view; 
} 

davvero Gradirei qualsiasi idea di come risolvere questo problema! :)

Se sono necessarie ulteriori informazioni, mi dica.

Grazie in anticipo!

risposta

10

Lascia che ti mostri il codice che uso per ogni ListView e controllare adeguatamente l'evento click per cambiare lo sfondo e fare qualcosa di più

public class Offices extends Activity { 

    private ListView listView; 

    /* selectedListItem will contain the number of items to be selected. 
    * Your list item OnOlickListener will simply change this variable 
    * to the position of the clicked item. The Adapter will do the rest 
    * because you need to refresh the ListView. 
    */ 
    private int selectedListItem = -1; 
    private Handler mHandler = new Handler(); 
    private Vector<String> data; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.officeslayout); 
     data = new Vector<String>(); 

     // Add data as per your requirement 
     data.add("one"); 
     data.add("two"); 
     data.add("three"); 
     data.add("four"); 
     data.add("Five"); 
     data.add("Six"); 
     data.add("Seven"); 
     data.add("Eight"); 
     data.add("Nine"); 
     data.add("Ten"); 

     listView = (ListView)findViewById(R.id.ListView01); 
     listView.setDivider(null); 

     listView.setOnItemClickListener(new OnItemClickListener() { 
      public void onItemClick(AdapterView<?> parent, View view, 
        int position, long id) { 

       selectedListItem = position; 
       ((EfficientAdapter)listView.getAdapter()).notifyDataSetChanged(); 

       mHandler.postDelayed(new Runnable() { 

        @Override 
        public void run() { 
         // call any new activity here or do any thing you want here   

        } 
       }, 200L); 
      } 
     }); 

     listView.setAdapter(new EfficientAdapter(getApplicationContext())); 
    } 

    private class EfficientAdapter extends BaseAdapter { 
     private LayoutInflater mInflater; 

     public EfficientAdapter(Context context) { 
      mInflater = LayoutInflater.from(context); 
     } 

     public int getCount() { 
      return data.size(); 
     } 

     public Object getItem(int position) { 
      return position; 
     } 

     public long getItemId(int position) { 
      return position; 
     } 

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

      ViewHolder holder; 

      if (convertView == null || convertView.getTag() == null) { 
       convertView = mInflater.inflate(R.layout.officeslistitemlayout, null); 
       holder = new ViewHolder(); 
       holder.backgroundView = (ImageView) convertView 
        .findViewById(R.id.OfficesBackground); 
       holder.officesTitle = (TextView) convertView 
        .findViewById(R.id.OfficesName); 

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

      if(position == selectedListItem) { 
       holder.backgroundView.setBackgroundResource(R.drawable.and_gray_bg_listing_selected); 
      } else { 
       holder.backgroundView.setBackgroundResource(R.drawable.and_gray_bg_listing); 
      } 

      holder.officesTitle.setText(data.get(position)); 

      return convertView; 
     } 
    } 

    static class ViewHolder { 
     TextView officesTitle; 
     ImageView backgroundView; 
    } 

} 

file di officeslistitemlayout.xml sarà come seguire aggiungere disegnabile in base a voi mettere il seguente codice in RelativeLayout

<ImageView android:id="@+id/OfficesBackground" android:layout_width="fill_parent"  
      android:layout_height="45dip" 
      android:layout_alignParentTop="true" 
      android:background="@drawable/and_gray_bg_listing" 
      android:scaleType="fitXY" 
      ></ImageView> 


     <TextView android:id="@+id/OfficesName" android:layout_width="wrap_content" 
        android:text="Offices Name" 
        android:textColor="#000000" android:textStyle="bold" 
        android:layout_height="wrap_content" 
        android:layout_centerVertical="true" android:layout_marginLeft="5dip" 
      ></TextView> 

Spero che possa aiutare :)

+0

Ho ragione che forse è solo perché ho perso quella parte: se (posizione == selectedListItem) { holder.backgrouundView.setBackgroundResource (R.drawable.and_gray_bg_listing_selected); } altro { holder.backgrouundView.setBackgroundResource (R.drawable.and_gray_bg_listing); } ? Sono al lavoro, quindi non posso provarlo ... ma lo farò non appena sarò a casa. Grazie mille :) – Beasly

+1

Sì, devi solo eseguire questo controllo nel metodo getView .. il resto verrà eseguito automaticamente – Javanator

+0

Usando questo metodo possiamo disegnare qualsiasi listview molto facilmente e possiamo controllare anche altri eventi .. Usando questo Ho anche implementato la funzionalità di eliminazione animata di iPhone TableView .. pulsante di cancellazione rosso e altre cose – Javanator