FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

DroidKaigiで発表中にスライドがフリーズした話

次はGoogleスライドで作ろう…。

GANMA!開発チームのゆのうえです。 先日DroidKaigi 2017にて「実践アニメーション」という講義をさせていただきました。 発表資料はこちらになります。

事前に宣伝等しなかったこともあり、大部屋の半分程度埋まればいいかな、と軽く考えていたところ、予想に反して座席がほぼ埋まる盛況となってしまい、自分はつくづく見積もりが甘いなあと実感しました。決して言うまいと思っていた「緊張してます」宣言をのっけからやってしまうなど、始終余裕のない発表となってしまったと思います。未熟な登壇者の話を最後まで聞いていただいた来場者の方々には感謝が尽きません。それと同時に、アニメーションに関心のある人がこんなにもいるのか、という事に驚きました。内容自体、特に目新しいことのない技法の説明だったので、革新的な何かを期待していた方には満足のいかない内容だったかと思っています。事前に詳細な概要を出しておくべきだったというのも反省点です。

タイトルの事件ですが、講義の終盤に発生しました。 スライドはLibreOffice Impressで作成していたのですが、自分のSurfaceではハードウェアアクセラレーションを無効にしないとフルスクリーン表示した際にうまく表示できないという事態が前日に発覚しまして、その関係でアニメーションgifがもたついたりフリーズしたりという状況が起こったようです。 こんなこともあろうかと事前にSlackへノートをコピペしてあったため、講義の残りはスマホを見ながら(しどろもどろでしたが)続けることができました。備えはいくらあってもいいものですね。

それでは今回は講義の内容について、少し補足したいと思います。

TypeEvaluatorを実装してみる

ValueAnimator.setValues()の説明をした際に、TypeEvaluatorについて触れました。これは

T evaluate (float fraction, 
                T startValue, 
                T endValue)

というメソッドのみを持つ非常にシンプルなインターフェースです。 このメソッドについて公式リファレンスには

The calculation is a simple parametric calculation: result = x0 + t * (x1 - x0), where x0 is startValue, x1 is endValue, and t is fraction.

と説明されています。 つまりfractionが0から1.0まで変化するので、それに合わせてstartValueからendValueへと遷移させる関数を実装すればいいわけです。 それでは実際に実装してみましょう。

Material Designでよく見かけるのはPath自体がアニメーションするアイコンです。 TypeEvaluatorを使えば、Pathの変形も表現できそうです。 試しに四角形を変形させるTypeEvaluatorを作ってみます。 まずは4つの座標を持つ四角形クラスを作成します。

public class Quadrangle {

    private Point point1;
    private Point point2;
    private Point point3;
    private Point point4;

    public Quadrangle(Point point1, Point point2, Point point3, Point point4) {
        this.point1 = point1;
        this.point2 = point2;
        this.point3 = point3;
        this.point4 = point4;
    }
    // getter省略

これの各座標を評価するTypeEvaluatorを作成します。

public class QuadrangleEvaluator implements TypeEvaluator<Quadrangle> {

    @Override
    public Quadrangle evaluate(float fraction, Quadrangle startValue, Quadrangle endValue) {

        Point point1 = evaluatePoint(fraction, startValue.getPoint1(), endValue.getPoint1());
        Point point2 = evaluatePoint(fraction, startValue.getPoint2(), endValue.getPoint2());
        Point point3 = evaluatePoint(fraction, startValue.getPoint3(), endValue.getPoint3());
        Point point4 = evaluatePoint(fraction, startValue.getPoint4(), endValue.getPoint4());

        return new Quadrangle(point1, point2, point3, point4);
    }

    private Point evaluatePoint(float fraction, Point startPoint, Point endPoint) {
        return new Point(
                (int) (startPoint.x + fraction * (endPoint.x - startPoint.x)),
                (int) (startPoint.y + fraction * (endPoint.y - startPoint.y))
        );
    }
}

使うときはValueAnimatorにこのEvaluatorと初期値(startValue)、目標値(endValue)としてQuadrangleを設定します。

ValueAnimator animator = ValueAnimator.ofObject(new QuadrangleEvaluator(), startValue, endValue);

これだけです。

実装のサンプルはこちらです。 ちゃんと四角形をなめらかに変形させることができました。 f:id:n_yunoue:20170313035324g:plain

DroidKaigi 2017が終わって

反省点は尽きませんが、アフターパーティーで講義を聞いてくださった何人かの方から良い講義だったというお言葉を頂けたのがとても嬉しかったです(僕は社交辞令を本気にするタイプです)。 来年もぜひ発表したいと思えました。 開催に関わった方々、そして参加者の皆様、本当にありがとうございました。