Изменение фона ListView – странное поведение

У меня проблема с изменением фона представления в ListView.

Что мне нужно:
Измените фоновое изображение строки onClick ()

Что на самом деле происходит:
Фон будет изменен (выбран) после нажатия, например, первой записи. Но после прокрутки также выбирается восьмая запись. Прокрутите страницу вверх, а первая больше не будет выбрана. Теперь будет выбрана вторая запись. Продолжайте прокручивать, и он продолжает прыгать …

Что я дон в коде:
У меня есть каналы, а onClick () я переключаю атрибут выбранного логического канала, а затем меняю фон. Я делаю это только onClick (), поэтому я не понимаю, почему это происходит на других записях. Одна вещь, которую я замечаю: это, по-видимому, только «рисование» – часть, потому что элемент, который выбирается «сам», имеет все еще выбранное значение на false

Я думаю, что это как-то связано с повторным использованием представлений в пользовательских ListAdapters getView (…)

Код onClick () в 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; } 

Код 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; } 

Я действительно был бы признателен за любую идею, как решить эту проблему! 🙂

Если вам нужна дополнительная информация, пожалуйста, скажите мне.

Заранее спасибо!

Solutions Collecting From Web of "Изменение фона ListView – странное поведение"

Позвольте мне показать вам код, который я использую для каждого ListView и правильно контролировать событие click для изменения фона и делать что-либо еще

 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; } } 

Officelistitemlayout.xml файл будет выглядеть следующим образом: add drawable и спроектируйте его в соответствии с вашим кодом в 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> 

Надеюсь, это поможет 🙂