ListView中为每个item设置监听器(转)

转自: http://blog.csdn.net/xujk2008/article/details/10049845

最近需要给ListView写一个监听器,在按住ListView中Item不松手的时候,改变Item的样式,使得被按住的Item背景色为灰,并显示跑马灯效果。因为需要具体到每个Item,所以首先想到了OnItemClickListener。但是稍微想想就知道这样是不行的,OnItemClickListener监听的是点击某个Item的动作,点击包括按下和松开两个部分,所以不用到达想要的效果。


      于是想到用OnTouchListener监听按下的动作。但是,你知道我是会说但是的。OnTouchListener针对的是整个ListView,并没有提供被点击Item的位置参数,所以这样并不能达到改变单个Item显示效果的目的。顿时有种想掀桌的冲动,但是实验室的桌子我真的掀不动。于是去StackOverflow搜索,开始搜索不得法,没有找到想要的东西。难道老外们都不屑于问这种小白问题吗?不可能,我明明见过有人问Hello world为啥跑不出来之类的问题来着。几经变换关键词之后找到了一个和我问题很相似的提问。大概意思就是说 :“哥们儿,我原来遇到的问题和你现在遇到的这个问题贼拉想,唉呀妈呀,我告诉你咋整呗。你就自个儿写一个BaseAdapter子类,然后再getView()方法里加一个OnTouchListener就欧了,缸地好使。”之前要写跑马灯效果,所以自定义的适配器已经写过了,按照提问里说的办法加了OnTouchListener。



