6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Drawable.invalidateSelf()とはなにものなのか

Posted at

AnimatableなDrawable自作したときにハマったので。

Drawable

ViewonDraw()にあたる処理だけを切り出した抽象クラスです。
Viewの場合は主にonMeasure()onLayout()onDraw()の3つを担いますが、DrawableonDraw()のみになります。
サイズや配置などは、使う側(View)に委ねられています。

Drawable.invalidateSelf()

View.invalidate()同様、再描画を促すメソッドです。invalidate()Drawable版と思ってかまわないと思います。

とはいえ、DrawableViewと違い、描画しかサポートしていないため、本来再描画を促すことはできません。
ではinvalidateSelf()はどのように再描画可能にしているのか?

これにはDrawable.setCalllback()メソッドが関係しています。

Drawable.setCallback()

setCallback()とはなんなのか?(名前雑すぎて役割が何もつかめないんだけど…)

setCallback()の引数Drawable.Callbackインターフェースは以下のようになっています。

Drawable.Callback
public interface Callback {

    void invalidateDrawable(Drawable who);

    void scheduleDrawable(Drawable who, Runnable what, long when);

    void unscheduleDrawable(Drawable who, Runnable what);
}

Drawable.Callbackの役割は2つinvalidateDrawable()scheduleDrawable()です。

invalidateDrawable()who(SelfにあたるDrawable)がView.invalidate()を要求するコールバックです。
scheduleDrawable()whoが特定の時刻にスケジューリングされたRunnableの実行を要求するコールバックです。

このDrawable.Callbackですが、基本的に実装する必要はありません。というのも、既にViewが実装してくれているからです。1
CustomViewなどでinvalidateSelf()を有効にする場合は、**drawable.setCallback(this)**するだけで構いません。

ここまでで、invalidateSelf()Drawable.Callbackinvalidate()を要求するというメソッドであることがわかります。
invalidateSelf()をするためには準備が必要なんですね。(ハマり)

View.verifyDrawable()

先ほど、ViewDrawable.Callbackを実装しているので、drawable.setCallback(this)するだけでinvalidateSelf()は動くと書きましたが、これだけでは動かないケースが存在します

ViewinvalidateDrawable()の実装では、invalidate()を呼び出せるDrawableを制限しています。
この条件を実装しているのがView.verifyDrawable()です。

デフォルトでは以下のように実装されています。

View.java
@CallSuper
protected boolean verifyDrawable(@NonNull Drawable who) {
    return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
}

background及びforegroundに設定されているdrawable以外のinvalidateDrawable()は承認されません。
ImageViewの場合はこれに加えて、srcにあたるDrawableを追加しています。

つまり場合によっては、setCallback(this)をしてもverifyDrawable()をoverrideし忘れるとinvalidate()されないということです。
気をつけましょう。(2度目のハマり)

注釈

  1. supportライブラリのように、Drawableのラッパーをつくる場合は自前で実装したりするようです

6
1
0

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
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?