Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
スタディサプリENGLISHの今と攻めの開発 ~MotionLayout入れてみた~
Search
Yuki Mima
February 05, 2020
Programming
0
1.6k
スタディサプリENGLISHの今と攻めの開発 ~MotionLayout入れてみた~
Yuki Mima
February 05, 2020
Tweet
Share
More Decks by Yuki Mima
See All by Yuki Mima
RecyclerViewで 折れ線グラフを作る
amyu
2
410
Sliceのアレコレ
amyu
1
150
ビルド時間を1分短くするためにやったこと
amyu
0
780
ミスを少なくする明日からのCustom Lint Rules
amyu
0
1.9k
Other Decks in Programming
See All in Programming
テストコード文化を0から作り、変化し続けた組織
kazatohiei
2
1.5k
Webエンジニア主体のモバイルチームの 生産性を高く保つためにやったこと
igreenwood
0
340
php-conference-japan-2024
tasuku43
0
330
Security_for_introducing_eBPF
kentatada
0
110
毎日13時間もかかるバッチ処理をたった3日で60%短縮するためにやったこと
sho_ssk_
1
180
たのしいparse.y
ydah
3
120
テストコードのガイドライン 〜作成から運用まで〜
riku929hr
5
740
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
220
Kaigi on Railsに初参加したら、その日にLT登壇が決定した件について
tama50505
0
100
Beyond ORM
77web
7
970
SymfonyCon Vienna 2025: Twig, still relevant in 2025?
fabpot
3
1.2k
ドメインイベント増えすぎ問題
h0r15h0
2
360
Featured
See All Featured
Making Projects Easy
brettharned
116
5.9k
A Philosophy of Restraint
colly
203
16k
Optimizing for Happiness
mojombo
376
70k
Keith and Marios Guide to Fast Websites
keithpitt
410
22k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
28
2.1k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
How To Stay Up To Date on Web Technology
chriscoyier
789
250k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
66k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
28
900
Transcript
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ スタディサプリENGLISHの今と攻めの開発 ~MotionLayout入れてみた~ @amyu Study Sapuri/Quipper Product Meetup #4
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ Agenda | About me スタディサプリENGLISH for Androidの今 MotionLayoutの活用
まとめ 01 02 03 04 2
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ About me 01 3
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ 美馬 優貴 - 2016~社会人 - Android - Github:
amyu - Twitter: @amyu_san 4
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ 5
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ スタディサプリENGLISHの今 02 6
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ スタディサプリENGLISH for Android ➔ 2016年末に開発を開始 ➔ 2017年5月 Kotlin正式サポート
◆ Android Oが発表された ◆ Android Studio 3.0, Architecture Component... ➔ 2017年8月 TOEIC®L&R TEST対策コース をリリース ➔ 2018年5月 ◆ AAB, Jetpack, androidx, AS3.2, Android P, MotionLayout ➔ ... 7
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ スタディサプリENGLISH for Android ➔ Module数: 37 ◆ 機能単位で切られている
◆ ビルドはかなり早い方 ➔ Kotlin率: 75.1% ◆ (Javaは11%) ➔ リリースは当たり前の AAB ➔ Gradle6.0.1, AGP3.5.3, ConstraintLayout, Retrofit, Threetenbp, Dagger, RxJava… ➔ 意味のあるテストコードをしっかり書いてる 8
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ その時点の素晴らしいコードでも 時代とともに負債になってしまう 9
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ MotionLayoutの活用 03 10
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ Before ➔ 横向き、 縦向き対応、 横向き時Transition(Animation)、 縦向き時 Transition(Animation)の4パターンをコードでベタ書きしていた ◆
さらにPdfがあるとき、ないときなど条件が複雑 ➔ UI層(Fragment)で300行くらい関連コードがあった ➔ 全体的に負債が溜まっていたわけではない 12
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ After 縦向き ➔ 開閉TransitionをMotionLayoutへ任せることに より、ロジックから isOpen などの変数を削除でき る
➔ 地味な 矢印 のAnimationもMotionLayoutの Scene xmlへ記述することでスッキリ ◆ 特に clickAction の toggle が便利 13 あとのスライドで実際の Scene xmlを出します
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ After 横向き 14 あとのスライドで実際の Scene xmlを出します ➔ Controllerの出し分けTransitionを
MotionLayoutへ任せることにより、ロジックか ら isVisibleController などの変数を削除でき る ➔ clickAction の toggle が便利
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ After 15 ➔ UI層(Fragment)のTransitionやAnimation, 画面回転の記述が0に ➔ 新規に作ったMovieViewも77行 ➔
関心事が分離できた
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ 実装方法 16 ➔ MotionLayoutのScene XMLを2つ用意 ◆ 縦向き時 ◆
横向き時 ➔ MovieViewはonConfigurationChanged の発火でScene XMLを切り替 えるだけ
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="wrap_content" > <androidx.constraintlayout.motion.widget.MotionLayout app:layoutDescription="@xml/scene_movie_portrait" tools:showPaths="true" > <TextureView android:id="@+id/high_vision_texture_view" /> <jp.eigosapuri.ecp.android.movie.ui.PlaybackControlView android:id="@+id/playback_control_view" /> <ImageView android:id="@+id/open_close_button" /> </androidx.constraintlayout.motion.widget.MotionLayout> </FrameLayout>
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetEnd="@+id/scene_movie_end"
motion:constraintSetStart="@+id/scene_movie_start" motion:duration="500"> <OnClick motion:clickAction="toggle" motion:targetId="@+id/open_close_button" /> </Transition> <ConstraintSet android:id="@+id/scene_movie_start"> <Constraint android:id="@+id/high_vision_texture_view"> <Layout motion:layout_constraintTop_toTopOf="parent" /> </Constraint> <Constraint android:id="@+id/open_close_button" android:rotation="0" /> </ConstraintSet> <ConstraintSet android:id="@+id/scene_movie_end"> <Constraint android:id="@+id/high_vision_texture_view"> <Layout motion:layout_constraintBottom_toTopOf="parent" /> </Constraint> <Constraint android:id="@+id/open_close_button" android:rotation="180" /> </ConstraintSet> </MotionScene>
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <Transition motion:constraintSetEnd="@+id/scene_movie_end" motion:constraintSetStart="@+id/scene_movie_start" motion:duration="500"> <OnClick motion:clickAction="toggle" motion:targetId="@+id/open_close_button" />
</Transition> <ConstraintSet android:id="@+id/scene_movie_start"> </ConstraintSet> <ConstraintSet android:id="@+id/scene_movie_end"> </ConstraintSet>
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <ConstraintSet android:id="@+id/scene_movie_start"> <Constraint android:id="@+id/high_vision_texture_view"> <Layout motion:layout_constraintTop_toTopOf="parent" /> </Constraint>
</ConstraintSet> <ConstraintSet android:id="@+id/scene_movie_end"> <Constraint android:id="@+id/high_vision_texture_view"> <Layout motion:layout_constraintBottom_toTopOf="parent" /> </Constraint> </ConstraintSet> start end
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <ConstraintSet android:id="@+id/scene_movie_start"> <Constraint android:id="@+id/open_close_button" android:rotation="0" /> </ConstraintSet> <ConstraintSet
android:id="@+id/scene_movie_end"> <Constraint android:id="@+id/open_close_button" android:rotation="180" /> </ConstraintSet>
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="wrap_content" > <androidx.constraintlayout.motion.widget.MotionLayout app:layoutDescription="@xml/scene_movie_landscape" tools:showPaths="true" > <TextureView android:id="@+id/high_vision_texture_view" /> <jp.eigosapuri.ecp.android.movie.ui.PlaybackControlView android:id="@+id/playback_control_view" /> <ImageView android:id="@+id/open_close_button" /> </androidx.constraintlayout.motion.widget.MotionLayout> </FrameLayout>
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetEnd="@+id/scene_movie_landscape_end"
motion:constraintSetStart="@+id/scene_movie_landscape_start" motion:duration="500"> <OnClick motion:clickAction="toggle" motion:targetId="@+id/high_vision_texture_view" /> </Transition> <ConstraintSet android:id="@+id/scene_movie_landscape_start"> <Constraint android:id="@+id/playback_control_view"> <Layout motion:layout_constraintBottom_toBottomOf="parent" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/scene_movie_landscape_end"> <Constraint android:id="@+id/playback_control_view"> <Layout motion:layout_constraintTop_toBottomOf="parent" /> </Constraint> </ConstraintSet> </MotionScene>
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <Transition motion:constraintSetEnd="@+id/scene_movie_landscape_end" motion:constraintSetStart="@+id/scene_movie_landscape_start" motion:duration="500"> <OnClick motion:clickAction="toggle" motion:targetId="@+id/high_vision_texture_view" />
</Transition> <ConstraintSet android:id="@+id/scene_movie_landscape_start"> </ConstraintSet> <ConstraintSet android:id="@+id/scene_movie_landscape_end"> </ConstraintSet>
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ <ConstraintSet android:id="@+id/scene_movie_landscape_start"> <Constraint android:id="@+id/playback_control_view"> <Layout motion:layout_constraintBottom_toBottomOf="parent" /> </Constraint>
</ConstraintSet> <ConstraintSet android:id="@+id/scene_movie_landscape_end"> <Constraint android:id="@+id/playback_control_view"> <Layout motion:layout_constraintTop_toBottomOf="parent" /> </Constraint> </ConstraintSet> start end
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) motionLayout.transitionToStart() when
(newConfig?.orientation) { Configuration.ORIENTATION_LANDSCAPE -> { motionLayout.loadLayoutDescription(R.xml.scene_movie_landscape) motionLayout.setTransition(R.id.scene_movie_landscape_start, R.id.scene_movie_landscape_end) } Configuration.ORIENTATION_PORTRAIT -> { motionLayout.loadLayoutDescription(R.xml.scene_movie) motionLayout.setTransition(R.id.scene_movie_start, R.id.scene_movie_end) } } }
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) motionLayout.transitionToStart() when
(newConfig?.orientation) { Configuration.ORIENTATION_LANDSCAPE -> { motionLayout.loadLayoutDescription(R.xml.scene_movie_landscape) motionLayout.setTransition(R.id.scene_movie_landscape_start, R.id.scene_movie_landscape_end) } Configuration.ORIENTATION_PORTRAIT -> { motionLayout.loadLayoutDescription(R.xml.scene_movie) motionLayout.setTransition(R.id.scene_movie_start, R.id.scene_movie_end) } } }
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ まとめ 04 28
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ MotionLayoutについて ➔ まだbeta版だが本番投入しても大丈夫だった ◆ 不具合などは上がってきていない ➔ TransitionやAnimationを直感的に書きなれたXMLでかける ➔
TransitionやAnimationをMotionLayoutにすることで、UI層(Fragmentな ど)がAnimation Helper的な役割から開放される ◆ AnimationやTransitionの状態管理から開放されるだけでもかなりう れしい ◆ clickAction の toggle が便利(3回目) 29
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ 継続的なリファクタリング ➔ 新規案件が始まる前に既存コードの調査、リファクタリングの時間をもらえる ◆ 案件を進める上で障害になりそうなところを先に潰せる ◆ そして将来も開発がしやすいようにしている ➔
日々のキャッチアップをしっかり行う ◆ その時点で最適な技術選択を行えるようにしている 30
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ 弊社、弊チームに来てくれ!!!! 31
#sapurimeetup スタディサプリENGLISHの今と攻めの開発~MotionLayout入れてみた~ ご清聴ありがとうございました 32