ListView中为每个item设置监听器(转)
2014-03-21 11:36
134 查看
转自: 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
plaincopy
package org.cdpsn.client.widget.wheel;
import java.util.List;
import java.util.Map;
import org.cdpsn.client.R;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ListItemAdapter extends BaseAdapter
{
private LayoutInflater inflater;
private List<Map<String, Object>> items;
private static int index = 0;
public ListItemAdapter(Context context, List<Map<String, Object>> items) {
super();
this.inflater = LayoutInflater.from(context);
this.items = items;
}
public void setIndex(int selected)
{
index = selected;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
System.out.println("Get in function getView.");
ViewHolder holder;
if(convertView == null)
{
convertView = inflater.inflate(R.layout.list_job, null);
holder = new ViewHolder();
holder.jobTitle = (TextView)convertView.findViewById(R.id.jobTitle);
holder.content = (TextView)convertView.findViewById(R.id.content);
holder.publishTimeText = (TextView)convertView.findViewById(R.id.publishTimeText);
convertView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN)
{
System.out.println("Item" + position + "pressed.");
ListItemAdapter.this.setIndex(position);
ListItemAdapter.this.notifyDataSetChanged();
}
return false;
}
});
}
else
{
holder = (ViewHolder)convertView.getTag();
}
if(index == position)
{
convertView.findViewById(R.id.content).setSelected(true);
// convertView.setBackgroundColor(Color.rgb(196, 215, 0));
convertView.setBackgroundColor(Color.LTGRAY);
holder.jobTitle.setTextColor(Color.WHITE);
holder.content.setTextColor(Color.WHITE);
holder.publishTimeText.setTextColor(Color.WHITE);
}
else
{
convertView.findViewById(R.id.content).setSelected(false);
convertView.setBackgroundColor(Color.WHITE);
holder.jobTitle.setTextColor(Color.BLACK);
holder.content.setTextColor(Color.BLACK);
holder.publishTimeText.setTextColor(Color.BLACK);
}
convertView.setTag(holder);
holder.jobTitle.setText( (String)items.get(position).get("jobTitle") );
holder.content.setText((String)items.get(position).get("content"));
holder.publishTimeText.setText((String)items.get(position).get("publishTimeText"));
return convertView;
}
private class ViewHolder {
private TextView jobTitle;
private TextView content;
private TextView publishTimeText;
}
}
试着跑了一下程序,似乎是可以的。但是多试了几次之后,发现还是有问题,当按住位置靠后的Item时,被按住的子项显示的效果并没有改变,改变的是位置靠前的子项。于是去搜索了一下getView的工作机制,发现convertView并不像我想象的那么简单。在配置适配器时,getView并没有为每一个Item配备一个convertView。设想一下,假如列表中有上百个Item,同时配备这么多convertView是很浪费资源的。所以convertView其实是可以循环利用的。也就是说,随着列表向下拉,屏幕上会显示新的子项,而老的子项会移出屏幕。这是,老的子项会把convertView交给新的子项使用,节省了资源。
再看上面的代码,只有在convertView为空时,才为convertView设置OnTouchListener监听器。这样,老的Item在移交convertView的同时,也把老的监听器移交给了新的Item。所以才会出现按住下面的子项,上面的子项变化样式的诡异情况。清楚了原理之后,把监听器的设置写在了判断convertView是否为空的程序片段的外面,代码如下:
[java] view
plaincopy
package org.cdpsn.client.widget.wheel;
import java.util.List;
import java.util.Map;
import org.cdpsn.client.R;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ListItemAdapter extends BaseAdapter
{
private LayoutInflater inflater;
private List<Map<String, Object>> items;
private static int index = 0;
public ListItemAdapter(Context context, List<Map<String, Object>> items) {
super();
this.inflater = LayoutInflater.from(context);
this.items = items;
}
public void setIndex(int selected)
{
index = selected;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
System.out.println("Get in function getView.");
ViewHolder holder;
if(convertView == null)
{
convertView = inflater.inflate(R.layout.list_job, null);
holder = new ViewHolder();
holder.jobTitle = (TextView)convertView.findViewById(R.id.jobTitle);
holder.content = (TextView)convertView.findViewById(R.id.content);
holder.publishTimeText = (TextView)convertView.findViewById(R.id.publishTimeText);
}
else
{
holder = (ViewHolder)convertView.getTag();
}
convertView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN)
{
System.out.println("Item" + position + "pressed.");
ListItemAdapter.this.setIndex(position);
ListItemAdapter.this.notifyDataSetChanged();
}
return false;
}
});
if(index == position)
{
convertView.findViewById(R.id.content).setSelected(true);
// convertView.setBackgroundColor(Color.rgb(196, 215, 0));
convertView.setBackgroundColor(Color.LTGRAY);
holder.jobTitle.setTextColor(Color.WHITE);
holder.content.setTextColor(Color.WHITE);
holder.publishTimeText.setTextColor(Color.WHITE);
}
else
{
convertView.findViewById(R.id.content).setSelected(false);
convertView.setBackgroundColor(Color.WHITE);
holder.jobTitle.setTextColor(Color.BLACK);
holder.content.setTextColor(Color.BLACK);
holder.publishTimeText.setTextColor(Color.BLACK);
}
convertView.setTag(holder);
holder.jobTitle.setText( (String)items.get(position).get("jobTitle") );
holder.content.setText((String)items.get(position).get("content"));
holder.publishTimeText.setText((String)items.get(position).get("publishTimeText"));
return convertView;
}
private class ViewHolder {
private TextView jobTitle;
private TextView content;
private TextView publishTimeText;
}
}
这样,无论新的convertView,还是移交过来的老的convertView,都设置了和当前Item位置相对应的OnTouchListener,自然也就达到了预想的效果。
最近需要给ListView写一个监听器,在按住ListView中Item不松手的时候,改变Item的样式,使得被按住的Item背景色为灰,并显示跑马灯效果。因为需要具体到每个Item,所以首先想到了OnItemClickListener。但是稍微想想就知道这样是不行的,OnItemClickListener监听的是点击某个Item的动作,点击包括按下和松开两个部分,所以不用到达想要的效果。
于是想到用OnTouchListener监听按下的动作。但是,你知道我是会说但是的。OnTouchListener针对的是整个ListView,并没有提供被点击Item的位置参数,所以这样并不能达到改变单个Item显示效果的目的。顿时有种想掀桌的冲动,但是实验室的桌子我真的掀不动。于是去StackOverflow搜索,开始搜索不得法,没有找到想要的东西。难道老外们都不屑于问这种小白问题吗?不可能,我明明见过有人问Hello world为啥跑不出来之类的问题来着。几经变换关键词之后找到了一个和我问题很相似的提问。大概意思就是说
:“哥们儿,我原来遇到的问题和你现在遇到的这个问题贼拉想,唉呀妈呀,我告诉你咋整呗。你就自个儿写一个BaseAdapter子类,然后再getView()方法里加一个OnTouchListener就欧了,缸缸地好使。”之前要写跑马灯效果,所以自定义的适配器已经写过了,按照提问里说的办法加了OnTouchListener。
[java] view
plaincopy
package org.cdpsn.client.widget.wheel;
import java.util.List;
import java.util.Map;
import org.cdpsn.client.R;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ListItemAdapter extends BaseAdapter
{
private LayoutInflater inflater;
private List<Map<String, Object>> items;
private static int index = 0;
public ListItemAdapter(Context context, List<Map<String, Object>> items) {
super();
this.inflater = LayoutInflater.from(context);
this.items = items;
}
public void setIndex(int selected)
{
index = selected;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
System.out.println("Get in function getView.");
ViewHolder holder;
if(convertView == null)
{
convertView = inflater.inflate(R.layout.list_job, null);
holder = new ViewHolder();
holder.jobTitle = (TextView)convertView.findViewById(R.id.jobTitle);
holder.content = (TextView)convertView.findViewById(R.id.content);
holder.publishTimeText = (TextView)convertView.findViewById(R.id.publishTimeText);
convertView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN)
{
System.out.println("Item" + position + "pressed.");
ListItemAdapter.this.setIndex(position);
ListItemAdapter.this.notifyDataSetChanged();
}
return false;
}
});
}
else
{
holder = (ViewHolder)convertView.getTag();
}
if(index == position)
{
convertView.findViewById(R.id.content).setSelected(true);
// convertView.setBackgroundColor(Color.rgb(196, 215, 0));
convertView.setBackgroundColor(Color.LTGRAY);
holder.jobTitle.setTextColor(Color.WHITE);
holder.content.setTextColor(Color.WHITE);
holder.publishTimeText.setTextColor(Color.WHITE);
}
else
{
convertView.findViewById(R.id.content).setSelected(false);
convertView.setBackgroundColor(Color.WHITE);
holder.jobTitle.setTextColor(Color.BLACK);
holder.content.setTextColor(Color.BLACK);
holder.publishTimeText.setTextColor(Color.BLACK);
}
convertView.setTag(holder);
holder.jobTitle.setText( (String)items.get(position).get("jobTitle") );
holder.content.setText((String)items.get(position).get("content"));
holder.publishTimeText.setText((String)items.get(position).get("publishTimeText"));
return convertView;
}
private class ViewHolder {
private TextView jobTitle;
private TextView content;
private TextView publishTimeText;
}
}
试着跑了一下程序,似乎是可以的。但是多试了几次之后,发现还是有问题,当按住位置靠后的Item时,被按住的子项显示的效果并没有改变,改变的是位置靠前的子项。于是去搜索了一下getView的工作机制,发现convertView并不像我想象的那么简单。在配置适配器时,getView并没有为每一个Item配备一个convertView。设想一下,假如列表中有上百个Item,同时配备这么多convertView是很浪费资源的。所以convertView其实是可以循环利用的。也就是说,随着列表向下拉,屏幕上会显示新的子项,而老的子项会移出屏幕。这是,老的子项会把convertView交给新的子项使用,节省了资源。
再看上面的代码,只有在convertView为空时,才为convertView设置OnTouchListener监听器。这样,老的Item在移交convertView的同时,也把老的监听器移交给了新的Item。所以才会出现按住下面的子项,上面的子项变化样式的诡异情况。清楚了原理之后,把监听器的设置写在了判断convertView是否为空的程序片段的外面,代码如下:
[java] view
plaincopy
package org.cdpsn.client.widget.wheel;
import java.util.List;
import java.util.Map;
import org.cdpsn.client.R;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ListItemAdapter extends BaseAdapter
{
private LayoutInflater inflater;
private List<Map<String, Object>> items;
private static int index = 0;
public ListItemAdapter(Context context, List<Map<String, Object>> items) {
super();
this.inflater = LayoutInflater.from(context);
this.items = items;
}
public void setIndex(int selected)
{
index = selected;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
System.out.println("Get in function getView.");
ViewHolder holder;
if(convertView == null)
{
convertView = inflater.inflate(R.layout.list_job, null);
holder = new ViewHolder();
holder.jobTitle = (TextView)convertView.findViewById(R.id.jobTitle);
holder.content = (TextView)convertView.findViewById(R.id.content);
holder.publishTimeText = (TextView)convertView.findViewById(R.id.publishTimeText);
}
else
{
holder = (ViewHolder)convertView.getTag();
}
convertView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN)
{
System.out.println("Item" + position + "pressed.");
ListItemAdapter.this.setIndex(position);
ListItemAdapter.this.notifyDataSetChanged();
}
return false;
}
});
if(index == position)
{
convertView.findViewById(R.id.content).setSelected(true);
// convertView.setBackgroundColor(Color.rgb(196, 215, 0));
convertView.setBackgroundColor(Color.LTGRAY);
holder.jobTitle.setTextColor(Color.WHITE);
holder.content.setTextColor(Color.WHITE);
holder.publishTimeText.setTextColor(Color.WHITE);
}
else
{
convertView.findViewById(R.id.content).setSelected(false);
convertView.setBackgroundColor(Color.WHITE);
holder.jobTitle.setTextColor(Color.BLACK);
holder.content.setTextColor(Color.BLACK);
holder.publishTimeText.setTextColor(Color.BLACK);
}
convertView.setTag(holder);
holder.jobTitle.setText( (String)items.get(position).get("jobTitle") );
holder.content.setText((String)items.get(position).get("content"));
holder.publishTimeText.setText((String)items.get(position).get("publishTimeText"));
return convertView;
}
private class ViewHolder {
private TextView jobTitle;
private TextView content;
private TextView publishTimeText;
}
}
这样,无论新的convertView,还是移交过来的老的convertView,都设置了和当前Item位置相对应的OnTouchListener,自然也就达到了预想的效果。
相关文章推荐
- ListView中为每个item设置监听器
- 用 Case方法为每个 ListView 的Item设置监听器
- 如何设置listview每个item高度
- 设置listview 中每个Item之间的间距
- Android 对listview中每个item高度的设置
- android ListView 设置每个Item的高度
- Android设置Listview每个item的间距
- android中通过网络请求数据显示在Listview中,面对许多的item,如何给每个item设置点击事件以跳转到不同的activity
- listview设置每个item的间距
- 两个Listview之间旋转切换,并且为每个item设置动画
- 举例说明ArrayAdapter的使用和如何设置ListView中每个Item的点击事件
- android:设置listview里面每个item的上下间距
- 使用ListView界面布局、给每个item绑定监听器
- Android listView每个item设置不同
- android 每个listview的item上都设置一个倒计时 而不错乱、卡顿的一个Demo
- 设置listview展示数据每个item之间的间隔
- 记录:设置listview中每个item的高度
- 对listview中每个item高度的设置
- ListView每个Item上面的组件添加事件
- Android中为ListView的Item选项设置出场动画