[java]  view plain copy
  1. package org.cdpsn.client.widget.wheel;  
  2. import java.util.List;  
  3. import java.util.Map;  
  4.   
  5. import org.cdpsn.client.R;  
  6.   
  7. import android.content.Context;  
  8. import android.graphics.Color;  
  9. import android.view.LayoutInflater;  
  10. import android.view.MotionEvent;  
  11. import android.view.View;  
  12. import android.view.ViewGroup;  
  13. import android.widget.BaseAdapter;  
  14. import android.widget.TextView;  
  15.   
  16. public class ListItemAdapter extends BaseAdapter  
  17. {  
  18.     private LayoutInflater inflater;  
  19.     private List<Map<String, Object>> items;  
  20.     private static int index = 0;  
  21.       
  22.      public ListItemAdapter(Context context, List<Map<String, Object>> items) {    
  23.             super();    
  24.             this.inflater = LayoutInflater.from(context);    
  25.             this.items = items;    
  26.         }    
  27.     public void setIndex(int selected)  
  28.     {  
  29.             index = selected;  
  30.     }  
  31.        
  32.     @Override  
  33.     public int getCount() {  
  34.         // TODO Auto-generated method stub  
  35.         return items.size();  
  36.     }  
  37.   
  38.     @Override  
  39.     public Object getItem(int position) {  
  40.         // TODO Auto-generated method stub  
  41.         return items.get(position);  
  42.     }  
  43.   
  44.     @Override  
  45.     public long getItemId(int position) {  
  46.         // TODO Auto-generated method stub  
  47.         return position;  
  48.     }  
  49.   
  50.     @Override  
  51.     public View getView(final int position, View convertView, ViewGroup parent) {  
  52.         // TODO Auto-generated method stub  
  53.           
  54.         System.out.println("Get in function getView.");  
  55.         ViewHolder holder;  
  56.         if(convertView == null)  
  57.         {  
  58.             convertView = inflater.inflate(R.layout.list_job, null);  
  59.             holder = new ViewHolder();  
  60.             holder.jobTitle = (TextView)convertView.findViewById(R.id.jobTitle);  
  61.             holder.content = (TextView)convertView.findViewById(R.id.content);  
  62.             holder.publishTimeText = (TextView)convertView.findViewById(R.id.publishTimeText);  
  63.   
  64.             convertView.setOnTouchListener(new View.OnTouchListener() {  
  65.                 @Override  
  66.                 public boolean onTouch(View view, MotionEvent motionEvent) {  
  67.   
  68.                     if(motionEvent.getAction() == MotionEvent.ACTION_DOWN)  
  69.                     {  
  70.                         System.out.println("Item" + position + "pressed.");  
  71.                         ListItemAdapter.this.setIndex(position);  
  72.                         ListItemAdapter.this.notifyDataSetChanged();  
  73.                     }  
  74.   
  75.                     return false;  
  76.                 }  
  77.             });  
  78.         }  
  79.         else  
  80.         {  
  81.             holder = (ViewHolder)convertView.getTag();  
  82.         }  
  83.   
  84.   
  85.           
  86.         if(index == position)  
  87.         {  
  88.             convertView.findViewById(R.id.content).setSelected(true);  
  89. //          convertView.setBackgroundColor(Color.rgb(196, 215, 0));  
  90.             convertView.setBackgroundColor(Color.LTGRAY);  
  91.             holder.jobTitle.setTextColor(Color.WHITE);  
  92.             holder.content.setTextColor(Color.WHITE);  
  93.             holder.publishTimeText.setTextColor(Color.WHITE);  
  94.         }  
  95.         else  
  96.         {  
  97.             convertView.findViewById(R.id.content).setSelected(false);  
  98.             convertView.setBackgroundColor(Color.WHITE);  
  99.             holder.jobTitle.setTextColor(Color.BLACK);  
  100.             holder.content.setTextColor(Color.BLACK);  
  101.             holder.publishTimeText.setTextColor(Color.BLACK);  
  102.         }  
  103.           
  104.         convertView.setTag(holder);  
  105.         holder.jobTitle.setText( (String)items.get(position).get("jobTitle") );  
  106.         holder.content.setText((String)items.get(position).get("content"));  
  107.         holder.publishTimeText.setText((String)items.get(position).get("publishTimeText"));  
  108.           
  109.         return convertView;  
  110.     }  
  111.       
  112.     private class ViewHolder {    
  113.         private TextView jobTitle;  
  114.         private TextView content;    
  115.         private TextView publishTimeText;  
  116.     }    
  117.       
  118. }  



      试着跑了一下程序,似乎是可以的。但是多试了几次之后,发现还是有问题,当按住位置靠后的Item时,被按住的子项显示的效果并没有改变,改变的是位置靠前的子项。于是去搜索了一下getView的工作机制,发现convertView并不像我想象的那么简单。在配置适配器时,getView并没有为每一个Item配备一个convertView。设想一下,假如列表中有上百个Item,同时配备这么多convertView是很浪费资源的。所以convertView其实是可以循环利用的。也就是说,随着列表向下拉,屏幕上会显示新的子项,而老的子项会移出屏幕。这是,老的子项会把convertView交给新的子项使用,节省了资源。

      再看上面的代码,只有在convertView为空时,才为convertView设置OnTouchListener监听器。这样,老的Item在移交convertView的同时,也把老的监听器移交给了新的Item。所以才会出现按住下面的子项,上面的子项变化样式的诡异情况。清楚了原理之后,把监听器的设置写在了判断convertView是否为空的程序片段的外面,代码如下


