自定义 ListView 适配器,奇怪的 ImageView 行为 [英] Custom ListView adapter, strange ImageView behavior

查看:30
本文介绍了自定义 ListView 适配器,奇怪的 ImageView 行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义的 ListView Adapter,我正在使用它为列表创建行.我的问题是,它似乎并没有将 ImageView 彼此区分开来.当我上下滚动时,它似乎是随机选择 ImageViews 来卡入到位.文本信息(从该片段中省略)不会中断.它按预期工作.

I have a custom ListView Adapter, with which I'm creating rows for a list. My problem is though, that it doesn't seem to be distinguishing the ImageViews, from each other. It seems to be randomly picking ImageViews to chuck into place as I scroll up and down. The text information (omitted from this snippet) does not break. It works as one would expect.

这里是我的Adapter的相关方法:

Here is the relevant method of my Adapter:

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

    if( v == null )
    {
      LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      v = vi.inflate( R.layout.generic_row, null );
    }

    // find the image
    ImageView favImage = (ImageView)v.findViewById( R.id.toggle_favorite );

   // when clicked...
   favImage.setOnClickListener( new OnClickListener() {

     @Override
     public void onClick( View v )
     {
       // make the gray star a yellow one
       int newImage = R.drawable.ic_star_yellow_embossed;
       ((ImageView)v).setImageBitmap(BitmapFactory.decodeResource(getContext().getResources(), newImage));
     }

   });

  return v;
  }

推荐答案

出现这种行为是因为 ListView 在您上下滚动列表时回收行视图,因此您会得到行由用户(图像已更改)在位置上操作的图像不应被修改.为避免这种情况,您必须以某种方式为列表中的每一行保存 ImageView 的状态,并使用此状态在 getView() 中设置正确的图像方法.因为您没有说明具体是如何实现适配器的,所以我将向您展示一个简单的示例.

That behavior appears because the ListView recycles the row views as you scroll the list up and down, and because of this you get rows that were acted on by the user(the image was changed) in position were the image should be unmodified. To avoid this you'll have to somehow hold the status of the ImageView for every row in the list and use this status to set up the correct image in the getView() method. Because you didn't say how exactly did you implement your adapter I will show you a simple example.

首先,您应该存储 ImageView 的状态.我使用了一个 ArrayList 作为自定义适配器的成员,如果这个列表中的位置(对应于列表中的行的位置)是 false 那么图像是默认的,否则如果它是 true 则用户点击它,我们应该放置新图像:

First of all you should store your the statuses of the ImageView. I used an ArrayList<Boolean> as a member of the custom adapter, if the position(corresponding to the row's position in the list) in this list is false then the image is the default one, otherwise if it is true then the user clicked it and we should put the new image:

private ArrayList<Boolean> imageStatus = new ArrayList<Boolean>();

在您的自定义适配器构造函数中初始化此列表.例如,如果您在适配器中放入了一个列表,那么您应该使 imageStatus 与该列表一样大并填充 false(默认/启动状态):

In your custom adapter constructor initialize this list. For example if you put in your adapter a list of something then you should make your imageStatus as big as that list and filled with false(the default/start status):

//... initialize the imageStatus, objects is the list on which your adapter is based
for (int i = 0; i < objects.size(); i++) {
    imageStatus.add(false);
}

然后在您的 getView() 方法中:

Then in your getView() method:

View v = convertView;

            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getContext()
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.adapters_adapter_with_images, null);
            }

            // find the image
            ImageView favImage = (ImageView) v
                    .findViewById(R.id.toggle_favorite);
            // Set the image bitmap. If the imageStatus flag for this position is TRUE then we
            // show the new image because it was previously clicked by the user
            if (imageStatus.get(position)) {
                int newImage = R.drawable.ic_star_yellow_embossed;
                favImage.setImageBitmap(BitmapFactory.decodeResource(
                        getContext().getResources(), newImage));
            } else {
                // If the imageStatus is FALSE then we explicitly set the image
                // back to the default because we could be dealing with a
                // recycled ImageView that has the new image set(there is no need to set a default drawable in the xml layout)                                       
                int newImage = R.drawable.basket_empty; //the default image
                favImage.setImageBitmap(BitmapFactory.decodeResource(
                        getContext().getResources(), newImage));
            }
            // when clicked... we get the real position of the row and set to TRUE
            // that position in the imageStatus flags list. We also call notifyDataSetChanged
            //on the adapter object to let it know that something has changed and to update!
            favImage.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    Integer realPosition = (Integer) v.getTag(); //get the position from the view's tag
                    imageStatus.set(realPosition, true); //this position has been clicked be the user
                    adapter.notifyDataSetChanged(); //notify the adapter
                }

            });
            // set the position to the favImage as a tag, we later retrieve it
            // in the onClick method
            favImage.setTag(new Integer(position));
            return v;

        }

如果您不打算动态修改列表(删除/添加行),这应该很有效,否则您还必须注意修改 imageStatus 的列表以反映变化.您没有说您的行数据是什么,另一种方法(如果您打算在用户单击该图像时执行某些操作(除了更改它),则是正确的方法)是将图像的状态合并到行的数据模型中.关于这一点,这里有一些教程:

This should work well if you don't plan to dynamically modify the list(remove/add rows), otherwise you'll have to take care of also modifying that list of imageStatus to reflect the changes. You didn't say what was your row data, another approach(and the right one if you plan to do something if the user clicks that image(besides changing it)) is to incorporate the status of the image in the row's data model. Regarding this here are some tutorials:

Android ListView 高级交互Commonsware-Android 摘录(交互式行)

这篇关于自定义 ListView 适配器,奇怪的 ImageView 行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