恋人専用SNSアプリCouplesに追加されたThinking of you機能の実装方法

thinkinfOfYou-og

こんにちは!恋人専用SNSアプリCouplesのAndroid版開発を担当している二川です。
この記事では、恋人を想う気持ちを1タップで伝えられる機能で押す長さによって大きさを変えられたり、隠し機能もあったりと、「2人のコミュニケーションをさらに楽しいものにしたい」という想いを込めて開発したThinking of you機能をご紹介します!!

Thinking of you機能とは

Thinking of you機能とは簡単にまとめると下記のような機能です。

  • パートナーに1タップでハートを届けられる機能
  • FacebookMessengerのいいね!のハート版のイメージ

実際の動きはこのようになっています。

CouplesThinkingOfYouAnimation1
CouplesThinkingOfYouAnimation2

実装

実装方法について説明していきます。

全体の流れ

まずはアニメーションの全体の流れを説明します。
ハートボタンのACTION_DOWNをキックにして震えながら拡大するアニメーションが始まります。
ボタンから手を離したタイミングで、アニメーションに使っているInterpolatorを変更してバウンドアニメーションに変更します。
途中で手を離さずに規定の時間をすぎるまで拡大したらハートが拡散するアニメーションを実行します。

全体の流れを表すコードです。

animator = ValueAnimator.ofInt(0, animationTime);
animator.setDuration(animationTime);
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int milliseconds = (Integer) animation.getAnimatedValue();
if (ACTION_UP) {
// ボタンから手を離したらバウンドアニメーションに変更させる
animator.setInterpolator(new HeartBounceInterpolator());
}
// 震えながら拡大するアニメーション
increaseHeart(milliseconds);
}
});
animator.addListener(new AnimatorListener() {
boolean canceled = false;
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if(!canceled){
// ハートが拡散するアニメーション開始
heartEmit();
}
}
@Override
public void onAnimationCancel(Animator animation) {
canceled = true;
}
});
animator.setInterpolator(new DecelerateInterpolator(1.4f));
animator.start();

震えながら拡大するアニメーション

震えながら拡大するアニメーションはincreaseHeart(milliseconds)のメソッド内で時間経過によって変化するパラメーターを更新し、
ViewのonDraw(canvas)で毎回描画していくことで実現しています。

パラメーターを更新するコードです。

public boolean increaseHeart(long milliseconds) {
float shakeDegree = (rotationSpeed * milliseconds / 1000) % maxDegree;
float futureDegree = curShakeDegree + shakeDirection * shakeDegree;
if (shakeDirection > 0 && futureDegree > maxDegree) {
// 反時計回りに動きを変更する
shakeDirection = -shakeDirection;
} else if (shakeDirection < 0 && futureDegree < maxDegree) {
// 時計回りに動きを変更する
shakeDirection = -shakeDirection;
}
curShakeDegree += shakeDirection * shakeDegree;
rotation = curShakeDegree;
scale = 1.0f * milliseconds / animationDuration;
currentX = initialX - bitmapHalfWidth * scale;
currentY = initialY - bitmapHalfHeight * scale;
}

指を離した後にバウンドするアニメーション

ハートボタンから指を離したACTION_UPが呼ばれるタイミングで、AnimatorのInterpolatorを変更することで
震えながら拡大するアニメーションからバウンドアニメーションへ変更させます。

バウンドアニメーションを実現させるためのInterpolatorのコードです。
こちらの記事を参考に作成しました。Qiita 変なInterpolatorの使い方

public class HeartBounceInterpolator implements TimeInterpolator {
private static final float SLOPE = 20.0f;
private float mStartX = -1.0f;
private float mAdjustX = 0.0f;
@Override
public float getInterpolation(float input) {
if (mStartX == -1.0f) {
mStartX = input;
mAdjustX = initAdjustX(input);
}
input += mAdjustX;
if (input < 0.0495f + mStartX) {
// y = 20x
// 上記の式を拡大アニメーション中のACTION_UPのタイミングのinput分x軸+方向にずらした式
return SLOPE * (input - mStartX);
} else if (input < 0.1512f + mStartX) {
// y = bounce(3x - 0.3) * 8 + 0.9
// 上記の式を拡大アニメーション中のACTION_UPのタイミングのinput分x軸+方向にずらした式
return bounce(3.0f * (input - mStartX) - 0.3f) + 0.9f;
} else {
// 1.0fを返してアニメーションを終了させる
return 1.0f;
}
}
private static float bounce(float t) {
return t * t * 8.0f;
}
private float initAdjustX(float x) {
return (float) (1.0f - Math.pow((1.0f - x), 2.0f * 1.4f)) / SLOPE;
}
}

バウンドアニメーションを作成するにあたって、数値の調整にはGrapherというmacに標準でインストールされているアプリを使いました。
Grapherを使うと2次方程式のグラフが簡単にかけるのでInterpolatorを使ったアニメーションを作る際にはおすすめです。
今回のThinking of youでは下記のように作成しました。

graph

ハートが拡散するアニメーション

このアニメーションにはplattysoft/Leonidsというライブラリーを利用しました。

拡散するオブジェクトのScaleやSpeedの範囲を設定するだけでいい感じの拡散アニメーションを作ることが可能です。
細かいプロパティは記載していませんが、CouplesのThinking of youの最後のハートが拡散するアニメーションは下記のようなコードで実現しています。

// drawableResIdで指定した画像をmaxParticlesの数拡散させる
ParticleSystem Particle = new ParticleSystem(Activity, maxParticles, drawableResId, duration)
.setScaleRange(min, max)
.setSpeedRange(min, max)
.setRotationSpeedRange(min, max)
.setAcceleration(acceleration, angle)
.setFadeOut(duration, new DecelerateInterpolator());
// viewの位置に拡散アニメーションを発生させる
particle.emit(view, particlesPerSecond, emittingTime);

おわりに

Thinking of you機能のアニメーションについてご紹介しました。
Interpolatorを使ったアニメーションの作成を覚えることで、複雑なアニメーションもかなりシンプルに書くことができるのでおすすめです。
今回はBounceInterpolatorを参考にカスタマイズしましたが、他にもたくさん標準で用意されたInterpolatorがあります。
Interpolator | Android Developers
これらを参考に自分好みのアニメーションを作っていくのも楽しいのではないでしょうか。
コミュニケーションを盛り上げるかわいいアニメーションを作りたい!と思った方はぜひオフィスに遊びにきてみてください!