Android:动态更改Listview中的图像

14

我有一个由以下XML定义的列表视图。 我需要在运行时切换列表中的图像,当用户单击任何行时。 我该如何实现这一点? 非常感谢任何帮助。 谢谢

//list_item.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/play" 
android:id="@+id/img"
/> 
<TextView 
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:id="@+id/txt"
/>
</LinearLayout>
5个回答

20

你可以通过在onItemClick处理程序中调用第二个参数(即被点击项的View)上的findViewById来定位该项的img视图:

public void onItemClick(AdapterView parentView, View clickedItemView, int pos, long id)
{
    ImageView imageView = (ImageView) clickedItemView.findViewById(R.id.img);
    // ...
}

编辑:请注意,Android会重用列表项View对象(也称为视图回收),因此每个项目的切换状态需要存储以供后续使用。当将列表项视图绑定到列表项进行显示时,需要访问每个项目的切换状态。

例如,以下是一个在单击时切换每个项目图像的活动的工作示例:

import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;

public class SO4539968TestCaseActivity extends Activity {
    private static final List<String> ITEM_TEXTS = Arrays.asList(new String[] {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"});

    private boolean[] itemToggled;

    private class MyArrayAdapter<T> extends ArrayAdapter<T>
    {
        public MyArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects) {
            super(context, resource, textViewResourceId, objects);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View itemView = super.getView(position, convertView, parent);
            ImageView imageView = (ImageView) itemView.findViewById(R.id.img);
            imageView.setImageResource(itemToggled[position] ? R.drawable.on : R.drawable.off);
            return itemView;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        itemToggled = new boolean[ITEM_TEXTS.size()];
        Arrays.fill(itemToggled, false);

        ListView listView = (ListView) findViewById(R.id.list_view0);
        listView.setAdapter(new MyArrayAdapter<String>(this, R.layout.list_item, R.id.txt, ITEM_TEXTS));
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> listView, View itemView, int position, long id) {
                itemToggled[position] = ! itemToggled[position];

                ImageView imageView = (ImageView) itemView.findViewById(R.id.img);
                imageView.setImageResource(itemToggled[position] ? R.drawable.on : R.drawable.off);
            }
        });
    }
}

重要的部分是研究onItemClick回调和在MyArrayAdapter中覆盖getView方法。 Adapter类的getView方法负责膨胀项目布局。在本例中,我调用超类的getView方法来初始化准备项目视图,但然后我确保适当地设置项目的img视图的资源ID:
imageView.setImageResource(itemToggled[position] ? R.drawable.on : R.drawable.off);

参见:为Android开发应用程序-陷阱和怪癖


1
@Vivek:听起来像是视图重用的问题。请查看我的更新答案,因为我已经添加了一个可工作的示例,并链接到了一篇描述Android视图回收的优秀博客文章。 - Daniel Trebbien
@Panache:我不确定你在问什么。你是想只显示一个“选中”的行吗?也就是说,如果项目1被“选中”,那么点击项目2会选择该项目并取消选择项目1吗? - Daniel Trebbien
1
@Panache:代码非常相似。你可以使用一个int成员变量来存储“选中”项的位置,而不是使用itemToggled数组。然后,在onItemClick(或者如果使用ListActivity,则是onListItemClick)中,更新int成员变量并在列表视图的MyArrayAdapter<String>实例上调用notifyDataSetInvalidated()。如果需要,我有可用的工作代码。只需提出一个新问题,我就会发布它。 - Daniel Trebbien
大家好,我面临着相同的问题。我尝试了这个答案,但在itemtoggled数组中出现了null指针异常。你们能否帮助我提供一个基于我的stackoverflow问题的示例答案呢?http://stackoverflow.com/questions/17404273/listview-odd-even-rows-refresh-automatically-when-scrolling-down-or-selecting-an。谢谢和问候。 - Dimitri
@Dimitri:我不确定为什么itemToggled会为空。你能再次确认一下成员变量是否在onCreate()方法中初始化了吗?如果你更新新问题并包含涉及适应此itemToggled数组解决方案的完整代码,我可以帮你看一下。 - Daniel Trebbien
显示剩余5条评论

