Android 是否正确设置在ListView中删除行的动画?
问题是: 1在listview中的行中添加一个触摸监听器,以便在滑动时 播放2个滑动动画 在后端删除3行,然后 4动画播放时没有任何闪烁或抖动。通过闪烁,我的意思是删除的行在动画完成后短暂显示 我怀疑动画监听器发生了一些奇怪的事情,因此我按照给定的顺序完成了以下操作: 通过将setFillAfter和setFillenabled设置为true,执行动画并使其持久化 在动画结束时使视图不可见 删除数据库中的行 重置动画 重新加载listview 使视图可见,但再等待300毫秒 结果删除行时没有抖动或闪烁,但现在由于额外的300毫秒等待而感觉迟钝。我也不确定这种延迟是否适用于所有设备 更新:我应该指出,300毫秒的延迟是它工作的原因。这很奇怪,因为此时动画已经重置,listview拥有最新的数据。没有理由让视图可见会使旧行短暂显示,对吗 我还尝试按照使用ViewPropertyAnimator,但由于某些原因,在动画的每一步都会调用onAnimationEnd侦听器 我还读到,我们应该实现一个自定义视图并覆盖其onAnimationEnd侦听器。然而,我还没有尝试过这种方法 更新:只是尝试在末尾添加一个额外的虚拟动画。然而,这是行不通的 我的测试手机运行冰淇淋三明治。我的应用程序的目标是姜饼和之后 那么正确的解决方案是什么?我这样做不对吗 代码如下:Android 是否正确设置在ListView中删除行的动画?,android,android-listview,android-animation,Android,Android Listview,Android Animation,问题是: 1在listview中的行中添加一个触摸监听器,以便在滑动时 播放2个滑动动画 在后端删除3行,然后 4动画播放时没有任何闪烁或抖动。通过闪烁,我的意思是删除的行在动画完成后短暂显示 我怀疑动画监听器发生了一些奇怪的事情,因此我按照给定的顺序完成了以下操作: 通过将setFillAfter和setFillenabled设置为true,执行动画并使其持久化 在动画结束时使视图不可见 删除数据库中的行 重置动画 重新加载listview 使视图可见,但再等待300毫秒 结果删除行时没有抖动
@Override
public boolean onTouch(final View view, MotionEvent event)
{
//...
switch(action) {
//...
case MotionEvent.ACTION_MOVE:
// ...
if (//check for fling
{
view.clearAnimation();
//animation = standard translate animation
animation.setAnimationListener(new AnimationListener() {
//
@Override
public void onAnimationEnd(Animation animation)
{
view.setVisibility(View.INVISIBLE);
flingListener.onFling(cursorPosition, view, velocity);
}
//...
});
view.startAnimation(animation);
}
break;
//
}
放纵的听众:
@Override
public void onFling(int position, final View view, float velocity)
{
//delete row -- its actually a Loader
//the following code runs in the Loader's onLoadFinished
view.clearAnimation();
adapter.notifyDataSetChanged();
adapter.swapCursor(null);
//reload listview -- it's actually a Loader
//the following code runs in the Loader's onLoadFinished
adapter.swapCursor(cursor);
view.postDelayed(new Runnable() {
@Override
public void run()
{
view.setVisibility(View.VISIBLE);
}
}, 300);
}
更新:在比较Chet Haase的代码之后,我们正在做一些类似的事情,但有一些重要的区别:1他使用一个onPreDraw侦听器和ListView树观察器来执行实际的删除,2他不仅从数组中删除行,而且从ListView中删除行。在模仿了他的代码之后,它仍然不起作用。现在的问题是加载器——我使用加载器异步删除行。在后端删除行之前,加载程序似乎会强制对ListView进行额外的draw调用。这是闪烁的另一个原因。但是仍然没有找到解决办法。切特·哈斯谷歌工程师在这个主题上做了一个非常好的开发,我建议看一下/从他的来源中吸取一些想法。如果您使用nineodeldroid,我认为这将向后兼容到GB 在这里查看:
谷歌工程师切特·哈斯(Chet Haase)在这个话题上做了一个非常好的设计,我建议你看看/从他的来源中汲取一些想法。如果您使用nineodeldroid,我认为这将向后兼容到GB 在这里查看:
正如我在评论中指出的,Chet代码的问题在于它是为同步数据访问而设计的。一旦开始异步删除行,他的代码就会失败 我通过结合Chet的代码和以下答案找到了闪烁问题的解决方案: 正确执行行删除操作的解决方案是: 为ListView树观察者创建onPreDraw侦听器以防止闪烁。此侦听器中的所有代码在列表视图重新绘制自身之前运行,以防止闪烁。 找到删除listview中但尚未删除数据库中的行的方法。有两种方法,请参见: 创建一个AbstractCursor包装器,忽略要删除的行,并将其替换为真正的游标。或 将要删除的行标记为染色,并在重新绘制该行时对其进行适当操作。 异步删除数据库中的real行。 使用AbstractCursor包装器的一些伪代码技术上称为代理:
//Called when you swipe a row to delete
@Override
public void onFling(final int positionToRemove, final View view)
{
final ViewTreeObserver observer = listView.getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
public boolean onPreDraw()
{
observer.removeOnPreDrawListener(this);
//remove the row from the matrix cursor
CursorProxy newCursor = new CursorProxy(cursor,
positionToRemove);
swapCursor(newCursor);
//delete row in database
}
}
}
正如我在评论中指出的,Chet代码的问题在于它是为同步数据访问而设计的。一旦开始异步删除行,他的代码就会失败 我通过结合Chet的代码和以下答案找到了闪烁问题的解决方案: 正确执行行删除操作的解决方案是: 为ListView树观察者创建onPreDraw侦听器以防止闪烁。此侦听器中的所有代码在列表视图重新绘制自身之前运行,以防止闪烁。 找到删除listview中但尚未删除数据库中的行的方法。有两种方法,请参见: 创建一个AbstractCursor包装器,忽略要删除的行,并将其替换为真正的游标。或 将要删除的行标记为染色,并在重新绘制该行时对其进行适当操作。 异步删除数据库中的real行。 使用AbstractCursor包装器的一些伪代码技术上称为代理:
//Called when you swipe a row to delete
@Override
public void onFling(final int positionToRemove, final View view)
{
final ViewTreeObserver observer = listView.getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
public boolean onPreDraw()
{
observer.removeOnPreDrawListener(this);
//remove the row from the matrix cursor
CursorProxy newCursor = new CursorProxy(cursor,
positionToRemove);
swapCursor(newCursor);
//delete row in database
}
}
}
可能的副本请在表决前阅读。您提供的链接仅适用于Android 4.1及以上版本。我需要姜饼和姜饼。如果你读过,你就会意识到这一点
欧丁,;不要检查这个。它还有姜饼的代码。我不投反对票。我把它作为复制品合上了。我还没有测试代码。但它应该是有效的,因为Cher haase是一名谷歌工程师。我对你的问题投了更高的票,但我仍然认为这是一个重复的问题。我不知道我是否可以回滚关闭投票,因为我已经将其标记为重复。啊,好的,谢谢。我看到姜饼密码,正在调查。感谢可能的副本,请在投票前阅读。您提供的链接仅适用于Android 4.1及以上版本。我需要姜饼和姜饼。如果你读过,你就会意识到你在读;不要检查这个。它还有姜饼的代码。我不投反对票。我把它作为复制品合上了。我还没有测试代码。但它应该是有效的,因为Cher haase是一名谷歌工程师。我对你的问题投了更高的票,但我仍然认为这是一个重复的问题。我不知道我是否可以回滚关闭投票,因为我已经将其标记为重复。啊,好的,谢谢。我看到姜饼密码,正在调查。感谢幸运的是,这是可行的,因为它依赖于withEndAction,Android 4.1的一项功能。不幸的是,早期版本中的等效功能动画侦听器已损坏。因此,我的问题。是的,这就是为什么我要检查,它提供了一个向后兼容的动画api版本。是的,推出本机动画代码来使用NineodelDroids,你就很好了。我试图避免使用另一个库来做一些应该很简单的事情。但如果我不能弄清楚,我肯定会调查。不幸的是,这是可行的,因为它依赖于withEndAction,一个Android 4.1的功能。不幸的是,早期版本中的等效功能动画侦听器已损坏。因此,我的问题。是的,这就是为什么我要检查,它提供了一个向后兼容的动画api版本。是的,推出本机动画代码来使用NineodelDroids,你就很好了。我试图避免使用另一个库来做一些应该很简单的事情。但如果我搞不清楚,我肯定会调查的