Hey I had a similar problem and solved like this, hope it helps you:
I used what Chet Haase showed in this devbyte: http://www.youtube.com/watch?v=YCHNAi9kJI4
It's very similar to Roman's code, but here he uses a ViewTreeObserver, so after you deleted the item from the adapter, but before the list is redrawn, you have time to animate closing the gap, and it won't flicker. Another difference is, that he sets the Listener to each view(item) of the list in the adapter, and not on the ListView itself.
So a sample of my code:
This is the ListActivity's onCreate, here I pass the listener to the adapter nothing special:
ListAdapterTouchListener listAdapterTouchListener = new ListAdapterTouchListener(getListView());
listAdapter = new ListAdapter(this,null,false,listAdapterTouchListener);
Here is part of the ListAdapter(it's my own adapter that extends the CursorAdapter),
I pass the Listener in the Constructor,
private View.OnTouchListener onTouchListener;
public ListAdapter(Context context, Cursor c, boolean autoRequery,View.OnTouchListener listener) {
super(context, c, autoRequery);
onTouchListener = listener;
}
and then in the newView method I set it to the view:
@Override
public View newView(final Context context, Cursor cursor, ViewGroup parent) {
View view = layoutInflater.inflate(R.layout.list_item,parent,false);
// here should be some viewholder magic to make it faster
view.setOnTouchListener(onTouchListener);
return view;
}
The listener is mostly the same as in the code shown in the video, I don't use the backgroundcontainer but that's just my choice. So the animateRemoval has the part what is interesting, here it is:
private void animateRemoval(View viewToRemove){
for(int i=0;i<listView.getChildCount();i++){
View child = listView.getChildAt(i);
if(child!=viewToRemove){
// since I don't have stableIds I use the _id from the sqlite database
// I'm adding the id to the viewholder in the bindView method in the ListAdapter
ListAdapter.ViewHolder viewHolder = (ListAdapter.ViewHolder)child.getTag();
long itemId = viewHolder.id;
itemIdTopMap.put(itemId, child.getTop());
}
}
// I'm using content provider with LoaderManager in the activity because it's more efficient, I get the id from the viewholder
ListAdapter.ViewHolder viewHolder = (ListAdapter.ViewHolder)viewToRemove.getTag();
long removeId = viewHolder.id;
//here you remove the item
listView.getContext().getContentResolver().delete(Uri.withAppendedPath(MyContentProvider.CONTENT_ID_URI_BASE,Long.toString(removeId)),null,null);
// after the removal get a ViewTreeObserver, so you can set a PredrawListener
// the rest of the code is pretty much the same as in the sample shown in the video
final ViewTreeObserver observer = listView.getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
observer.removeOnPreDrawListener(this);
boolean firstAnimation = true;
for(int i=0;i<listView.getChildCount();i++){
final View child = listView.getChildAt(i);
ListAdapter.ViewHolder viewHolder = (ListAdapter.ViewHolder)child.getTag();
long itemId = viewHolder.id;
Integer startTop = itemIdTopMap.get(itemId);
int top = child.getTop();
if(startTop!=null){
if (startTop!=top) {
int delta=startTop-top;
child.setTranslationY(delta);
child.animate().setDuration(MOVE_DURATION).translationY(0);
if(firstAnimation){
child.animate().setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
swiping=false;
listView.setEnabled(true);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
firstAnimation=false;
}
}
}else{
int childHeight = child.getHeight()+listView.getDividerHeight();
startTop = top+(i>0?childHeight:-childHeight);
int delta = startTop-top;
child.setTranslationY(delta);
child.animate().setDuration(MOVE_DURATION).translationY(0);
if(firstAnimation){
child.animate().setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
swiping=false;
listView.setEnabled(true);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
firstAnimation=false;
}
}
}
itemIdTopMap.clear();
return true;
}
});
}
Hope this helps you, it's working nice for me! You really should watch the devbyte, it helped me a lot!