Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
実例で理解する Material Design Animation
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Ryo Sakaguchi
February 08, 2018
Programming
5.4k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
実例で理解する Material Design Animation
DroidKaigi 2018 2/8 Room2
Ryo Sakaguchi
February 08, 2018
More Decks by Ryo Sakaguchi
See All by Ryo Sakaguchi
なんとなくgRPC-Java を使ってるそこの俺、gRPC-Kotlin に移行したらどうだ?
wakwak3125
0
25
Android Architecture Componentsを使って、改善・効率化するAndroidアプリ開発
wakwak3125
0
1.3k
Test multiple APKs with Robolectric
wakwak3125
0
840
Clip, Elevation and ViewOutlineProvider
wakwak3125
1
1.4k
WebView as Fancy and effective View
wakwak3125
1
1.7k
ViewPager2をちょっとさわってみよう
wakwak3125
0
1.7k
年末だし、振り返るKotlin
wakwak3125
1
1.2k
社内ライブラリのアップデートフロー
wakwak3125
4
3.9k
Wantedly Peopleのリリースフロー
wakwak3125
1
4.9k
Other Decks in Programming
See All in Programming
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
570
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
190
FreeBSDでZabbixを動かす.pdf
kenkino
0
280
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
180
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
250
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
170
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
230
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
180
【高い買い物LT会】初任給で話題の国産フィジカルAIを買った話
akagami
PRO
0
160
アクセシビリティから考える情報設計
high_g_engineer
0
380
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
280
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
410
Featured
See All Featured
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Everyday Curiosity
cassininazir
0
320
Optimizing for Happiness
mojombo
378
71k
Between Models and Reality
mayunak
4
460
Are puppies a ranking factor?
jonoalderson
2
3.9k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Abbi's Birthday
coloredviolet
4
10k
The browser strikes back
jonoalderson
0
1.7k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
The Limits of Empathy - UXLibs8
cassininazir
1
670
Mind Mapping
helmedeiros
1
360
Design in an AI World
tapps
1
320
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!