ListView在不刷新整个界面下,单独更新item
2015-08-21 19:33
260 查看
大家有没有遇到过在不刷新listview,即调用notifyDataSetChanged()的情况下单独更新item.下面带大家按照google采用的方式单独更新item
代码如下:
MainActivity
public class MainActivity extends Activity implements OnItemClickListener{
ArrayList<String> list;
ListView listview;
ListViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview=(ListView) findViewById(R.id.listview);
init();
adapter=new ListViewAdapter(list,this);
listview.setAdapter(adapter);
listview.setOnItemClickListener(this);
}
public void init(){
list=new ArrayList<String>();
list.add("the item 1");
list.add("the item 2");
list.add("the item 3");
list.add("the item 4");
list.add("the item 5");
list.add("the item 6");
..........
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long id) {
adapter.updateSingleRow(listview,id);
}
}
activity_main.xml 只有一个ListView控件。
ListViewAdapter:
public class ListViewAdapter extends BaseAdapter{
ArrayList<String> list;
Context context;
public ListViewAdapter(ArrayList<String> list,Context context){
this.list=list;
this.context=context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int arg0) {
return list.get(arg0);
}
@Override
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int arg0, View convertView, ViewGroup viewGroup) {
ViewHolder holder;
if(convertView==null){
convertView=LayoutInflater.from(context).inflate(R.layout.listview_item, null, false);
holder=new ViewHolder();
holder.textView=(TextView) convertView.findViewById(R.id.item_text);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
holder.textView.setText(list.get(arg0));
return convertView;
}
class ViewHolder{
TextView textView;
}
public void updateSingleRow(ListView listview,long id){
int firstPosition=listview.getFirstVisiblePosition();
int lasrPosition=listview.getLastVisiblePosition();
for(int i=firstPosition;i<=lasrPosition;i++){
if(listview.getItemIdAtPosition(i)==id){ //当传过来的id与遍历的id相同就更新
View view=listview.getChildAt(i-firstPosition); //如果可见的第一个item不是0
list.remove(i);
list.add(i,"我在更新数据");
getView(i,view,null);
}
}
}
}
这里解释下:
long id 表示item的id,这是与position是不同的概念。
listview.getFirstVisiblePosition(); 获取的屏幕上显示的第一条item的positon
listview.getLastVisiblePosition(); 获取屏幕上显示的最后一条item的position
getView(i,view,null) 可以实现单独的更新,注意参数view.
至此就可以实现单独跟新item了,同样的采用notifyDataSetChanged()同样可以实现。
疑问:如果我加上Header和Footer还会实现相同的效果吗?
在MainActivity的listview.setAdapter(adapter)之前添加如下语句:
View header=LayoutInflater.from(this).inflate(R.layout.listview_header,null); //很简单的布局
View footer=LayoutInflater.from(this).inflate(R.layout.listview_footer,null);
listview.addHeaderView(header);
listview.addFooterView(footer);
测试图:
上拉刷新之后:
通过测试发现当点击刷新之后,滑动之后,更改数据出现下滑的现象.
主要原因是:添加header和footer之后第一个position的item变成了header, 最后一个position的item变成footer
假如我点击的第3个position的item,在前面有一个header和1个item,通过调用updateSingleRow(),遍历之后调用getView(i,view null),这里需要注意getView()中的position只对应arraylist的index,不包含header和footer,所以这里传进去的i包含了header,导致arraylist集体下移了,所以实际上更新的是第4个position的值,当滑动时肯定还原,变成第四个position更改数据。
解决方式:
list.remove(i-1);
list.add(i-1,"我在更新数据"); //加入i=3,那么改变的 是集合中第四条数据,所以必须减去1
getView(i-1,view,null);
最终的结果正确
问题:按照错误的方式,为什么我初次点击的时候,数据更改是对的,但是当我上拉之后数据才会变化,刚开始按照前面的逻辑应该也会错位?
代码如下:
MainActivity
public class MainActivity extends Activity implements OnItemClickListener{
ArrayList<String> list;
ListView listview;
ListViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview=(ListView) findViewById(R.id.listview);
init();
adapter=new ListViewAdapter(list,this);
listview.setAdapter(adapter);
listview.setOnItemClickListener(this);
}
public void init(){
list=new ArrayList<String>();
list.add("the item 1");
list.add("the item 2");
list.add("the item 3");
list.add("the item 4");
list.add("the item 5");
list.add("the item 6");
..........
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long id) {
adapter.updateSingleRow(listview,id);
}
}
activity_main.xml 只有一个ListView控件。
ListViewAdapter:
public class ListViewAdapter extends BaseAdapter{
ArrayList<String> list;
Context context;
public ListViewAdapter(ArrayList<String> list,Context context){
this.list=list;
this.context=context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int arg0) {
return list.get(arg0);
}
@Override
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int arg0, View convertView, ViewGroup viewGroup) {
ViewHolder holder;
if(convertView==null){
convertView=LayoutInflater.from(context).inflate(R.layout.listview_item, null, false);
holder=new ViewHolder();
holder.textView=(TextView) convertView.findViewById(R.id.item_text);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
holder.textView.setText(list.get(arg0));
return convertView;
}
class ViewHolder{
TextView textView;
}
public void updateSingleRow(ListView listview,long id){
int firstPosition=listview.getFirstVisiblePosition();
int lasrPosition=listview.getLastVisiblePosition();
for(int i=firstPosition;i<=lasrPosition;i++){
if(listview.getItemIdAtPosition(i)==id){ //当传过来的id与遍历的id相同就更新
View view=listview.getChildAt(i-firstPosition); //如果可见的第一个item不是0
list.remove(i);
list.add(i,"我在更新数据");
getView(i,view,null);
}
}
}
}
这里解释下:
long id 表示item的id,这是与position是不同的概念。
listview.getFirstVisiblePosition(); 获取的屏幕上显示的第一条item的positon
listview.getLastVisiblePosition(); 获取屏幕上显示的最后一条item的position
getView(i,view,null) 可以实现单独的更新,注意参数view.
至此就可以实现单独跟新item了,同样的采用notifyDataSetChanged()同样可以实现。
疑问:如果我加上Header和Footer还会实现相同的效果吗?
在MainActivity的listview.setAdapter(adapter)之前添加如下语句:
View header=LayoutInflater.from(this).inflate(R.layout.listview_header,null); //很简单的布局
View footer=LayoutInflater.from(this).inflate(R.layout.listview_footer,null);
listview.addHeaderView(header);
listview.addFooterView(footer);
测试图:
上拉刷新之后:
通过测试发现当点击刷新之后,滑动之后,更改数据出现下滑的现象.
主要原因是:添加header和footer之后第一个position的item变成了header, 最后一个position的item变成footer
假如我点击的第3个position的item,在前面有一个header和1个item,通过调用updateSingleRow(),遍历之后调用getView(i,view null),这里需要注意getView()中的position只对应arraylist的index,不包含header和footer,所以这里传进去的i包含了header,导致arraylist集体下移了,所以实际上更新的是第4个position的值,当滑动时肯定还原,变成第四个position更改数据。
解决方式:
list.remove(i-1);
list.add(i-1,"我在更新数据"); //加入i=3,那么改变的 是集合中第四条数据,所以必须减去1
getView(i-1,view,null);
最终的结果正确
问题:按照错误的方式,为什么我初次点击的时候,数据更改是对的,但是当我上拉之后数据才会变化,刚开始按照前面的逻辑应该也会错位?
相关文章推荐
- Java三大常用布局管理器
- poj 1274 The Perfact Stall
- js倒计时
- 消除递归的方法
- DataSetObservable,Observable<T>,DataSetObserver源码注释翻译
- 将一个或多个OC对象写入文件/从文件读出
- ZOJ 3529 A Game Between Alice and Bob
- java中常用io流 BufferedInputStream和BufferedOutputStream
- js流程控制语句(判断语句)
- 【 D3.js 入门系列 --- 9.3 】 弦图生产
- JAVA12个最重要的J2EE最佳实践
- img下图形必须刷新才显示最新数据的问题
- 2015 HUAS Summer Contest#5~B
- 微信内置浏览器的 User Agent的判断
- spmio 内网源部署(二)
- sql server 2008如何导入mdf,ldf文件
- CSND博文书写格式
- 多线程
- 关于UIScreen的applicationFrame和bounds方法区别
- KM算法板子2