Wednesday, March 13, 2013

List animation with drawingCache

A bit of animation for the rest of the items when a listitem is removed from a ListView. I've seen an interesting solution for this. The basic idea is to get a bitmap copy of the existing layout and animate the bitmap only. And when the animation finishes, hide the bitmap. With this we don't have to inflate (and measure and layout again and again).
One addition might be the ViewGroup.setClipChildren(false) call. This may prevent a visual glitch: the item at the bottom of the screen may be clipped so the animation may animate a half item. I didn't try it out though.
I made a small change in the code linked above, but I copy here the code to have syntax highlight.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View rowView, int positon,long id) {
        listView.setDrawingCacheEnabled(true); // turn this on to be able to get the bitmapcopy
        Bitmap bitmap = listView.getDrawingCache(); // get the bitmapcopy of the view
        int bottom = rowView.getBottom();
        Bitmap myBitmap1 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), Math.min(bottom, bitmap.getHeight())); // get the upper half
        Bitmap myBitmap2 = Bitmap.createBitmap(bitmap,
                                               0,
                                               bottom,
                                               bitmap.getWidth(),
                                               bitmap.getHeight() - myBitmap1.getHeight()); // get the lower half (that will slide up)
        listView.setDrawingCacheEnabled(false); // turn off, not to mess up anything
        imgView1.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap1)); // these to imageView are added to the layout (eg. in the layout file)
        imgView2.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap2));
        imgView1.setVisibility(View.VISIBLE);
        imgView2.setVisibility(View.VISIBLE);
        FrameLayout.LayoutParams lp2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
        FrameLayout.LayoutParams lp1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
        lp2.setMargins(0, rowView.getBottom(), 0, 0);
        lp1.height = bottom;
        imgView1.setLayoutParams(lp1);
        imgView2.setLayoutParams(lp2);
        TranslateAnimation transanim=new TranslateAnimation(0, 0, 0, -rowView.getHeight());
        transanim.setDuration(1000);
        transanim.setAnimationListener(new Animation.AnimationListener() {
            public void onAnimationStart(Animation animation) {}
            public void onAnimationRepeat(Animation animation) {}
            public void onAnimationEnd(Animation animation) {
                imgView1.setVisibility(View.GONE);
                imgView2.setVisibility(View.GONE);
            }
        });
        mAdapter.remove(mAdapter.getItem(positon));
        imgView2.startAnimation(transanim);
   }});

No comments: