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
実例で理解する Material Design Animation
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Ryo Sakaguchi
February 08, 2018
Programming
9
5.4k
実例で理解する Material Design Animation
DroidKaigi 2018 2/8 Room2
Ryo Sakaguchi
February 08, 2018
Tweet
Share
More Decks by Ryo Sakaguchi
See All by Ryo Sakaguchi
Android Architecture Componentsを使って、改善・効率化するAndroidアプリ開発
wakwak3125
0
1.3k
Test multiple APKs with Robolectric
wakwak3125
0
790
Clip, Elevation and ViewOutlineProvider
wakwak3125
1
1.3k
WebView as Fancy and effective View
wakwak3125
1
1.6k
ViewPager2をちょっとさわってみよう
wakwak3125
0
1.6k
年末だし、振り返るKotlin
wakwak3125
1
1.1k
社内ライブラリのアップデートフロー
wakwak3125
4
3.8k
Wantedly Peopleのリリースフロー
wakwak3125
1
4.7k
KOINかわいいよ、KOIN
wakwak3125
0
970
Other Decks in Programming
See All in Programming
[KNOTS 2026登壇資料]AIで拡張‧交差する プロダクト開発のプロセス および携わるメンバーの役割
hisatake
0
250
責任感のあるCloudWatchアラームを設計しよう
akihisaikeda
3
160
AI巻き込み型コードレビューのススメ
nealle
0
130
ThorVG Viewer In VS Code
nors
0
760
SourceGeneratorのススメ
htkym
0
190
疑似コードによるプロンプト記述、どのくらい正確に実行される?
kokuyouwind
0
380
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
1.8k
AIによるイベントストーミング図からのコード生成 / AI-powered code generation from Event Storming diagrams
nrslib
2
1.8k
2026年 エンジニアリング自己学習法
yumechi
0
130
AtCoder Conference 2025
shindannin
0
1k
コントリビューターによるDenoのすゝめ / Deno Recommendations by a Contributor
petamoriken
0
200
CSC307 Lecture 09
javiergs
PRO
1
830
Featured
See All Featured
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
1.8k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
170
Test your architecture with Archunit
thirion
1
2.1k
The Cult of Friendly URLs
andyhume
79
6.8k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.4k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
0
140
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
310
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.4k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
240
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
57
50k
Rails Girls Zürich Keynote
gr2m
96
14k
Transcript
2018.2.8 ࣮ྫͰཧղ͢Δ Material Design Animation DroidKaigi 2018 Room2 Feb 8th,
2018 Ryo Sakaguchi (wakwak3125)
2018.2.8 Ryo Sakaguchi @wakwak3125 • Wantedly, Inc • Android application
developer • Wantedly People • Music, Guitar, UI/UX About me
2018.2.8 Ryo Sakaguchi @wakwak3125 • Wantedly, Inc • Android application
developer • Wantedly People • Music, Guitar, UI/UX About me
2018.2.8 Wantedly People
2018.2.8 Wantedly People • ໊ཧΞϓϦ • ػցֶशΛ༻͍ͯ͠Δ • ಡΈऔ໊ͬͨɺࣗͷใΛݩ ʹʮʯΛఏڙ͢Δ
• ؾ໊͍͍࣋ͪࡱӨମݧ
2018.2.8 Wantedly People • ໊ཧΞϓϦ • ػցֶशΛ༻͍ͯ͠Δ • ಡΈऔ໊ͬͨɺࣗͷใΛݩ ʹʮʯΛఏڙ͢Δ
• ؾ໊͍͍࣋ͪࡱӨମݧ
2018.2.8 Agenda
2018.2.8 Agenda • ʮʯػೳͷΞχϝʔγϣϯͷհ • ࣮ͷղઆ • Ξχϝʔγϣϯ࣮ͷצॴ • ΞχϝʔγϣϯͷDebug
2018.2.8 ʮʯػೳͷΞχϝʔγϣϯհ
2018.2.8 Article ͷهࣄΛදࣔ͢Δը໘ • ৴͞ΕΔΛදࣔ͢Δը໘ • Ϣʔβʔʹରͯͯ͠͠΄͍͠ʮը૾ʯ Λ࣠ʹΞχϝʔγϣϯ͢Δɻ • RecyclerViewʹΧʔυܕͷΞΠςϜΛฒ
ɺͦΕ͕Expand͢ΔΠϝʔδ • ΧʔυഎܠˠΧόʔΠϝʔδ • هࣄͷ֓ཁ/λΠτϧͷίϯςΩετ Λڞ༗Ͱ͖Δ ʮʯػೳͷΞχϝʔγϣϯհ Article
2018.2.8 Graphic contents ΠϯϑΥάϥϑΟοΫ • ΠϯϑΥάϥϑΟοΫ͕ϝΠϯͷهࣄΛ දࣔ͢Δ • ίϯςϯπࣗମAfterEffectsΛ༻͠ ͯ࡞͠ɺbodymovinΛ༻ͯ͠
WebViewͰ࠶ੜ͍ͯ͠Δ • Χʔυͷഎܠը૾͕શ໘ʹ͕͍ͬͯ͘ • ΧʔυˠهࣄৄࡉͷભҠͰੈք؍ ΛଛͳΘͳ͍ ʮʯػೳͷΞχϝʔγϣϯհ Graphic contents
2018.2.8 Timeline هࣄ͕දࣔ͞ΕΔTimeline • هࣄΛҰཡͰදࣔ͢ΔRecyclerView • Χʔυ͕എܠը૾Λ࣋ͭλΠϓͱ࣋ͨ ͳ͍λΠϓ͕͋Δ • എܠը૾Λ࣋ͭλΠϓͷͷͷ߹ɺ
Timelineͷഎܠશମʹϒϥʔ͕͔͔ͬ ͨͷ͕هࣄͷग़ݱͱڞʹΫϩεϑΣʔ υ͢Δ • ࠓճϝΠϯͰΛ͢ΔͭΓͷɺ SharedElementTransitionͱҧ͏͚ ͲɺҰԠհ ʮʯػೳͷΞχϝʔγϣϯհ Timeline
2018.2.8 ΞχϝʔγϣϯͬͯͳΜͰඞཁͳͷʁ
2018.2.8 ͔͍͍͔ͬ͜Β
2018.2.8 ͔͍͍͔ͬ͜Βʁ ͚ͩ͡Όͳ͍Ͱ͢ • ΞχϝʔγϣϯʹΑͬͯɺϢʔβʔʹ ͯ͠΄͍͠ͷΛΞϐʔϧͰ͖Δ • ͍ͬͯͯɺಥવίϯςϯπ͕ೖΕସ Θͬͨ෩ʹײͯ͡͠·͏Ϣʔβʔډ Δͣɻ
• Βͳ͍ΑΓͬͨ΄͏͕ઈରྑ͍ • Γ͗͢ྑ͘ͳ͍ɻ͚Ͳɺ·ͣ ࡞͔ͬͯΒ͍ͬͯ͘ͷ͕େࣄ • ͪΖΜ͔͍͍ͬͬͯ͜ͷ͋Δʂ ΞχϝʔγϣϯͬͯͳΜͰඞཁͳͷʁ
2018.2.8 ࣮ͷղઆ
2018.2.8 ࣮ͷղઆ • Shared Element Transitionͷجຊͷ ͓͞Β͍ • ֤ػೳ(Article/Graphic contents)
ʹґଘ͠ͳ͍෦ͷڞ௨࣮ͷ • ֤ػೳຖʹߦ͍ͬͯΔಛผͳ෦ͷ • Article • Graphic content
2018.2.8 ·ͣجຊͷ͓͞Β͍
2018.2.8 Transition Name 1/3 ڞ༗͍ͨ͠Viewʹ໊લΛ͚ͭΔ ·ͣجຊͷ͓͞Β͍ Shared Element Transition public
class MainActivity extends AppCompatActivity { ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView( this, R.layout.activity_main ); binding.button.setOnClickListener(v -> goToNextActivity()); } void goToNextActivity() { Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation( this, /*ભҠݩͷActivity*/ binding.imageView, /*ભҠݩͱભҠઌͰڞ༗͍ͨ͠View*/
2018.2.8 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding =
DataBindingUtil.setContentView( this, R.layout.activity_main ); binding.button.setOnClickListener(v -> goToNextActivity()); } Transition Name 2/3 TransitionʹඞཁͳใΛBundleʹ٧Ίͯ͢ ·ͣجຊͷ͓͞Β͍ Shared Element Transition void goToNextActivity() { Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation( this, /*ભҠݩͷActivity*/ binding.imageView, /*ભҠݩͱભҠઌͰڞ༗͍ͨ͠View*/ "transition:image" /*ڞ༗͍ͨ͠ViewͷTransition Name*/ ).toBundle(); ActivityCompat.startActivity( this, new Intent(this, NextActivity.class), bundle); }
2018.2.8 Transition Name 3/3 ભҠઌͷActivityͷڞ༗͍ͨ͠ViewʹTransition NameΛηοτ͢Δ ·ͣجຊͷ͓͞Β͍ Shared Element Transition
this, /*ભҠݩͷActivity*/ binding.imageView, /*ભҠݩͱભҠઌͰڞ༗͍ͨ͠View*/ "transition:image" /*ڞ༗͍ͨ͠ViewͷTransition Name*/ ).toBundle(); ActivityCompat.startActivity( this, new Intent(this, NextActivity.class), bundle); } public class NextActivity extends AppCompatActivity { ActivityNextBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_next); binding.imageView.setTransitionName("transition:image"); } }
2018.2.8
2018.2.8 Default animation theme_material.xmlͰ σϑΥϧτͰҎԼͷΞχϝʔγϣϯ͕ηοτ͞Ε͍ͯΔ ·ͣجຊͷ͓͞Β͍ Shared Element Transition <transitionSet
xmlns:android="http://schemas.android.com/apk/res/android"> <changeBounds/> <changeTransform/> <changeClipBounds/> <changeImageTransform/> </transitionSet> move.xml
2018.2.8 Postpone Transition Transition animationΛҙͷλΠϛϯάͰ։࢝Ͱ͖Δ ·ͣجຊͷ͓͞Β͍ Shared Element Transition public
class NextActivity extends AppCompatActivity { static final Handler sHandler = new Handler(Looper.getMainLooper()); ActivityNextBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_next); binding.imageView.setTransitionName("transition:image"); ActivityCompat.postponeEnterTransition(this); sHandler.postDelayed(() -> ActivityCompat.startPostponedEnterTransition(this), 1000 ); } }
2018.2.8 ࣮ͷղઆ Wantedly PeopleͰ͍ͬͯΔShared Element Transitionͷڞ௨ͳ෦
2018.2.8 ࣮ͷղઆ ڞ௨ͷ෦ .BJO"DUJWJUZ
2018.2.8 ࣮ͷղઆ ڞ௨ͷ෦ .BJO"DUJWJUZ 5JNFMJOF'SBHNFOU
2018.2.8 ࣮ͷղઆ ڞ௨ͷ෦ .BJO"DUJWJUZ 5JNFMJOF'SBHNFOU 1PTU"SUJDMF"DUJWJZ
2018.2.8 ࣮ͷղઆ ڞ௨ͷ෦ .BJO"DUJWJUZ 5JNFMJOF'SBHNFOU 1PTU"SUJDMF"DUJWJZ 1PTU"SUJDMF'SBHNFOU
2018.2.8 ࣮ͷղઆ ڞ௨ͷ෦ .BJO"DUJWJUZ 5JNFMJOF'SBHNFOU 1PTU"SUJDMF"DUJWJZ 1PTU"SUJDMF'SBHNFOU
2018.2.8 ͔͜͜ΒϓϩμΫγϣϯίʔυ ͍Ζ͍Ζͳྺ࢙తͳഎܠͰग़དྷ্͕ͬͯ·͢ɻ ࠓେʹݟͯ΄͍͠ʂ Page Title Page Subtitle
2018.2.8 TimelineFragment ͜ͷFragment͔ΒTransitionΛ։࢝͢Δ /** * @param fragment ભҠݩͷFragment * @param
postKey هࣄͷKey * @param provider TransitionʹඞཁͳViewΛViewHolder͔Βऔͬͯ͘Δ * adapterΛ࣋ͭ */ public void openPost(BaseFragment fragment, String postKey, PostLogic.ITransitionAdapterProvider provider) { PostArticleFragment nextFragment = PostArticleFragment.newInstance(postKey); TransitionExtra extra = new TransitionExtra.Builder().build(); ࣮ͷղઆ ڞ௨ͷ෦ // ରͱͳΔViewͱTransition nameͷPairͷListΛ࡞Δ List<Pair<View, String>> pairList = new ArrayList<>(); if (provider != null) { PostLogic.TransitionAdapter adapter = provider.getTransitionAdapter(); // Viewʹରͯ͠ Transition nameΛ༩͍͑ͯ͘
2018.2.8 TimelineFragment ͜ͷFragment͔ΒTransitionΛ։࢝͢Δ * @param provider TransitionʹඞཁͳViewΛViewHolder͔Βऔͬͯ͘Δ * adapterΛ࣋ͭ */
public void openPost(BaseFragment fragment, String postKey, PostLogic.ITransitionAdapterProvider provider) { PostArticleFragment nextFragment = PostArticleFragment.newInstance(postKey); TransitionExtra extra = new TransitionExtra.Builder().build(); ࣮ͷղઆ ڞ௨ͷ෦ // ରͱͳΔViewͱTransition nameͷPairͷListΛ࡞Δ List<Pair<View, String>> pairList = new ArrayList<>(); if (provider != null) { PostLogic.TransitionAdapter adapter = provider.getTransitionAdapter(); // Viewʹରͯ͠ Transition nameΛ༩͍͑ͯ͘ pairList.add(Pair.create( adapter.getCoverImage(), fragment.getString(R.string.transition_image_cover))); // ଞʹView͕͋Ε͜͜Ͱηοτ͍ͯ͘͠... } //TransitionExtraʹpairListΛ͢ extra.setSharedElementPair(pairList); // BaseFragment͕ը໘ભҠΛߦ͏ؔΛ͍࣋ͬͯΔͷͰͦΕΛݺͼग़͢ fragment.replaceFragment(nextFragment, extra);
2018.2.8 BaseFragment replaceFragment ࣮ͷղઆ ڞ௨ͷ෦ public void replaceFragment(@NonNull BaseFragment fragment,
@Nullable TransitionExtra extra) { // BaseActivity͕listenerΛ࣮͍ͯ͠ΔͷͦͪΒʹϦϨʔ͢Δ getListener().replaceFragment(fragment, extra); }
2018.2.8 BaseActivity replaceFragment ࣮ͷղઆ ڞ௨ͷ෦ @Override public void replaceFragment(BaseFragment fragment,
@Nullable TransitionExtra extra) { if (extra != null) { Intent intent = PostArticleActivity.createIntent(this); Pair<View, String>[] sharedElements; if (!isEmpty(extra.getSharedElementPair())) { sharedElements = new Pair[extra.getSharedElementPair().size()]; for (int i = 0; i < extra.getSharedElementPair().size(); i++) { Pair<View, String> pair = extra.getSharedElementPair().get(i); if (pair.first != null && pair.second != null) { sharedElements[i] = pair; } } } else { sharedElements = new Pair[0]; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { ActivityOptionsCompat options =
2018.2.8 BaseActivity replaceFragment ࣮ͷղઆ ڞ௨ͷ෦ new Pair[extra.getSharedElementPair().size()]; for (int i
= 0; i < extra.getSharedElementPair().size(); i++) { Pair<View, String> pair = extra.getSharedElementPair().get(i); if (pair.first != null && pair.second != null) { sharedElements[i] = pair; } } } else { sharedElements = new Pair[0]; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, sharedElements); ActivityCompat.startActivity(this, intent, options.toBundle()); } else { startActivity(intent); } } else { /*͔͜͜ΒFragmentͰ։͘߹ͷॲཧ*/ }
2018.2.8 PostArticleActivity TransitionΛҰ࣌ఀࢭ͢Δ ࣮ͷղઆ ڞ௨ͷ෦ @Override protected void onCreate(Bundle savedInstanceState)
{ // ৭ʑͳॳظԽͷॲཧΛ͢Δ // FragmentͷView͕ग़དྷ্͕Δ·ͰɺTransitionΛҰ࣌ఀࢭ͢Δ // ࠶։Fragmentଆ͔ΒݺΜͰ͋͛Δ supportPostponeEnterTransition(); }
2018.2.8 PostArticleActivity ҎԼͷTransitionSet͕ద༻͞Ε͍ͯΔ <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:duration="250" android:transitionOrdering="together"> <changeBounds android:interpolator="@anim/interpolator_transition"
/> <changeTransform android:interpolator="@anim/interpolator_transition" /> <changeClipBounds android:interpolator="@anim/interpolator_transition" /> </transitionSet> ࣮ͷղઆ ڞ௨ͷ෦
2018.2.8 ࣮ͷղઆ Article
2018.2.8 Article Transition։࢝લ ࣮ͷղઆ Article • CardView • ImageView(Mark Zuckerberg)
• ߘऀΛදࣔ͢ΔϨΠΞτ • Title • ͍͍ͶίϝϯτϘλϯͷϨΠΞτ
2018.2.8 Article Transition։࢝લ ࣮ͷղઆ Article • CardView • ImageView(Mark Zuckerberg)
• ߘऀΛදࣔ͢ΔϨΠΞτ • Title • ͍͍ͶίϝϯτϘλϯͷϨΠΞτ
2018.2.8 Article Transition։࢝લ ࣮ͷղઆ Article • CardView • ImageView(Mark Zuckerberg)
• ߘऀΛදࣔ͢ΔϨΠΞτ • Title • ͍͍ͶίϝϯτϘλϯͷϨΠΞτ
2018.2.8 Article Transition։࢝લ ࣮ͷղઆ Article • CardView • ImageView(Mark Zuckerberg)
• ߘऀΛදࣔ͢ΔϨΠΞτ • Title • ͍͍ͶίϝϯτϘλϯͷϨΠΞτ
2018.2.8 Article Transition։࢝લ ࣮ͷղઆ Article • CardView • ImageView(Mark Zuckerberg)
• ߘऀΛදࣔ͢ΔϨΠΞτ • Title • ͍͍ͶίϝϯτϘλϯͷϨΠΞτ
2018.2.8 Article Transition։࢝ޙং൫ ࣮ͷղઆ Article • CardView • ImageView(Mark Zuckerberg)
• ߘऀΛදࣔ͢ΔϨΠΞτ • Title • ͍͍ͶίϝϯτϘλϯͷϨΠΞτ • CardViewͷSharedElementͱͯ͠ ஔ͍ͯͨ͠ന͍͚ͩͷ FrameLayout
2018.2.8 Article Transition։࢝ޙऴ൫ ࣮ͷղઆ Article • CardView • ImageView(Mark Zuckerberg)
• ߘऀΛදࣔ͢ΔϨΠΞτ • Title • ͍͍ͶίϝϯτϘλϯͷϨΠΞτ • CardViewͷSharedElementͱͯ͠ ஔ͍ͯͨ͠ന͍͚ͩͷ FrameLayout
2018.2.8
2018.2.8 Article Shared Elements ࣮ͷղઆ Article 5JNFMJOF'SBNFOU 1PTU"SUJDMF'SBHNFOU 7JFX %FTDSJQUJPO
7JFX %FTDSJQUJPO *NBHF7JFX Χʔυഎܠ *NBHF7JFX ΧόʔΠϝʔδ $BSE7JFX Χʔυ 'SBNF-BZPVU μϛʔͷഎܠ -JOFBS-BZPVU ߘऀͷϨΠΞτ -JOFBS-BZPVU ߘऀͷϨΠΞτ 5FYU7JFX λΠτϧ 5FYU7JFX λΠτϧ 5FYU7JFX ϝσΟΞ 5FYU7JFX ϝσΟΞ $POTUSBJOU-BZPVU ίϝϯτϘλϯͳͲ $POTUSBJOU-BZPVU ίϝϯτϘλϯͳͲ
2018.2.8 PostArticleFragment ϨΠΞτߏ <FrameLayout android:id="@+id/content_root"> ࣮ͷղઆ Article fragment_post_article.xml </FrameLayout> <android.support.constraint.ConstraintLayout
android:id=“@+id/reaction"> <!--͍͍ͶͷϘλϯͱ͔ίϝϯτͷϘλϯͱ͔--> </android.support.constraint.ConstraintLayout>
2018.2.8 <FrameLayout android:id="@+id/content_root"> ࣮ͷղઆ Article <FrameLayout android:id="@+id/background_view" android:background="@drawable/background_post_article" /> </FrameLayout>
<android.support.constraint.ConstraintLayout android:id=“@+id/reaction"> <!--͍͍ͶͷϘλϯͱ͔ίϝϯτͷϘλϯͱ͔--> </android.support.constraint.ConstraintLayout> PostArticleFragment ϨΠΞτߏ fragment_post_article.xml
2018.2.8 <FrameLayout android:id="@+id/content_root"> ࣮ͷղઆ Article <FrameLayout android:id="@+id/background_view" android:background="@drawable/background_post_article" /> <android.support.constraint.ConstraintLayout>
<android.support.v4.widget.NestedScrollView android:id="@+id/parent_nested_scroll_view"> </android.support.v4.widget.NestedScrollView> </FrameLayout> <android.support.constraint.ConstraintLayout android:id=“@+id/reaction"> <!--͍͍ͶͷϘλϯͱ͔ίϝϯτͷϘλϯͱ͔--> </android.support.constraint.ConstraintLayout> PostArticleFragment ϨΠΞτߏ fragment_post_article.xml
2018.2.8 <FrameLayout android:id="@+id/content_root"> ࣮ͷղઆ Article <FrameLayout android:id="@+id/background_view" android:background="@drawable/background_post_article" /> <FrameLayout
android:id="@+id/card"> <android.support.constraint.ConstraintLayout> <android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout> <android.support.v4.widget.NestedScrollView android:id="@+id/parent_nested_scroll_view"> </android.support.v4.widget.NestedScrollView> </FrameLayout> <android.support.constraint.ConstraintLayout android:id=“@+id/reaction"> <!--͍͍ͶͷϘλϯͱ͔ίϝϯτͷϘλϯͱ͔--> </android.support.constraint.ConstraintLayout> PostArticleFragment ϨΠΞτߏ fragment_post_article.xml
2018.2.8 <FrameLayout android:id="@+id/content_root"> ࣮ͷղઆ Article <FrameLayout android:id="@+id/background_view" android:background="@drawable/background_post_article" /> <FrameLayout
android:id="@+id/card"> <android.support.constraint.ConstraintLayout> <android.support.v4.widget.NestedScrollView android:id="@+id/parent_nested_scroll_view"> <FrameLayout android:id="@+id/card"> <ImageView android:id="@+id/image_cover" /> <android.support.constraint.ConstraintLayout> <include android:id="@+id/layout_poster" layout="@layout/item_post_user" /> <TextView android:id="@+id/text_title" /> <TextView android:id="@+id/label_ad" /> <TextView android:id="@+id/text_source_media" /> <TextView android:id="@+id/text_published_at" /> </android.support.constraint.ConstraintLayout> </FrameLayout> PostArticleFragment ϨΠΞτߏ fragment_post_article.xml
2018.2.8 ࣮ͷղઆ Article layout="@layout/item_post_user" /> <TextView android:id="@+id/text_title" /> <TextView android:id="@+id/label_ad"
/> <TextView android:id="@+id/text_source_media" /> <TextView android:id="@+id/text_published_at" /> </android.support.constraint.ConstraintLayout> </FrameLayout> <WebView android:id="@+id/web_view_short_article" /> <android.support.constraint.ConstraintLayout> </android.support.v4.widget.NestedScrollView> <android.support.constraint.ConstraintLayout android:id=“@+id/reaction"> <!--͍͍ͶͷϘλϯͱ͔ίϝϯτͷϘλϯͱ͔--> </android.support.constraint.ConstraintLayout> </FrameLayout> PostArticleFragment ϨΠΞτߏ fragment_post_article.xml
2018.2.8 @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup
container, @Nullable Bundle savedInstanceState) { mBinding = FragmentPostArticleBinding.inflate(inflater, container, false); ViewCompat.setTransitionName(mBinding.imageCover, getString(R.string.transition_image_cover)); ViewCompat.setTransitionName(mBinding.backgroundView, getString(R.string.transition_background)); ViewCompat.setTransitionName(mBinding.layoutPoster.getRoot(), getString(R.string.transition_item_user)); ViewCompat.setTransitionName(mBinding.textTitle, getString(R.string.transition_text_title)); ViewCompat.setTransitionName(mBinding.textSourceMedia, getString(R.string.transition_item_source_media)); ViewCompat.setTransitionName(mBinding.reaction, getString(R.string.transition_item_reactions)); return mBinding.getRoot(); } ࣮ͷղઆ Article PostArticleFragment TransitionपΓͷίʔυ
2018.2.8 @Override public void onStart() { super.onStart(); mPostAccessor.getObservable() .compose(this.bindToLifecycle()) .subscribe(post
-> { refreshPost(post, mState); getActivity().supportStartPostponedEnterTransition(); }, e -> recordError(null, this, e, null)); } ࣮ͷղઆ Article PostArticleFragment Ωϟογϡʹ͋Δهࣄͷσʔλ(post)Λऔಘ͠ɺྃޙTransitionΛ࠶։
2018.2.8 ϙΠϯτ • Transition։࢝લͷλΠϛϯάͰҰ࣌ఀࢭ͢Δ • Viewͷ४උ͕Ͱ͖ͨΒ࠶։ • Χʔυ͕expand͢ΔΑ͏ͳΞχϝʔγϣϯ ͪΐͬͱͨ͠τϦοΫΛ͍ͬͯΔ͚ͩɻ ͘͠ͳ͍
࣮ͷղઆ Article PostArticleFragment
2018.2.8 ࣮ͷղઆ Graphic contents
2018.2.8 Graphic contents Transition։࢝લ ࣮ͷղઆ Graphic contents • CardView •
ImageView(Χʔυഎܠ) • ߘऀΛදࣔ͢ΔϨΠΞτ • Title
2018.2.8 Graphic contents ࣮ͷղઆ Graphic contents • CardView • ImageView(Χʔυഎܠ)
• ߘऀΛදࣔ͢ΔϨΠΞτ • Title Transition։࢝લ
2018.2.8 Graphic contents ࣮ͷղઆ Graphic contents Transition։࢝લ • CardView •
ImageView(Χʔυഎܠ) • ߘऀΛදࣔ͢ΔϨΠΞτ • Title
2018.2.8 Graphic contents ࣮ͷղઆ Graphic contents Transition։࢝લ • CardView •
ImageView(Χʔυഎܠ) • ߘऀΛදࣔ͢ΔϨΠΞτ • Title
2018.2.8 Graphic contents Transition։࢝ޙং൫ • Χʔυશମ͕ը໘ΛຒΊΔ༻ʹ͕ͬͯ ͍͘ • ߘऀλΠτϧͳͲಉ͡Α͏ʹಈ͍ ͍ͯ͘
࣮ͷղઆ Graphic contents
2018.2.8 Graphic contents Transition։࢝ޙத൫ • എܠʹઃఆ͍ͯͨ͠ImageView͕ը໘ ͍ͬͺ͍ʹ͕Δ ࣮ͷղઆ Graphic contents
2018.2.8 Graphic contents Transition։࢝ޙऴ൫1/2 • ίϯςϯπͷϩʔυ͕ऴྃ͠ɺϔομʔ ෦͕ϑΣʔυΞτ&্ʹফ͍͑ͯ͘ ࣮ͷղઆ Graphic contents
2018.2.8 Graphic contents Transition։࢝ޙऴ൫2/2 • ίϯςϯπͱഎܠը૾͕ΫϩεϑΣʔυ ͢ΔܗͰೖΕସΘΔ ࣮ͷղઆ Graphic contents
2018.2.8
2018.2.8 Graphic contents Shared Elements ࣮ͷղઆ 5JNFMJOF'SBNFOU (SBQIJD$POUFOUT'SBHNFOU 7JFX %FTDSJQUJPO
7JFX %FTDSJQUJPO *NBHF7JFX Χʔυഎܠ *NBHF7JFX എܠը૾ -JOFBS-BZPVU ߘऀͷϨΠΞτ -JOFBS-BZPVU ߘऀͷϨΠΞτ 5FYU7JFX λΠτϧ 5FYU7JFX λΠτϧ 5FYU7JFX ϝσΟΞ 5FYU7JFX ϝσΟΞ Graphic contents
2018.2.8 GraphicContentsFragment ϨΠΞτߏ <android.support.constraint.ConstraintLayout android:id="@+id/content_root"> ࣮ͷղઆ fragment_graphic_contents.xml </android.support.constraint.ConstraintLayout> Graphic contents
2018.2.8 GraphicContentsFragment ϨΠΞτߏ <android.support.constraint.ConstraintLayout android:id="@+id/content_root"> ࣮ͷղઆ fragment_graphic_contents.xml </android.support.constraint.ConstraintLayout> Graphic contents
<WebView android:id="@+id/web_view_graphic_content" /> <ImageView android:id="@+id/background_view" />
2018.2.8 GraphicContentsFragment ϨΠΞτߏ <android.support.constraint.ConstraintLayout android:id="@+id/content_root"> ࣮ͷղઆ fragment_graphic_contents.xml </android.support.constraint.ConstraintLayout> Graphic contents
<WebView android:id="@+id/web_view_graphic_content" /> <ImageView android:id="@+id/background_view" />
2018.2.8 GraphicContentsFragment ϨΠΞτߏ <android.support.constraint.ConstraintLayout android:id="@+id/content_root"> ࣮ͷղઆ fragment_graphic_contents.xml </android.support.constraint.ConstraintLayout> Graphic contents
<WebView android:id="@+id/web_view_graphic_content" /> <ImageView android:id="@+id/background_view" /> <android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>
2018.2.8 GraphicContentsFragment ϨΠΞτߏ <android.support.constraint.ConstraintLayout android:id="@+id/content_root"> ࣮ͷղઆ fragment_graphic_contents.xml </android.support.constraint.ConstraintLayout> Graphic contents
<WebView android:id="@+id/web_view_graphic_content" /> <ImageView android:id="@+id/background_view" /> <android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout> <FrameLayout android:id="@+id/header"> </FrameLayout>
2018.2.8 GraphicContentsFragment ϨΠΞτߏ <android.support.constraint.ConstraintLayout android:id="@+id/content_root"> ࣮ͷղઆ fragment_graphic_contents.xml Graphic contents <WebView
android:id="@+id/web_view_graphic_content" /> <ImageView android:id="@+id/background_view" /> <android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout> <FrameLayout android:id="@+id/header"> </FrameLayout> <android.support.constraint.ConstraintLayout> <include android:id="@+id/layout_poster" /> <TextView android:id="@+id/text_title" /> <TextView android:id="@+id/label_ad" /> <TextView android:id="@+id/text_source_media" /> <TextView android:id="@+id/text_published_at" /> </android.support.constraint.ConstraintLayout>
2018.2.8 GraphicContentsFragment TransitionपΓͷίʔυ1/2 ࣮ͷղઆ Graphic contents @Nullable @Override public View
onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { mBinding = FragmentPostArticleSp1Rev2Binding.inflate(inflater, container, false); ViewCompat.setTransitionName(mBinding.backgroundView, getString(R.string.transition_background)); ViewCompat.setTransitionName(mBinding.textTitle, getString(R.string.transition_text_title)); ViewCompat.setTransitionName(mBinding.layoutPoster.getRoot(), getString(R.string.transition_item_user)); ViewCompat.setTransitionName(mBinding.textSourceMedia, getString(R.string.transition_item_source_media)); return mBinding.getRoot(); }
2018.2.8 GraphicContentsFragment TransitionपΓͷίʔυ2/2 ࣮ͷղઆ Graphic contents @Override public void onPageFinished(WebView
view, String url) { super.onPageFinished(view, url); TransitionSet transitionSet = new TransitionSet().setDuration(400).setStartDelay(200); Fade fadeTransition = new Fade(); Transition slideUpTransition = new Slide(Gravity.TOP) .setStartDelay(100) .excludeTarget(R.id.background_view, true); transitionSet.addTransition(fadeTransition); transitionSet.addTransition(slideUpTransition); transitionSet.setInterpolator(AnimationUtils.loadInterpolator( getContext(), R.anim.accelerate_quad)); TransitionManager.beginDelayedTransition(((ViewGroup) getView()), transitionSet); mBinding.card.setVisibility(View.INVISIBLE); mBinding.backgroundView.setVisibility(View.INVISIBLE); view.setVisibility(View.VISIBLE); }
2018.2.8 @Override public void onStart() { super.onStart(); mPostAccessor.getObservable() .compose(this.bindToLifecycle()) .subscribe(post
-> { refreshPost(post, mState); getActivity().supportStartPostponedEnterTransition(); }, e -> recordError(null, this, e, null)); } ࣮ͷղઆ GraphicContentsFragment Ωϟογϡʹ͋Δهࣄͷσʔλ(post)Λऔಘ͠ɺྃޙTransitionΛ࠶։ Graphic contents
2018.2.8 ϙΠϯτ • Transition։࢝લͷλΠϛϯάͰҰ࣌ఀࢭ͢Δ • Viewͷ४උ͕Ͱ͖ͨΒ࠶։ • ࣮ࡍʹେ͖͘ಈ͍͍ͯΔͷImageView͚ͩ • ࡉ͔͘ಈ͍͍ͯΔΞΠςϜୡ
TransitionFrameworkͷ͓͔͛ • ΞχϝʔγϣϯͷAPI৭ʑ͋ΔͷͰɺཁॴཁ ॴͰΈ߹Θ͍ͯͬͯ͘͠ ࣮ͷղઆ GraphicContentsFragment Graphic contents
2018.2.8 Ξχϝʔγϣϯ࣮ͷצॴ ·ͣਅ͔ͬΒߟ͑ͣʹΖ͏
2018.2.8 ࡶʹ࡞Δ Ξχϝʔγϣϯ࣮ͷצॴ ·ͣਅ͔ͬΒߟ͑ͣʹΖ͏
2018.2.8 ὃ͢Α͏ʹߟ͑Δ Ξχϝʔγϣϯ࣮ͷצॴ ·ͣਅ͔ͬΒߟ͑ͣʹΖ͏
2018.2.8 ਅࣅΛ͢Δ Ξχϝʔγϣϯ࣮ͷצॴ ·ͣਅ͔ͬΒߟ͑ͣʹΖ͏
2018.2.8 ఘΊͳ͍ Ξχϝʔγϣϯ࣮ͷצॴ ·ͣਅ͔ͬΒߟ͑ͣʹΖ͏
2018.2.8 ΞχϝʔγϣϯͷDebug
2018.2.8 • AnimatorεέʔϧΛ5xʙ10xʹ͢Δ • ϨΠΞτͷڥքઢΛදࣔ͢Δ • γϣʔτΧοτͱͯ͠௨ͷॴʹஔ͍ͱ͘ ͱྑ͍͔ ΞχϝʔγϣϯͷDebug ։ൃऀΦϓγϣϯ
2018.2.8 • android:animateLayoutChanges=“true" ͕ViewGroupʹઃఆ͞Ε͍ͯΔ͔ʁ • ࣗͰద༻ͨ͠ΞχϝʔγϣϯͱίϯϑϦ ΫτΛى͍ͯ͜͠ΔՄೳੑ͕͋Δ • clipChildren/clipToPaddingͷࢦఆΛ͍ͬ͡ ͯΈΔ
• େ͖͘Λ͑ͯΞχϝʔγϣϯ͢Δ࣌ ্هͷࢦఆ͕ฉ͍ͯ͘Δɻfalseʹ͢Δ͜ͱ ͰViewGroupͷΛඈͼग़ͯ͠ಈ͘Α͏ ʹͰ͖Δ͔͠Εͳ͍ ΞχϝʔγϣϯͷDebug มͳಈ͖Λ͍ͯͨ͠Β1/2 ҎԼͷ߲ΛٙͬͯΈ͍͍͔ͯ
2018.2.8 • Ұ୴ϨΠΞτϑΝΠϧΛ࡞Γͯ͠ΈΔ • ແཧͷ͋ΔϨΠΞτϑΝΠϧʹͳ͍ͬͯ Δ͔͠Εͳ͍ • ֊͕ਂ͍ͱ͘͜͠ͳΔɻͳΔ͘ ConstrainLayoutͳͲΛͬͯ֊Λઙ͘ ͢Δ͜ͱ͕ग़དྷͳ͍͔ߟ͑Δ
• Ұͭͷख๏͚ͩͰΰϦԡ͠͠Α͏ͱ͍ͯ͠ͳ ͍͔ʁ • ଞʹָͳํ๏͕ͳ͍͔ݕূ͢Δɻ·ͨɺࣅ ͨΑ͏ͳΞϓϦ͕ͳ͍͔୳ͯ͠ΈΔ ΞχϝʔγϣϯͷDebug มͳಈ͖Λ͍ͯͨ͠Β2/2 ҎԼͷ߲ΛٙͬͯΈ͍͍͔ͯ
2018.2.8 • Shared Element Transitionαϯϓϧίʔυ ࣗମ؆୯ͳͷ͕ଟ͍͚Ͳɺ࣮ࡍʹΈࠐ ΉͱͳΔͱɺϨΠΞτϑΝΠϧͷ࡞Γํ ͕ඞཁʹͳΔ • Shared
Element TransitionҰ࣌ఀࢭ/࠶։ ͕ίϯτϩʔϧͰ͖Δ • ͜·ͬͨΒɺҰ୴Ϧηοτͯ͠ߟ͑Δɻ·ͨɺ ࣅͯΔΞϓϦΛ୳ͯ͠Α͘؍͢Δ ·ͱΊ ·ͱΊ
2018.2.8 Thanks!