BaseAdapter выбор элемента и проблема обработки


У меня есть ListView, который расширяет BaseAdapter. У меня есть массив данных []. ListView раздувается и заселяется правильно. То, что я пытаюсь сделать, - это сделать ImageView видимым на элементе списка (в основном изображение проверки в правой части раздутого представления), когда пользователь выбирает элемент, и если был выбран предыдущий элемент, я просто скрываю этот ImageView. Это тоже прекрасно работает.

Но после того, как я выбираю новый элемент и прокручиваю назад и вперед, я вижу странное поведение, изображение проверки иногда видно в нескольких элементы списка или скрыт в фактическом элементе, который в данный момент выбран. Не мог бы кто-нибудь помочь и объяснить, что я делаю не так?

У меня есть эти две строки в методе onCreate:

    adap = new EfficientAdapter(this);
    lstview.setAdapter(adap);

И код адаптера:

public static class EfficientAdapter extends BaseAdapter implements Filterable {
  private LayoutInflater mInflater;
  private Context context;
  private ImageView CurrentSelectedImageView;
  private Integer CurrentPosition = 14;


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


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

    ViewHolder holder;

    //Log.e("TAG",String.valueOf(position));

    if (convertView == null) {
      convertView = mInflater.inflate(R.layout.adaptor_content, null);

      holder = new ViewHolder();
      holder.textLine = (TextView) convertView.findViewById(R.id.txtCategoryCaption);
      holder.iconLine = (ImageView) convertView.findViewById(R.id.iconLine);
      holder.imgCheckbox = (ImageView) convertView.findViewById(R.id.imgCheck);


      //If the CurrentPosition == position then make the checkbox visible else dont.
      if (CurrentPosition == position){

        holder.imgCheckbox.setVisibility(View.VISIBLE);
      }else{
        holder.imgCheckbox.setVisibility(View.INVISIBLE);
      }


      final ImageView Checkbox = holder.imgCheckbox;

      //Now if the list item is clicked then set the position as the current item and make the checkbox visible.

      convertView.setOnClickListener(new OnClickListener() {
        private int pos = position;

        @Override
        public void onClick(View v) {
            if (CurrentSelectedImageView!=null){
                CurrentSelectedImageView.setVisibility(View.INVISIBLE);
            }
            Checkbox.setVisibility(View.VISIBLE);
            CurrentSelectedImageView = Checkbox;
            CurrentPosition = pos;

        }
      });

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


        int id = context.getResources().getIdentifier("nodeinsert", "drawable", context.getString(R.string.package_str));
        if (id != 0x0) {
          mIcon1 = BitmapFactory.decodeResource(context.getResources(), id);
        }

        holder.iconLine.setImageBitmap(mIcon1);
        holder.textLine.setText(String.valueOf(data[position]));


    if (CurrentPosition == position){
        Log.e("TAG",CurrentPosition + "---" + String.valueOf(position));
        holder.imgCheckbox.setVisibility(View.VISIBLE);
    }else{
        holder.imgCheckbox.setVisibility(View.INVISIBLE);
    }


    return convertView;
  }



  static class ViewHolder {
    TextView textLine;
    ImageView iconLine;
    ImageView imgCheckbox;
  }

  @Override
  public Filter getFilter() {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public long getItemId(int position) {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public int getCount() {
    // TODO Auto-generated method stub
    return data.length;
  }

  @Override
  public Object getItem(int position) {
    // TODO Auto-generated method stub
    return data[position];
  }

}
1 3

1 ответ:

Но после того, как я выбираю новый элемент и прокручиваю его вперед и назад, я вижу wierd поведение, изображение проверки иногда видно в нескольких элементах списка или скрыт в фактическом элементе, который в данный момент выбран.

Это, скорее всего, происходит из-за того, как вы устанавливаете прослушиватель кликов для convertView. Вы устанавливаете OnCLickListener только для случая, когда convertView является null, но при прокрутке ListView вверх и вниз, строки будут переработаны, и вы получите тот же слушатель, что и другие строки.

В любом случае, если вы просто хотите иметь только одну строку с видимым изображением, есть гораздо более простой способ сделать это. Прежде всего, вы должны отбросить OnCLickListener на convertView и использовать OnItemClickListener на вашем элементе ListView. Из этого обратного вызова слушателя вы измените строки:
lstview.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> l, View v, int position,
                    long id) {
                View oldView = l.getChildAt(adap.getSelectedPosition());
                ImageView img;
                if (oldView != null && adap.getSelectedPosition() != -1) {
                    img = (ImageView) oldView.findViewById(R.id.imageView1);
                    img.setVisibility(View.INVISIBLE);
                }
                img = (ImageView) v.findViewById(R.id.imageView1);
                img.setVisibility(View.VISIBLE);
                adap.setSelectedPosition(position);
            }
        });

Затем измените адаптер следующим образом:

// a field in the adapter
private int mSelectedPosition = -1;

// getter and setter methods for the field above
public void setSelectedPosition(int selectedPosition) {
    mSelectedPosition = selectedPosition;
    notifyDataSetChanged();
}

public int getSelectedPosition() {
    return mSelectedPosition;
}

// and finally your getView() method
public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
      convertView = mInflater.inflate(R.layout.adaptor_content, parent, false);
      holder = new ViewHolder();
      holder.textLine = (TextView) convertView.findViewById(R.id.txtCategoryCaption);
      holder.iconLine = (ImageView) convertView.findViewById(R.id.iconLine);
      holder.imgCheckbox = (ImageView) convertView.findViewById(R.id.imgCheck);
      convertView.setTag(holder);
    } else {
      holder = (ViewHolder) convertView.getTag();
    }
    if (mSelectedPosition == position) {
    holder.imgCheckbox.setVisibility(View.VISIBLE);
    } else {
    holder.imgCheckbox.setVisibility(View.INVISIBLE);
    }     
      // what is the point of this call?!
      // you should move this to another place(like the adapter's constructor), the getIdentifier()
      // method is a bit slow and you call it each time the adapter calls getView()
      // you should never use it in the getView() method(), especially as all you do is get the id of the same drawable again and again
      int id = context.getResources().getIdentifier("nodeinsert", "drawable", context.getString(R.string.package_str));
      // ?!?
      if (id != 0x0) {
          mIcon1 = BitmapFactory.decodeResource(context.getResources(), id);
      }
      holder.iconLine.setImageBitmap(mIcon1);
      holder.textLine.setText(String.valueOf(data[position]));
      return convertView;
}