[java]  view plain copy
  1. package org.cdpsn.client.widget.wheel;  
  2.   
  3.   
  4. import java.util.List;  
  5. import java.util.Map;  
  6.   
  7. import org.cdpsn.client.R;  
  8.   
  9. import android.content.Context;  
  10. import android.graphics.Color;  
  11. import android.view.LayoutInflater;  
  12. import android.view.MotionEvent;  
  13. import android.view.View;  
  14. import android.view.ViewGroup;  
  15. import android.widget.BaseAdapter;  
  16. import android.widget.TextView;  
  17.   
  18. public class ListItemAdapter extends BaseAdapter  
  19. {  
  20.     private LayoutInflater inflater;  
  21.     private List<Map<String, Object>> items;  
  22.     private static int index = 0;  
  23.       
  24.      public ListItemAdapter(Context context, List<Map<String, Object>> items) {    
  25.             super();    
  26.             this.inflater = LayoutInflater.from(context);    
  27.             this.items = items;    
  28.         }    
  29.     public void setIndex(int selected)  
  30.     {  
  31.             index = selected;  
  32.     }  
  33.        
  34.     @Override  
  35.     public int getCount() {  
  36.         // TODO Auto-generated method stub  
  37.         return items.size();  
  38.     }  
  39.   
  40.     @Override  
  41.     public Object getItem(int position) {  
  42.         // TODO Auto-generated method stub  
  43.         return items.get(position);  
  44.     }  
  45.   
  46.     @Override  
  47.     public long getItemId(int position) {  
  48.         // TODO Auto-generated method stub  
  49.         return position;  
  50.     }  
  51.   
  52.     @Override  
  53.     public View getView(final int position, View convertView, ViewGroup parent) {  
  54.         // TODO Auto-generated method stub  
  55.           
  56.         System.out.println("Get in function getView.");  
  57.         ViewHolder holder;  
  58.         if(convertView == null)  
  59.         {  
  60.             convertView = inflater.inflate(R.layout.list_job, null);  
  61.             holder = new ViewHolder();  
  62.             holder.jobTitle = (TextView)convertView.findViewById(R.id.jobTitle);  
  63.             holder.content = (TextView)convertView.findViewById(R.id.content);  
  64.             holder.publishTimeText = (TextView)convertView.findViewById(R.id.publishTimeText);  
  65.         }  
  66.         else  
  67.         {  
  68.             holder = (ViewHolder)convertView.getTag();  
  69.         }  
  70.   
  71.         convertView.setOnTouchListener(new View.OnTouchListener() {  
  72.             @Override  
  73.             public boolean onTouch(View view, MotionEvent motionEvent) {  
  74.   
  75.                 if(motionEvent.getAction() == MotionEvent.ACTION_DOWN)  
  76.                 {  
  77.                     System.out.println("Item" + position + "pressed.");  
  78.                     ListItemAdapter.this.setIndex(position);  
  79.                     ListItemAdapter.this.notifyDataSetChanged();  
  80.                 }  
  81.   
  82.                 return false;  
  83.             }  
  84.         });  
  85.           
  86.         if(index == position)  
  87.         {  
  88.             convertView.findViewById(R.id.content).setSelected(true);  
  89. //          convertView.setBackgroundColor(Color.rgb(196, 215, 0));  
  90.             convertView.setBackgroundColor(Color.LTGRAY);  
  91.             holder.jobTitle.setTextColor(Color.WHITE);  
  92.             holder.content.setTextColor(Color.WHITE);  
  93.             holder.publishTimeText.setTextColor(Color.WHITE);  
  94.         }  
  95.         else  
  96.         {  
  97.             convertView.findViewById(R.id.content).setSelected(false);  
  98.             convertView.setBackgroundColor(Color.WHITE);  
  99.             holder.jobTitle.setTextColor(Color.BLACK);  
  100.             holder.content.setTextColor(Color.BLACK);  
  101.             holder.publishTimeText.setTextColor(Color.BLACK);  
  102.         }  
  103.           
  104.         convertView.setTag(holder);  
  105.         holder.jobTitle.setText( (String)items.get(position).get("jobTitle") );  
  106.         holder.content.setText((String)items.get(position).get("content"));  
  107.         holder.publishTimeText.setText((String)items.get(position).get("publishTimeText"));  
  108.           
  109.         return convertView;  
  110.     }  
  111.       
  112.     private class ViewHolder {    
  113.         private TextView jobTitle;  
  114.         private TextView content;    
  115.         private TextView publishTimeText;  
  116.     }    
  117.       
  118. }  

      这样,无论新的convertView,还是移交过来的老的convertView,都设置了和当前Item位置相对应的OnTouchListener,自然也就达到了预想的效果。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值