14
    listview.setOnItemClickListener(new AdapterView.OnItemClickListener(){

        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            ImageView imageView=arg1.findViewById(R.id.img);
            imageView.setImageResource(R.drawable.new_image);

        }

    });

没关系。我很感激你的努力。 - Vivek

1
我将动态生成ListView,然后绑定到onclickitem事件,以便按照“Kiril Kirilov”的说法进行setimageresource。

0

这可以很容易地完成,您只需要查看用户单击的列表项位置。下面是一个完整的演示代码:

 public class ChangeImageInListDynamically extends Activity {
/**
 * Adapter for your data. 
 */
ImageAdapter adpAR;
ArrayList<String> itemList;
ListView mListView;
ImageAdapter mAdapter;

/**
 * Indicate which item is currently selected.  
 * Its default selected item is '0' e.g., 1st item. 
 */
private int selectedPosition=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    itemList = new ArrayList<String>();
    for (int i = 0; i < 11; i++) {
        itemList.add("Item - "+i);
    }

    mListView = (ListView)findViewById(R.id.data_list);

    //Initialize your adapter
    mAdapter = new ImageAdapter(nChangeImageInListDynamically.this, itemList);

    //set adapter to your list.
    mListView.setAdapter(mAdapter);

    //set list click listener.
    mListView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> av, View view, int position, long id) {
            //your image that need to change dynamically.
            ImageView imageView = (ImageView) view.findViewById(R.id.select);

            //position of clicked item.  
            selectedPosition=position;

            //change image of respective image.
            imageView.setImageResource(R.drawable.selected);

            //notify your adapter to update your list.  
            adpAR.notifyDataSetChanged();
        }
    });

}

static class ViewHolder {
    TextView title;
    ImageView img;                  
}   

/**
 * Your ImageAdapter.
 */
public class ImageAdapter extends BaseAdapter {

    ArrayList<String> dataList;
    Context context;

    public ImageAdapter(Context context, ArrayList<String> arrayList) {
        this.context = context;
        this.dataList = arrayList;

    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;

        final ViewHolder holder;
        Log.d("posiiton ImageAdapater : ",""+position);
        if (row == null) { 
            LayoutInflater inflater = ChangeImageInListDynamically.this.getLayoutInflater();
            row = inflater.inflate(R.layout.listrow, null);

            holder = new ViewHolder();
            holder.title = (TextView) row.findViewById(R.id.text);
            holder.img = (ImageView) row.findViewById(R.id.select);
            row.setTag(holder);
        } else {
            holder = (ViewHolder) row.getTag();
        }

        //set titel text.
        holder.title.setText(dataList.get(position));

        //Change Image of selected item dynamically.
             if(selectedPosition == position) {
                 //Item is selected.
                 holder.img.setImageResource(R.drawable.selected);

             }else{
                 //Other non-selected items.
                 holder.img.setImageResource(R.drawable.dis_selected);

             }

        return row;

    }

 }

}

希望这对大家有所帮助 :)


-1

使用

public void setImageResource (int resId);

ImageView类的方法。

P.S. 我之前的回答似乎不完整,这里是完整解决方案:

ImageView imageView = (ImageView) this.findViewById(R.id.img);
                ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();
                imageView.setImageResource(R.drawable.new_image);
                imageView.invalidate();

这里的问题是获取ImageView。我该如何从ListView中获取相应的ImageView?当我在OnListItemClick方法中执行**ImageView iv = (ImageView) view;**时,会出现类转换异常。 - Vivek
这个行不行 - ImageView imageView = (ImageView) this.findViewById(R.id.img); - Kiril Kirilov
1
不行。因为,假设我的列表视图中有40行,所有的图像都将具有相同的ID(即img)。因此,我们无法使用唯一ID获取所选ImageView的句柄。 - Vivek
ImageView的ID是R.id.img,但可绘制对象的ID可以是不同的,例如R.drawable.image1、R.drawable.image2... - Kiril Kirilov
是的。如果我更改与R.id.img对应的图像源,那么我的整个列表中的所有行都会受到影响,对吗?但是我只想更改其中一行的图像。 - Vivek
抱歉我误解了!如果没有你初始化整个列表的原始来源,我无法帮助你。 - Kiril Kirilov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接