Android 在不重新填充的情况下更新GridView/ListView
每当更新GridView/ListView时,您都会在适配器上调用Android 在不重新填充的情况下更新GridView/ListView,android,android-listview,android-gridview,android-adapter,Android,Android Listview,Android Gridview,Android Adapter,每当更新GridView/ListView时,您都会在适配器上调用notifyDatasetChanged,该适配器会使用新数据重新填充列表,删除列表中当前的所有内容 现在以L预览版设计指南中的这个小例子为例 当适配器重新加载时,您看到的唯一变化是新项目进入时没有任何“闪烁”,或者这是现在只能在L中完成的事情时,是否有可能实现相同的效果 添加新注释时,也可以在googlekeep应用程序中找到这种效果在不重新填充的情况下更新GridView/ListView 如果在每次更新和删除时间时都使用相同
notifyDatasetChanged
,该适配器会使用新数据重新填充列表,删除列表中当前的所有内容
现在以L预览版
设计指南中的这个小例子为例
当适配器重新加载时,您看到的唯一变化是新项目进入时没有任何“闪烁”,或者这是现在只能在L中完成的事情时,是否有可能实现相同的效果
添加新注释时,也可以在
googlekeep
应用程序中找到这种效果在不重新填充的情况下更新GridView/ListView
如果在每次更新和删除时间时都使用相同的数组列表,而不创建新的ArrayList,则adapter.notifyDatasetChanged()方法可以工作。
请您每次都使用相同的arrayList,不要创建适配器类的新实例,恐怕这都是视觉上的诡计,也就是动画 …删除列表中当前的所有内容。 事实上,没有
notifyDataSetChanged
仅告知基础观察者数据已更改。就这样。作为响应,getView(…)
将为每个可见视图调用,即可通过ListView\getChildCount()
访问的编号。由于索引已更改(添加/删除项),或者这些索引中的对象中保存的数据已(^)更改(一个或多个项已更改),因此通过后续调用ListView#getView(…)
可以直观地刷新数据
“Android开发者”有一段有趣的视频,解释了如何产生你想要的效果:
视频/示例仅讨论单个项目的插入。但它应该可以扩展到所有的数据操作,并具备一定的时间和数学技能
我能够扩展示例代码以插入多个项。我将动画更改为更简单的alpha淡入。单击添加行
按钮将项目的随机数(介于1和3之间)添加到列表视图中。下面是它的外观:
Psuedo工作流:
- 在将新项传递给适配器之前,在listview中循环所有可见项,并保存它们的边界(在
中)和快照(在Rect
中)BitmapDrawables
- 将项目传递给适配器
- 向ListView的ViewTreeObserver添加一个
OnPreDrawListener
- 调用
时,新项目已准备好绘制。我们可以使用带有相应索引的onPreDraw(…)
访问他们的ListView#getChildAt(…)
视图
- 所有新项目都设置为“不可见”,并指定alpha动画师
- 所有旧项目都被指定为平移动画
- 由于添加新项目,无法通过
访问的项目将被指定为翻译动画制作者,以使其离开屏幕(或超出listview范围)getChildAt(..)
- 翻译动画师被解雇了。当这些动画师完成运行时,alpha动画师将启动
GridView
或StaggeredGridView
(keep)的情况下,这将更加困难,因为数学将涉及X
和Y
中的翻译。但是工作流应该保持不变
(^)-语法上不正确,但在我看来很自然。这可以通过抓取视图并更改其中的数据来实现。我举了一个例子,在长时间单击时,您可以在不刷新可见项和不调用notifyDataSetChanged()的情况下更改数据 这个问题在谷歌I/O 2010上被提出,你可以在这里观看: 代码改编自
package com.example.stableids;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入android.os.Build;
导入android.os.Bundle;
导入android.annotation.SuppressLint;
导入android.annotation.TargetApi;
导入android.app.Activity;
导入android.content.Context;
导入android.database.DataSetObserver;
导入android.util.Log;
导入android.view.Menu;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.Adapter;
导入android.widget.AdapterView;
导入android.widget.ArrayAdapter;
导入android.widget.ListView;
导入android.widget.TextView;
@TargetApi(构建版本代码蜂窝MR1)
@SuppressLint(“新API”)
公共类MainActivity扩展了活动{
@TargetApi(构建版本代码蜂窝)
@SuppressLint(“新API”)
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
最终ListView ListView=(ListView)findViewById(R.id.ListView);
字符串[]值=新字符串[]{“Android”、“iPhone”、“WindowsMobile”,
“黑莓”、“WebOS”、“Ubuntu”、“Windows7”、“Max OS X”,
“Linux”、“OS/2”、“Ubuntu”、“Windows7”、“Max OS X”、“Linux”,
“OS/2”、“Ubuntu”、“Windows7”、“Max OS X”、“Linux”、“OS/2”,
“安卓”、“iPhone”、“WindowsMobile”};
最终ArrayList=新ArrayList();
对于(int i=0;ipackage com.example.stableids;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.os.Build;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.database.DataSetObserver;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
@SuppressLint("NewApi")
public class MainActivity extends Activity {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ListView listview = (ListView) findViewById(R.id.listview);
String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
"Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
"Linux", "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux",
"OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2",
"Android", "iPhone", "WindowsMobile" };
final ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < values.length; ++i) {
list.add(values[i]);
}
final StableArrayAdapter adapter = new StableArrayAdapter(this,
android.R.layout.simple_list_item_1, list);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@SuppressLint("NewApi")
@Override
public void onItemClick(AdapterView<?> parent, final View view,
final int position, long id) {
final String item = (String) parent.getItemAtPosition(position);
view.animate().setDuration(2000).alpha(0)
.withEndAction(new Runnable() {
@Override
public void run() {
int i = list.indexOf(item);
list.remove(item);
list.add(i, "MODIFIED");
adapter.mIdMap.put("MODIFIED", position);
TextView tv = (TextView)view.findViewById(android.R.id.text1);
tv.setText("MODIFIED");
//adapter.notifyDataSetChanged();
view.setAlpha(1);
}
});
}
});
}
private class StableArrayAdapter extends ArrayAdapter<String> {
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public StableArrayAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("STABLE ID", "getView called for " + position + " position");
return super.getView(position, convertView, parent);
}
@Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
@Override
public boolean hasStableIds() {
return true;
}
}
}