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
740
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.5k
KOINかわいいよ、KOIN
wakwak3125
0
920
Other Decks in Programming
See All in Programming
Node-RED を(HTTP で)つなげる MCP サーバーを作ってみた
highu
0
120
“いい感じ“な定量評価を求めて - Four Keysとアウトカムの間の探求 -
nealle
1
8.5k
都市をデータで見るってこういうこと PLATEAU属性情報入門
nokonoko1203
1
600
猫と暮らす Google Nest Cam生活🐈 / WebRTC with Google Nest Cam
yutailang0119
0
110
ペアプロ × 生成AI 現場での実践と課題について / generative-ai-in-pair-programming
codmoninc
1
15k
Porting a visionOS App to Android XR
akkeylab
0
360
XP, Testing and ninja testing
m_seki
3
240
新メンバーも今日から大活躍!SREが支えるスケールし続ける組織のオンボーディング
honmarkhunt
3
6.1k
ソフトウェア品質を数字で捉える技術。事業成長を支えるシステム品質の マネジメント
takuya542
1
11k
Systèmes distribués, pour le meilleur et pour le pire - BreizhCamp 2025 - Conférence
slecache
0
120
Is Xcode slowly dying out in 2025?
uetyo
1
260
AIと”コードの評価関数”を共有する / Share the "code evaluation function" with AI
euglena1215
1
140
Featured
See All Featured
Scaling GitHub
holman
459
140k
Docker and Python
trallard
44
3.5k
The Cult of Friendly URLs
andyhume
79
6.5k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
A Modern Web Designer's Workflow
chriscoyier
694
190k
Code Review Best Practice
trishagee
69
18k
Visualization
eitanlees
146
16k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.9k
Site-Speed That Sticks
csswizardry
10
680
The Straight Up "How To Draw Better" Workshop
denniskardys
234
140k
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
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!