简体   繁体   English

BaseAdapter选择项目和处理问题

[英]BaseAdapter selecting item and processing issue

I have a ListView which extends BaseAdapter . 我有一个扩展BaseAdapterListView I have a data[] array. 我有一个data []数组。 The ListView inflates and populates correctly. ListView正确地膨胀和填充。 What I am trying to do is make a ImageView visible on the list item (basically a check image on the right side of the inflated view) when the user selects the item and if there was a previous item selected, I just hide that ImageView . 我想要做的是当用户选择项目时,在列表项目上显示一个ImageView (基本上是膨胀视图右侧的检查图像),如果选择了上一个项目,我只是隐藏了ImageView This works fine too. 这也很好。

But after I select a new item and scroll back and forth I see weird behavior, the check image is sometimes visible in multiple list items or is hidden in the actual item that is currently selected. 但是在我选择一个新项目并来回滚动后,我看到了奇怪的行为,检查图像有时在多个列表项中可见,或隐藏在当前选中的实际项目中。 Could someone please help and explain what I am doing wrong? 有人可以帮忙解释我做错了什么吗?

I have these two lines in the onCreate method: 我在onCreate方法中有这两行:

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

and the adapter code: 和适配器代码:

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

}

But after I select a new item and scroll back and forth I see wierd behavior, the check image is sometimes visible in multiple list items or is hidden in the actual item that is currently selected. 但是在我选择一个新项目并来回滚动后,我看到了奇怪的行为,检查图像有时在多个列表项中可见,或者隐藏在当前选中的实际项目中。

That's most likely happening because of the way you set the click listener for convertView . 由于您为convertView设置单击侦听器的方式,这很可能发生。 You set the OnCLickListener only for the case when convertView is null but as you scroll the ListView up and down, rows will get recycled and you would end up with the same listener as other rows. 您只为convertViewnull时的情况设置OnCLickListener ,但是当您向上和向下滚动ListView时,行将被回收,您最终将获得与其他行相同的侦听器。

Anyway if you just want to have only one row with the image visible there is a much simpler way to do it. 无论如何,如果你只想让一行显示图像,那么有一种更简单的方法。 First of all you should drop the OnCLickListener on the convertView and use the OnItemClickListener on your ListView element. 首先,您应该在convertView上删除OnCLickListener ,并在ListView元素上使用OnItemClickListener From this listener callback you'll modify the rows: 从这个监听器回调你将修改行:

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

Then modify the adapter like this: 然后像这样修改适配器:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM