更新GridView / ListView而不重新填充

每当你更新一个GridView / ListView的时候,你notifyDatasetChanged在适配器上调用notifyDatasetChanged来重新填充列表中的新数据,删除当前列表中的所有内容。

现在把这个小video例如从L Previewdevise指南

是否有可能实现相同的效果,只有当你看到的新变化是在适配器重新加载时没有任何“闪烁”而进入的新项目,还是现在只能在L中完成的事情?

在添加新笔记时, Google Keep应用程序中也可以find这种效果

Solutions Collecting From Web of "更新GridView / ListView而不重新填充"

我担心它的所有视觉诡计 – 又名animation。

清除当前列表中的所有内容

其实没有

notifyDataSetChanged只告诉底层观察者数据已经改变。 而已。 作为响应,为每个可见视图调用getView(...)ListView#getChildCount()可访问的数字。 由于任何索引已经改变(添加/删除项目),或者在这些索引处的对象中保存的数据已经被改变(一个或多个项目已经改变),所以通过随后调用ListView#getView(...)

“Android开发人员”有一个有趣的video,解释了如何产生你以后的效果: DevBytes:ListView Cell Insertion Animation 。

video/示例只讲单品插入。 但是它应该可以延伸到具有一定时间和math技能的所有数据操作。

我能够扩展示例代码插入多个项目。 我将animation更改为更简单的alpha淡入。 点击Add rowbutton将一个随机数(1到3之间)的项目添加到列表视图。 这是它的样子:

在这里输入图像说明

伪的工作stream程:

  • 在将新项目传递给适配器之前,循环访问列表视图中的所有可见项目并保存其边界(在Rect )和快照(在BitmapDrawables

  • 将项目传递给适配器

  • 添加一个OnPreDrawListener到ListView的ViewTreeObserver。

  • onPreDraw(...)被调用时,新的项目准备好被绘制。 我们可以使用ListView#getChildAt(...)和各自的索引来访问他们的views

  • 所有新项目都被设置为不可见,并且分配了阿尔法animation师

  • 所有旧的项目被分配translation_yanimation师

  • 不能再通过getChildAt(..)访问的项目 – 由于添加了新项目 – 被赋予了translation_yanimation师 – 将它们从屏幕上移除(或者不在列表视图范围内)

  • 翻译animation师被解雇。 当这些animation师完成了运行,alphaanimation师开始。

请注意,animationtypes(alpha,翻译,缩放或这些的任意组合)是相对不重要的。 我想这将是困难的GridViewStaggeredGridView (保留)的情况下 – 只是因为math将涉及X Y翻译。 工作stream程应该保持不变。

(^) – 语法不正确,但自然IMO。

这可以通过抓取视图并更改其中的数据来实现。我已经包含了一个例子,在长时间点击更改数据而无需刷新可见项和不调用notifyDataSetChanged()。

这个问题已经在Google I / O 2010上问过了,你可以在这里看到:

ListView的世界,时间52:30

代码改编自Vogella

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

在不重新填充的情况下更新GridView / ListView

如果每次更新和删除时都使用相同的数组List,而不创build新的ArrayList,那么您的adapter.notifyDatasetChanged()方法就可以工作。 请每次和你一样的arrayList,不要创build适配器类的新实例