Diverse developer blog

株式会社Diverse(ダイバース) 開発者ブログです。

SingleChildScrollViewでアニメーション実装!見せびらかし会レポート #4

こんにちは!Diverse広報担当です。

Diverseでは週に1回、エンジニア同士で「見せびらかし会」を開催しています。

f:id:diverse-tech:20210917162138p:plain
「見せびらかし会」とは、各エンジニアが1週間の中で頑張った開発Tipsを、仲間に向けて発表する場。
各自の知見やノウハウの共有を目的に行っています。”見せびらかす”という仰々しい名前ですが、ちょっとした工夫や改善も大歓迎!というラフな発表会です。

▼過去の見せびらかし会ブログ
見せびらかし会 カテゴリーの記事一覧 - Diverse developer blog

第4回目は、エンジニアoyaさんの”見せびらかし”と、oyaさんが感銘を受けたabuiさんの”見せびらかし”を紹介します。
ぜひお読みください!


▼目次

LIVE配信画面でテキストをアニメーションで出す方法

oyaさんの今週の見せびらかしについて

oya:今回は、YYCのワイワイライブで使える「ワイワイBOX話題アニメーション」について紹介します。
※画面最下部にテキストを出せるアニメーションです。
f:id:diverse-tech:20210921134339g:plain

LIVE配信画面の場合、そもそもいろんな場所にオブジェクトが出されていますよね。
テキストを入れようにも2行以上にするのがそもそも難しく、チームメンバーからも「1行で入れるべき理由」を聞いていました。そういう制限の中で、頑張ってアニメーションを入れました!

どうやってアニメーションを作ったのか?

oya:「SingleChildScrollView」を使って実装しています。
ScrollViewだとWidgetの幅を超えてテキストを表示できるので、今回の用途に合っている方法でした。
ScrollControllerでoffsetを少しずつずらして、アニメーションさせるようにしました。

Scrollだとコンテンツギリギリまでしか表示されません。そこで、サイズや横幅はさらにウィンドウ分を足して、テキストが全部流れたらループするという形にしました。
テキストがWidgetに収まる場合は、アニメーションが再生されないよう設定しています。

f:id:diverse-tech:20210917163809p:plain

文字幅は、フォントサイズとテキストの長さから計算しています。
半角の場合は流れる秒数が変化しますが、LIVE配信をされる方は日本語と絵文字を使う傾向が高いので、問題なさそうです。

実装までの試行錯誤…ある日神が降りてきた!

f:id:diverse-tech:20210917163825p:plain

oya:この仕組みを思いつく前は、全然違うアプローチをしていて Text Widgetで書いていました。
Widgetに収まるとテキストが切れてしまうので、左のマージンを変えてネガティブマージンにしていけば、Text Widgetが伸びて表示されるかな?と考えていたんです。

しかしこの方法を試してみたところ、エラーになりました…。
ネガティブにならないとしても、 Text Widget の幅は決まったものに固定されます。文字が延々と伸びることがなかったので、これでは難しいと判断しました。

f:id:diverse-tech:20210917163846p:plain

次は、Stackに入れて、Positionedで左に移動させていくことを試しました。
しかし、テキストのサイズが固定になってしまい、Widgetの幅から溢れる部分が表示されなくなるという問題があり…。
Stackの領域分の幅だけしかレンダリングされず、長文の場合だと後ろの文字が表示されないんです。

ここまでやったんですが、ScrollViewに入れるという概念が全くなく、作業は1~2日間止まっていました。
それが先日パッと神が舞い降りてきて、今の仕組みを思いついたんです。
いろんな方法を試していたからこそですね。「発想」って大事だなと実感しました!

ー参加者より:Slackのtimes(※)に書いていた「神が降りてきた」はこのことだったんですね(笑)

※DiverseのSlackでは分報(times)チャンネルを運用しています。

UIImageViewのアニメーション実装

oyaさんが感銘を受けたabuiさんの見せびらかしを紹介!

oya:発想といえば、個人的に最近面白いと思ったのがabuiさんの取り組みです。画像が左から出てくるアニメーションの実装がめちゃくちゃ天才的だったので…!ぜひabuiさんの代わりに紹介させてください。

abuiさんは、YYCのチャンスタイムバナーの改善に取り組んでいました。
実装されたのが、「チャンスタイム終了まで」の下の方からニョロニョロっと出てくるアニメーションです。

f:id:diverse-tech:20210921134817g:plain

iOSのUIImageViewを使って、この画像をオリジナルの長さであらかじめ貼っています。
UIImageViewのcontentModeをleftにしてUIImageViewにつけたconstraintsでwidthを0にすると…UIImageViewは伸縮しても画像本来のサイズを裏で表示させ続けることが可能になっています。

どんな仕組みで作ったのか?

oya:contentModeという画像表示を切り替えられるモードがあり、abuiさんは「左に寄せる(left)」という指定をしていました。
最初に、UIImageViewに設定されているconstraintsで、UIImageViewの幅を0にしています。

f:id:diverse-tech:20210917164032p:plain

それから、アニメーションでconstraintsをドンドン大きくして、ImageViewを広げていくことで実現させています。
この発想はすごいな…!とめちゃくちゃ感動しました。

【質問】Androidではこの方法で実装できないのですか?

AndroidのImageViewの場合、iOSのような便利なオプションがありません。
近いオプションはあるのですが、iOSに比べて手間がかかり面倒くさいというデメリットがあります。

その点では、iOSだとUIImageViewの中で、画像描画する範囲を独立させて(UI)ImageView内の左側に寄せるということができます。
そのため、容易に実装可能だったんです。

f:id:diverse-tech:20210917164047p:plain

これはあくまでiOSでの実装方法で、AndroidではImageViewで”contentMode = .left”ができないので、実装は難しそうですね。

最後に

いかがでしたか?
Diverseエンジニアは、見せびらかし会でお互いを刺激し、チームのナレッジ蓄積を図っています。
今後も見せびらかし会を通じて、Diverseエンジニアの裏側を紹介していきます!お楽しみに!


◆Diverseの取り組みに共感いただいた方、エンジニアの働き方に興味がある方、ぜひ弊社の採用ページをご覧ください!

herp.careers