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
Ryo Sakaguchi
February 08, 2018
Programming
9
5.2k
実例で理解する 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.2k
Test multiple APKs with Robolectric
wakwak3125
0
750
Clip, Elevation and ViewOutlineProvider
wakwak3125
1
1.2k
WebView as Fancy and effective View
wakwak3125
1
1.5k
ViewPager2をちょっとさわってみよう
wakwak3125
0
1.6k
年末だし、振り返るKotlin
wakwak3125
1
1k
社内ライブラリのアップデートフロー
wakwak3125
4
3.7k
Wantedly Peopleのリリースフロー
wakwak3125
1
4.6k
KOINかわいいよ、KOIN
wakwak3125
0
920
Other Decks in Programming
See All in Programming
アセットのコンパイルについて
ojun9
0
120
Ruby Parser progress report 2025
yui_knk
1
440
Android 16 × Jetpack Composeで縦書きテキストエディタを作ろう / Vertical Text Editor with Compose on Android 16
cc4966
1
190
機能追加とリーダー業務の類似性
rinchoku
2
1.3k
今だからこそ入門する Server-Sent Events (SSE)
nearme_tech
PRO
2
130
個人軟體時代
ethanhuang13
0
320
請來的 AI Agent 同事們在寫程式時,怎麼用 pytest 去除各種幻想與盲點
keitheis
0
120
CloudflareのChat Agent Starter Kitで簡単!AIチャットボット構築
syumai
2
480
ファインディ株式会社におけるMCP活用とサービス開発
starfish719
0
310
AI Coding Agentのセキュリティリスク:PRの自己承認とメルカリの対策
s3h
0
200
AIでLINEスタンプを作ってみた
eycjur
1
230
How Android Uses Data Structures Behind The Scenes
l2hyunwoo
0
420
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
173
14k
Context Engineering - Making Every Token Count
addyosmani
1
37
4 Signs Your Business is Dying
shpigford
184
22k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.9k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Navigating Team Friction
lara
189
15k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
51
5.6k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
15k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
34
3.1k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
112
20k
Building Applications with DynamoDB
mza
96
6.6k
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!