LoginSignup
3
1

More than 5 years have passed since last update.

AndroidでrealmとRecyclerViewを使っているときにrowのanimationをしたかったが諦めた話

Posted at

環境

  • realm : io.realm:realm-gradle-plugin:2.2.0
  • kotlin : org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.6

はじめに

Androidほぼ初心者です。のでお手柔らかに..
RecyclerRecycle と書いてしまうのがなかなか抜けない..

なにをしたか

RealmとRecyclerViewを使っているときに、 データの削除(モデル的には更新)をしたときにRowのAnimationを走らせたかったんですが色々あってやらなかったっていう話です。

はじめに?

AndroidでRecyclerViewのRowに対して 追加, 更新, 移動, 削除 のアニメーションをするためには以下の方法が正攻法なのかなと感じました。

  • android.support.v7.widget.RecyclerView.ItemAnimator を継承したサブクラスを作る
  • 必要なメソッドをoverrideする
  • やりたい操作に対応して、Adapterの notifyDataSetChanged 以外 の通知メソッドを呼び出す(※1)
  • ItemAnimatorのサブクラスにイベントが降ってくる。

※1: RecyclerViewのデータ操作通知メソッド

notifyItemChanged / notifyItemRangeChanged
notifyItemInserted / notifyItemRangeInserted
notifyItemMoved
notifyItemRemoved / notifyItemRangeRemoved

ItemAnimatorのサブクラス

今回は SimpleItemAnimatorを採用することにしました。

A wrapper class for ItemAnimator that records View bounds and decides whether it should run move, change, add or remove animations. This class also replicates the original ItemAnimator API.

公式Documentにもあるように ItemAnimatorを使いやすくwrapしてくれたクラスらしいので凝ったことをしないのであればこれで十分だと思ったからです。

次に必要なメソッド群を実装しました。

class MainTimelineRowAnimator : SimpleItemAnimator() {

  override fun runPendingAnimations() {...}
  override fun animateAdd(holder: RecyclerView.ViewHolder?): Boolean {...}
  override fun animateChange(oldHolder: RecyclerView.ViewHolder?, newHolder: RecyclerView.ViewHolder?, fromLeft: Int, fromTop: Int, toLeft: Int, toTop: Int): Boolean {...}
  override fun animateMove(holder: RecyclerView.ViewHolder?, fromX: Int, fromY: Int, toX: Int, toY: Int): Boolean {...}
  override fun animateRemove(holder: RecyclerView.ViewHolder?): Boolean {...}
  override fun isRunning(): Boolean {...}
  override fun endAnimation(item: RecyclerView.ViewHolder?) {...}
  override fun endAnimations() {...}
}

RecyclerViewのItemAnimatorの解説は この記事が非常にわかりやすかったです。

ここまでのまとめ

RecyclerViewでRowのAnimationをしたければ、 データセットの削除をした後に notifyItemXXX 系のメソッドを呼んであげればよさそうです。

ここでrealm

realmをRecyclerViewで使うには RealmRecyclerViewAdapter を使っています。 では、ここの実装を見てみることにしましょう。

// Right now don't use generics, since we need maintain two different
// types of listeners until RealmList is properly supported.
// See https://github.com/realm/realm-java/issues/989
this.listener = hasAutoUpdates ? new RealmChangeListener() {
    @Override
    public void onChange(Object results) {
        notifyDataSetChanged();
    }
} : null;

Githubでも議論されているように、まだ細かい通知には対応していないと書いてあります。
なのでActivity, Fragment側で notifyItemRemoved() を呼んでも反応しないわけですね..。

3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1