【问题标题】:Android: Dynamically change Image in ListviewAndroid:动态更改列表视图中的图像
【发布时间】:2010-12-27 16:07:13
【问题描述】:

我有一个由以下 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>

【问题讨论】:

    标签: android listview


    【解决方案1】:

    您可以通过在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 回调和getViewMyArrayAdapter 中的覆盖。

    Adapter 类的getView 方法负责膨胀项目布局。在这个例子中,我调用超类的getView 方法来初步准备项目视图,但随后我确保适当地设置项目的img 视图的资源ID:

    imageView.setImageResource(itemToggled[position] ? R.drawable.on : R.drawable.off);
    

    另请参阅:Developing Applications for Android – Gotchas and Quirks

    【讨论】:

    • 非常感谢。它对我有用。我一直在寻找这个解决方案,大约一个月。你救了我:D
    • 现在,我可以更改 Imageview 的来源,但是当我向下滚动并再次返回时,imageview 会重置回其先前的来源。为什么会这样?你能帮帮我吗?
    • @Vivek:听起来像是视图重用问题。请查看我更新的答案,因为我添加了一个工作示例并链接到一篇描述 Android 的视图回收的优秀博客文章。
    • @Daniel Trebbien 非常感谢。这对我来说就像魔术一样..我将它用于我的图像视图,我希望它的行为类似于单选按钮.. 那么如何在项目单击时将其他选定的切换设置为未选中?请告诉我一个实现这一目标的方法..
    • @Panache:代码非常相似。您将使用int 成员来存储“选定”项的位置,而不是itemToggled 数组。然后,在onItemClick(或onListItemClick,如果使用ListActivity)内部,更新int 成员并在列表视图的MyArrayAdapter&lt;String&gt; 实例上调用notifyDataSetInvalidated()。如果您需要,我有工作代码。只要提出一个新问题,我就会发布它。
    【解决方案2】:
        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);
    
            }
    
        });
    

    【讨论】:

    • 没关系。感谢您的努力。
    • 非常感谢您的回复。您的解决方案对我很有帮助。
    【解决方案3】:

    我将动态生成列表视图,然后绑定到 onclickitem 事件,以便按照“Kiril Kirilov”的说法执行 setimageresource。

    【讨论】:

      【解决方案4】:

      这很容易做到,您只需要查看用户单击的列表项的位置即可。一个描述良好的完整演示代码如下_

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

      我希望这对所有人都有帮助:)

      【讨论】:

        【解决方案5】:

        使用

        public void setImageResource (int resId);
        

        ImageView 类的方法。

        附:我之前的答案似乎不完整,这是整个解决方案:

        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; 时,我得到了类转换异常。
        • 这个工作 - ImageView imageView = (ImageView) this.findViewById(R.id.img);
        • 没有。因为,假设如果我的列表视图中有 40 行,所有图像都将拥有相同的 ID(即 img)。所以我们无法获得具有唯一 ID 的选定 ImageView 的句柄。
        • ImageView ID 为 R.id.img,但可绘制对象可以具有不同的 ID,例如 R.drawable.image1、R.drawable.image2...
        • 是的。因此,如果我更改与 R.id.img 对应的图像的来源,我列表中的所有行都会受到影响,对吗?但我只想在一行中更改图像..
        猜你喜欢
        • 2012-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多