酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Androidでセルの並び替えをおこなえるライブラリ「ListViewAnimations」を導入する

iOSのUITableViewのスワイプやセルの並び替えみたいな挙動をAndroidで実現するための「ListViewAnimations」というライブラリがあります。

下記のリポジトリに、ListViewAnimationsのDynamicListViewを実装したものを公開しておきました。GitHubの実装がそのままなのであまり参考にならないかもしれませんが、ダウンロードして実行すれば動きます。

ListViewAnimationsの導入

適当に作成したプロジェクトのapp/build.gradleにListViewAnimations関係のライブラリを諸々追加しておきます。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'

    compile 'com.jakewharton:butterknife:6.1.0'

    compile 'com.nhaarman.listviewanimations:lib-core:3.1.0@aar'
    compile 'com.nhaarman.listviewanimations:lib-manipulation:3.1.0@aar'
    compile 'com.nhaarman.listviewanimations:lib-core-slh:3.1.0@aar'
    compile 'com.nineoldandroids:library:2.4.0'
}

MainActivity#onCreate(Bundle)listViewに対してAdapterを設定します。

/* Setup the adapter */
listAdapter = new ListAdapter(this);
SimpleSwipeUndoAdapter simpleSwipeUndoAdapter = new SimpleSwipeUndoAdapter(listAdapter,
        this, new OnDismissCallback() {
    @Override
    public void onDismiss(@NonNull ViewGroup listView, @NonNull int[] reverseSortedPositions) {

    }
});
AlphaInAnimationAdapter animAdapter = new AlphaInAnimationAdapter(simpleSwipeUndoAdapter);
animAdapter.setAbsListView(listView);
assert animAdapter.getViewAnimator() != null;
animAdapter.getViewAnimator().setInitialDelayMillis(300);
listView.setAdapter(animAdapter);

/* Enable drag and drop functionality */
listView.enableDragAndDrop();
listView.setDraggableManager(new TouchViewDraggableManager(R.id.list_row_draganddrop_touchview));
listView.setOnItemMovedListener(new OnItemMovedListener() {
    @Override
    public void onItemMoved(int originalPosition, int newPosition) {
        // リストの並び替え後に実行される
    }
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        if (listView != null) {
            listView.startDragging(position);
            return true;
        }
        return false;
    }
});

OnItemMovedListener#onItemMoved(int,int)はリストでの並び替え後に実行されます。ここでは何も処理していませんが、実際のアプリ開発ではこのタイミングでデータベースを書き換えると良いかもしれません。

セルを長押しして(ホールドして)、ドラッグアンドドロップでセルを移動させることができるようになりました。

f:id:ch3cooh393:20160507011011p:plain

トラブルシューティング

導入にあたって大きな問題のないListViewAnimationsですが、GitHubの指定通りに実装していると実行時にクラッシュしてしまいました。

D/Error: ERR: stack=java.lang.NoClassDefFoundError: Failed resolution of: [Lcom/nineoldandroids/animation/Animator;
      at com.nhaarman.listviewanimations.appearance.AnimationAdapter.animateViewIfNecessary(AnimationAdapter.java:174)
      at com.nhaarman.listviewanimations.appearance.AnimationAdapter.getView(AnimationAdapter.java:145)
      at android.widget.AbsListView.obtainView(AbsListView.java:2347)
      at android.widget.ListView.measureHeightOfChildren(ListView.java:1270)
      at android.widget.ListView.onMeasure(ListView.java:1182)
      at android.view.View.measure(View.java:17547)
      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
      at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)

GitHubのページに書いている通りだと内部的に使用しているライブラリが足りていないみたいです。app/build.gradlecom.nineoldandroids:libraryを追加しておく必要があります。

dependencies {
    
    // ...
    
    compile 'com.nhaarman.listviewanimations:lib-core:3.1.0@aar'
    compile 'com.nhaarman.listviewanimations:lib-manipulation:3.1.0@aar'
    compile 'com.nhaarman.listviewanimations:lib-core-slh:3.1.0@aar'
    compile 'com.nineoldandroids:library:2.4.0'
}