Androidリストビューの追加または削除をアニメーション化する方法


Question

iOSでは、UITableViewの行の追加や削除をアニメーション化するための非常に簡単で強力な機能があります。 ここには、デフォルトのアニメーションを表示するYouTubeビデオのクリップがあります。 周囲の行が削除された行にどのように崩壊するかに注意してください。 このアニメーションは、ユーザーがリスト内で変更された内容と、データが変更されたときにリスト内のどこを見ていたかを把握するのに役立ちます。

私はAndroidで開発してきたので、 TableView個々の行をアニメーション化する同等の機能は見つけられませんTableView 。 アダプタ上でnotifyDataSetChanged()を呼び出すと、ListViewはコンテンツを新しい情報で直ちに更新します。 私は、データが変更されたときに新しい行が押し込まれたり滑ったりする簡単なアニメーションを表示したいと思いますが、これを行うための文書化された方法は見つかりません。 LayoutAnimationControllerがこれを動作させるための鍵を保持しているようですが、ListViewにLayoutAnimationControllerを設定すると( ApiDemoのLayoutAnimation2に似ています)、リストが表示された後にアダプタから要素を削除すると、要素はアニメーション化されるのではなく、 。

また、削除された個々のアイテムをアニメートするために、次のようなことを試みました。

@Override
protected void onListItemClick(ListView l, View v, final int position, long id) {
    Animation animation = new ScaleAnimation(1, 1, 1, 0);
    animation.setDuration(100);
    getListView().getChildAt(position).startAnimation(animation);
    l.postDelayed(new Runnable() {
        public void run() {
            mStringList.remove(position);
            mAdapter.notifyDataSetChanged();
        }
    }, 100);
}

ただし、アニメーション行を囲む行は、 notifyDataSetChanged()が呼び出されたときに新しい位置にジャンプするまで、位置を移動しません。 ListViewは、要素が配置された後はそのレイアウトを更新しません。

私自身の実装/ ListViewのフォークを書くことが私の頭を越えていますが、これはそれほど難しいものではないようです。

ありがとう!




ListViewsは高度に最適化されているので、これは不可能であると私は考えている。 あなたはコードであなたの "ListView"を作成しようとしましたか(つまり、xmlからあなたの行を膨張させ、それらをLinearLayout追加してアニメーション化することLinearLayout )?




別のアプローチを共有するだけです。

まず、リストビューのandroid:animateLayoutChangestrueに 設定ます

<ListView
        android:id="@+id/items_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"/>

次に、 ハンドラを使用して項目を追加し、リストビューを遅延で更新します。

Handler mHandler = new Handler();
    //delay in milliseconds
    private int mInitialDelay = 1000;
    private final int DELAY_OFFSET = 1000;


public void addItem(final Integer item) {
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mDataSet.add(item);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mAdapter.notifyDataSetChanged();
                        }
                    });
                }
            }).start();

        }
    }, mInitialDelay);
    mInitialDelay += DELAY_OFFSET;
}



ListViewに新しい行を挿入した後、ListViewを新しい位置にスクロールするだけです。

ListView.smoothScrollToPosition(position);



私は自分のサイトで私のアプローチを説明していたので、私はリンクを共有しました。いずれにしても、getdrawingcacheによってビットマップを作成しています.2つのビットマップを持ち、

次のコードを参照してください:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {
        public void onItemClick(AdapterView<?> parent, View rowView, int positon, long id)
        {
            listView.setDrawingCacheEnabled(true);
            //listView.buildDrawingCache(true);
            bitmap = listView.getDrawingCache();
            myBitmap1 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), rowView.getBottom());
            myBitmap2 = Bitmap.createBitmap(bitmap, 0, rowView.getBottom(), bitmap.getWidth(), bitmap.getHeight() - myBitmap1.getHeight());
            listView.setDrawingCacheEnabled(false);
            imgView1.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap1));
            imgView2.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap2));
            imgView1.setVisibility(View.VISIBLE);
            imgView2.setVisibility(View.VISIBLE);
            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            lp.setMargins(0, rowView.getBottom(), 0, 0);
            imgView2.setLayoutParams(lp);
            TranslateAnimation transanim = new TranslateAnimation(0, 0, 0, -rowView.getHeight());
            transanim.setDuration(400);
            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);
                }
            });
            array.remove(positon);
            adapter.notifyDataSetChanged();
            imgView2.startAnimation(transanim);
        }
    });

画像で理解するために、 これを見てください

ありがとう。




Androidはオープンソースなので、実際にはListViewの最適化を再実装する必要はありません。 ListViewのコードを取得してアニメーションをハックする方法を見つけようとすると、アンドロイドバグトラッカーで機能要求開くこともできます(実装することを決めた場合は、パッチ提供することを忘れないでください)。

参考までに、ListViewのソースコードはhereです。




呼び出しlistView.scheduleLayoutAnimation(); リストを変更する前に




Related