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
View Animation
Search
satsukies
October 02, 2017
Programming
1
830
View Animation
View Animation in Android
satsukies
October 02, 2017
Tweet
Share
More Decks by satsukies
See All by satsukies
5分で作るモックサーバー
satsukies
0
1.2k
Android スキルセットをフル活用して始めるスマートテレビアプリ開発
satsukies
1
900
Android TVに関するアップデート / What's new on Android TV
satsukies
0
210
Kotlin Nativeでクロスプラットフォーム開発 / Cross-platform development with Kotlin Native
satsukies
1
920
Navigation Component
satsukies
5
3.9k
「OK google, プロジェクトのbuildして」
satsukies
2
1.6k
いまさら始めるInstant App
satsukies
1
400
Other Decks in Programming
See All in Programming
primeNumberでのRBS導入の現在 && RBS::Traceでinline RBSを拡充してみた
mnmandahalf
0
250
External SecretsのさくらProvider初期実装を担当しています
logica0419
0
230
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfold' relates to 'iterate'"
philipschwarz
PRO
0
130
生成AI時代のフルスタック開発
kenn
10
2.7k
技術懸念に立ち向かい 法改正を穏便に乗り切った話
pop_cashew
0
740
コンポーネントライブラリで実現する、アクセシビリティの正しい実装パターン
schktjm
1
660
〜可視化からアクセス制御まで〜 BigQuery×Looker Studioで コスト管理とデータソース認証制御する方法
cuebic9bic
1
260
型安全なDrag and Dropの設計を考える
yudppp
5
660
ユーザーにサブドメインの ECサイトを提供したい (あるいは) 2026年函館で一番熱くなるかもしれない言語の話
uvb_76
0
170
Zennの運営完全に理解した #完全に理解したTalk
wadayusuke
1
140
AI Coding Agent Enablement in TypeScript
yukukotani
17
7.1k
推論された型の移植性エラーTS2742に挑む
teamlab
PRO
0
150
Featured
See All Featured
Bash Introduction
62gerente
614
210k
How GitHub (no longer) Works
holman
314
140k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Building an army of robots
kneath
306
45k
Fontdeck: Realign not Redesign
paulrobertlloyd
84
5.5k
How STYLIGHT went responsive
nonsquared
100
5.6k
A better future with KSS
kneath
239
17k
Stop Working from a Prison Cell
hatefulcrawdad
269
20k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.1k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.2k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
228
22k
Transcript
7JFX"OJNBUJPO 4BUPTIJ5BLFEB "CFNB57*OD
8IPJT
8IPJT ాɹஐ 5BLFEBɹ4BUPTIJ ˡTBUTVLJFT ɹɹ$ZCFS"HFOUʹ৽ଔೖࣾ ʙɹ"CFNB57ʹ"OESPJEΤϯδχΞͰଐ
"OJNBUJPO
"OJNBUJPO 7JFX"OJNBUJPO 1SPQFSUZ"OJNBUJPO %SBXBCMF"OJNBUJPO
"OJNBUJPO 7JFX"OJNBUJPO 1SPQFSUZ"OJNBUJPO %SBXBCMF"OJNBUJPO BMQIB SPUBUF TDBMF USBOTMBUF ͍͍͢ɾ؆୯ ݟ͚͕ͨͩมԽ͢ΔΞχϝʔγϣϯ
// viewͷalpha͕0͔Β13ඵ͔͚ͯมԽ͢ΔΞχϝʔγϣϯ (findViewById(R.id.image_view) as? ImageView)?.apply { startAnimation(AlphaAnimation(0f, 1f).apply { duration = 3000 }) }
"OJNBUJPO 7JFX"OJNBUJPO 1SPQFSUZ"OJNBUJPO "1*͔Β࣮͞Εͨ৽͍͠BOJNBUPS ෳࡶͳΞχϝʔγϣϯΛදݱՄೳ ݟ͚ͨͩͰͳ࣮͘ࡍͷҐஔมԽ <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering=“together"> <objectAnimator
android:duration="3000" android:propertyName=“alpha" android:valueFrom="0f" android:valueTo="1f"/> <objectAnimator android:duration="3000" android:propertyName="translationY" android:valueFrom="0dp" android:valueTo="100dp"/> </set> %SBXBCMF"OJNBUJPO
"OJNBUJPO 1SPQFSUZ"OJNBUJPO %SBXBCMF"OJNBUJPO ը૾ϦιʔεΛෳຕར༻ͯ͠ ύϥύϥອըͷΑ͏ʹ࠶ੜͤ͞Δ 7JFX"OJNBUJPO <?xml version="1.0" encoding="utf-8"?> <animation-list
xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false" android:visible="true" > <item android:drawable=“@drawable/pict0" android:duration="300" /> <item android:drawable="@drawable/pict1" android:duration="300" /> <item android:drawable="@drawable/pict2" android:duration="300" /> <item android:drawable="@drawable/pict3" android:duration="300" /> <item android:drawable="@drawable/pict4" android:duration="300" /> </animation-list>
.BUFSJBM%FTJHO
.BUFSJBM%FTJHO w .BUFSJBMJTUIFNFUBQIPS w #PME HSBQIJD JOUFOUJPOBM w .PUJPOQSPWJEFTNFBOJOH ҙຯͷ͋Δಈ͖ΛϢʔβʹࣔ͢͜ͱͰ
ɾࢹ֮తʹҙΛҾ͖͚ͭΔ ɾཁૉͷग़ݱมܗɺҠಈΛ௨ͯ͡࿈ଓੑΛ͑Δ ը໘ભҠ͕࣌࠷࿈ଓੑ͕ࣦΘΕͦ͢͏
ը໘ભҠͷΧελϚΠζ
ը໘ભҠͷΧελϚΠζ https://developer.android.com/training/material/animations.html#Transitions (PPHMF%FWFMPQFSTͷ ʮΞΫςΟϏςΟભҠΛΧελϚΠζ͢ΔʯʹΑΕ ȜȄȨǠȩȅǴǢȱǠȕȨƵ!CTIVITYTRANSITIONS ᮊǠǭȄǡȑȄǡჟᮋƮƶųΒឬƠǒᖽᇽƵᣨƮƵ Ы˗NjدъǙឬƟƭųओƵϜǑଖƏƲᗆᗉƱ ƫƱƓǑǙেƦƢDžƠŴ લޙͷΞΫςΟϏςΟͰڞ௨ͷΞΠίϯը૾ݟग़͠ςΩετͳͲ͕ଘࡏ͢Δ߹ʹ ڞ௨͢Δཁૉͷද͕ࣔҾ͖ܧ͕Ε͍ͯΔΑ͏ʹݟͤΔ͜ͱͰ࿈ଓੑΛදݱ͢Δ
"DUJWJUZ5SBOTJUJPOTͷछྨ
"DUJWJUZ5SBOTJUJPOTͷछྨ &OUFS &YJU 4IBSFE&MFNFOUT
"DUJWJUZ5SBOTJUJPOTͷछྨ &OUFS &YJU 4IBSFE&MFNFOUT "DUJWJUZͷWJFX͕ͲͷΑ͏ʹը໘ೖͬͯ͘Δ͔Λܾఆ
"DUJWJUZ5SBOTJUJPOTͷछྨ &OUFS &YJU 4IBSFE&MFNFOUT "DUJWJUZͷWJFX͕ͲͷΑ͏ʹը໘͔Βग़ͯߦ͔͘Λܾఆ
"DUJWJUZ5SBOTJUJPOTͷछྨ &OUFS &YJU 4IBSFE&MFNFOUT ը໘্ʹ͋Δڞ௨ͷཁૉʢྫ͑*NBHF7JFXͱ͔ʣΛ ͲͷΑ͏ʹΞχϝʔγϣϯͤ͞Δ͔ɻ "1*͔Β࣮͞Εར༻Մೳʂ αϙʔτϥΠϒϥϦʹೖ͍ͬͯͳ͍ͷ͕ͪΐͬͱ೦
(PPHMF1MBZ4UPSF
None
Ґͩͱಈ͖͕গͳͯ͘ Α͔͘Βͳ͍ʁ!
Ξχϝʔγϣϯ εέʔϧY
"CFNB57ʹ
None
ͳΒ͜͜ʹ ΞχϝʔγϣϯΛʂ
7JFX"OJNBUJPO 4BUPTIJ5BLFEB "CFNB57*OD
7JFX"OJNBUJPO 4BUPTIJ5BLFEB "CFNB57*OD 5SBOTJUJPO
#BTJDJNQMFNFOU
#BTJDJNQMFNFOU /PSNBM.BTUFS"DUJWJUZLU val intent = Intent(context, SharedMasterActivity::class.java) val optionsCompat =
ActivityOptionsCompat.makeSceneTransitionAnimation( this, targetView, targetView.transitionName) startActivity(intent, optionsCompat.toBundle()) ΞχϝʔγϣϯରͷWJFX //viewͷΠϯελϯεϝιου targetView.setTransitionName("hogehoge") //ViewCompatΫϥεͷΫϥεϝιου ViewCompat.setTransitionName(targetView, "hogehoge") android:transitionName="hogehoge"
#BTJDJNQMFNFOU XJUIඇಉظ௨৴ ભҠઌͱભҠݩͰผʑͷը૾Λ͍ͬͯΔ߹ʜ ը૾ͷऔಘ͕Ξχϝʔγϣϯ։࢝ʹؒʹ߹Θͳ͍ʂ
"EWBODFEJNQMFNFOU
"EWBODFEJNQMFNFOU ݺͼग़ͨ͠λΠϛϯάͰ5SBOTJUJPO"OJNBUJPOΛ։࢝ͤ͞Δ QPTUQPOF&OUFS5SBOTJUJPO TUBSU1PTUQPOFE&OUFS5SBOTJUJPO 5SBOTJUJPO"OJNBUJPOͷ։࢝Λࢭ͢Δ Ξχϝʔγϣϯͷ։࢝λΠϛϯάΛ ίʔυଆͰίϯτϩʔϧՄೳ
"EWBODFEJNQMFNFOU override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) supportPostponeEnterTransition() // Ξχϝʔγϣϯࢭ
~~~~~~~~~~~~~~~ fun startEnterTransition() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return supportStartPostponedEnterTransition(); // Ξχϝʔγϣϯ࠶։ }
"EWBODFEJNQMFNFOU (MJEF1JDBTTPͷ$BMMCBDLʹࠐΜͰΈΔ ImageView targetImageView = (ImageView)findViewById(R.id.image_header); //Glideͷ߹(4.0-RC0) Glide.with(this) .load("http://hogehoge.com/fugafuga") .listener(new
RequestListener() { @Override public boolean onResourceReady(Object resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { startPostponedEnterTransition() return false; } }) .into(targetImageView); //Picassoͷ߹ Picasso.with(this) .load("http://hogehoge.com/fugafuga").into(targetImageView, new Callback(){ @Override public void onSuccess() { startPostponedEnterTransition() } });
ΫϦοΫ͔ͯ͠ΒΞχϝʔγϣϯ·Ͱͷػ͕࣌ؒࢥͬͨҎ্ʹ͍"
ϢʔβମݧΛҡ͍࣋ͨ͠
ϢʔβମݧΛҡ͍࣋ͨ͠ ಛʹߟ͑ͣγϯϓϧʹΞχϝʔγϣϯͤ͞Δͱ ɾΞϓϦ͕ϑϦʔζ͍ͯ͠ΔΑ͏ʹݟ͑ͯ͠·͏ ɾը૾͕ϩʔυ͞ΕΔ·ͰCBDLHSPVOE͕ݟ͑ݟ͑ ը૾ͷಡΈࠐΈΛͬͯΞχϝʔγϣϯ͢Δͱ ɾ్தͰը૾͕ϩʔυ͞Εͯද͕ࣔมʹͳΔ͜ͱ Ͳ͏ʹ͔ͯ͠ը૾Λૉૣ͘ϩʔυ͍ͨ͠ʜ"
None
ϢʔβମݧΛҡ͍࣋ͨ͠ (MJEFͷαϜωΠϧදࣔػೳΛ׆༻ ɾಉ͡WJFXͰෳͷը૾Λಉ࣌ʹಡΈࠐΊΔ ɾαϜωΠϧը૾ͷMPBEʹରͯ͠DBMMCBDL͕͚ͭΒΕΔ αϜωΠϧදࣔ Ξχϝʔγϣϯ։࢝ ݩը૾දࣔ
5SBOTJUJPOXJUIUIVNC
5SBOTJUJPOXJUIUIVNC ᶃ*OUFOUʹΩϟογϡࡁΈը૾ͷ63-ΛͤΔ ᶄαϜωΠϧಡΈࠐΈʹ*OUFOUͷ63-Λ͏
5SBOTJUJPOXJUIUIVNC ᶃ*OUFOUʹΩϟογϡࡁΈը૾ͷ63-ΛͤΔ ᶄαϜωΠϧಡΈࠐΈʹ*OUFOUͷ63-Λ͏ binding.getRoot().setOnClickListener(v -> episodeSelectListener.action( ep, ep.getEpisodeListThumbnail().with(options).url(), // ΩϟογϡࡁΈͷը૾URL
binding.episodeThumbnail, binding.vdSeriesThumbnailFreeMark, binding.episodePlayMark)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Intent intent = new Intent(this, DstActivity.class); intent.putExtra(“extra_url”, thumbnailUrlString);
5SBOTJUJPOXJUIUIVNC ᶃ*OUFOUʹΩϟογϡࡁΈը૾ͷ63-ΛͤΔ ᶄαϜωΠϧಡΈࠐΈʹ*OUFOUͷ63-Λ͏ //͢ͰʹMasterActivityͰऔಘࡁΈͰ͋Ζ͏ը૾ΛαϜωΠϧͱͯ͠ར༻͢Δ .thumbnail( Glide.with(imageView.getContext()) .load(imageThumbURL) .listener(new RequestListener<Drawable>() {
@Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { supportStartPostponedEnterTransition(); // ಡΈࠐΈྃͰΞχϝʔγϣϯ࣮ߦ return false; }}) .apply(new RequestOptions().skipMemoryCache(true) .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC))) .into(imageView);
ରࡦલ ରࡦޙ
"CFNB57BQQʜ
ͦͷଞ5JQT
ͦͷଞ5JQT TUBUVTOBWJHBUJPOCBSʹඃͤͳ͍ WJFX͕ݟΕͯͨΒΞχϝʔγϣϯ͠ͳ͍
ͦͷଞ5JQT TUBUVTOBWJHBUJPOCBSʹඃͤͳ͍ εςʔλεόʔφϏήʔγϣϯόʔ 4IBSFE&MFNFOU5SBOTJUJPOʹؚΊΔ // navigation bar View nav =
findViewById(android.R.id.navigationBarBackground); // status bar View stat = findViewById(android.R.id.statusBarBackground); Pair<View, String> navPair = new Pair<>(nav, "nav"); Pair<View, String> statPair = new Pair<>(stat, "stat"); ActivityOptionsCompat.makeSceneTransitionAnimation(this, navPair, statPair); WJFX͕ݟΕͯͨΒΞχϝʔγϣϯ͠ͳ͍
ͦͷଞ5JQT TUBUVTOBWJHBUJPOCBSʹඃͤͳ͍ WJFX͕ݟΕͯͨΒΞχϝʔγϣϯ͠ͳ͍
ͦͷଞ5JQT TUBUVTOBWJHBUJPOCBSʹඃͤͳ͍ ಈతͳΞχϝʔγϣϯ࣮ߦՄ൱ͷ੍ޚ ɾը໘ճస͕ൃੜͨ͠ΒΞχϝʔγϣϯΛ͠ͳ͍ ɾαϜωΠϧ͕ݟΕ͍ͯΔͱ͖Ξχϝʔγϣϯ͠ͳ͍ 4IBSFE&MFNFOU$BMMCBDLͰ ΞχϝʔγϣϯͷΩϟϯηϧॲཧΛ࣮
ͦͷଞ5JQT TUBUVTOBWJHBUJPOCBSʹඃͤͳ͍ ಈతͳΞχϝʔγϣϯ࣮ߦՄ൱ͷ੍ޚ 4IBSFE&MFNFOU$BMMCBDLͰ ΞχϝʔγϣϯͷΩϟϯηϧॲཧΛ࣮ setEnterSharedElementCallback(new SharedElementCallback() { @Override public
void onMapSharedElements(List<String> names, Map<String, View> sharedElements) { // Ξχϝʔγϣϯରview͕ݟΕ͍ͯΔ߹ΞχϝʔγϣϯΛ࣮ߦ͠ͳ͍ shouldClearSharedElements |= !Stream.of(sharedElements) .filter(item -> item.getValue() != null) .allMatch(item -> viewBehavior.checkViewContains(item.getValue())); if (shouldClearSharedElements) { names.clear(); sharedElements.clear(); } } });
ͦͷଞ5JQT TUBUVTOBWJHBUJPOCBSʹඃͤͳ͍ ಈతͳΞχϝʔγϣϯ࣮ߦՄ൱ͷ੍ޚ શදࣔ ݟΕ
4VNNBSZ
4VNNBSZ "OJNBUJPOʹछྨ͕͍Ζ͍Ζ "DUJWJUZ5SBOTJUJPO࿈ଓੑΛ͑ΔͷʹޮՌత গ͠ͷίʔυमਖ਼Ͱ"OJNBUJPOͷద༻͕Մೳ ඇಉظॲཧͱซ༻͢Δ࣌ҙΛ͏ඞཁ͋Γ
4VNNBSZ "OJNBUJPOʹछྨ͕͍Ζ͍Ζ "DUJWJUZ5SBOTJUJPO࿈ଓੑΛ͑ΔͷʹޮՌత গ͠ͷίʔυमਖ਼Ͱ"OJNBUJPOͷద༻͕Մೳ ඇಉظॲཧͱซ༻͢Δ࣌ҙΛ͏ඞཁ͋Γ 7JFX"OJNBUJPO 1SPQFSUZ"OJNBUJPO %SBXBCMF"OJNBUJPO "DUJWJUZ5SBOTJUJPOT
4VNNBSZ "OJNBUJPOʹछྨ͕͍Ζ͍Ζ "DUJWJUZ5SBOTJUJPO࿈ଓੑΛ͑ΔͷʹޮՌత લޙͷΞΫςΟϏςΟͰҎԼͷΑ͏ͳڞ௨ཁૉ͕ଘࡏ͢Δ߹ ɾΞΠίϯը૾ ɾݟग़͠ςΩετ ͜ΕΒͷද͕ࣔҾ͖ܧ͕Ε͍ͯΔΑ͏ʹݟͤΔ͜ͱͰ࿈ଓੑΛදݱ͢Δ গ͠ͷίʔυमਖ਼Ͱ"OJNBUJPOͷద༻͕Մೳ ඇಉظॲཧͱซ༻͢Δ࣌ҙΛ͏ඞཁ͋Γ
4VNNBSZ "OJNBUJPOʹछྨ͕͍Ζ͍Ζ গ͠ͷίʔυमਖ਼Ͱ"OJNBUJPOͷద༻͕Մೳ ඇಉظॲཧͱซ༻͢Δ࣌ҙΛ͏ඞཁ͋Γ "DUJWJUZ5SBOTJUJPO࿈ଓੑΛ͑ΔͷʹޮՌత USBOTJUJPO/BNFͷ ༩ 4IBSFE&MFNFOU 5SBOTJUJPOͷ࣮ߦڐՄ "DUJWJUZ0QUJPOT͖Ͱ
"DUJWJUZ࣮ߦ
4VNNBSZ "OJNBUJPOʹछྨ͕͍Ζ͍Ζ "DUJWJUZ5SBOTJUJPO࿈ଓੑΛ͑ΔͷʹޮՌత গ͠ͷίʔυमਖ਼Ͱ"OJNBUJPOͷద༻͕Մೳ ඇಉظॲཧͱซ༻͢Δ࣌ҙΛ͏ඞཁ͋Γ ඞཁʹԠͯ͡Ξχϝʔγϣϯͷ࣮ߦλΠϛϯάΛ੍ޚ QPTUQPOF&OUFS5SBOTJUJPO TUBSU1PTUQPOFE&OUFS5SBOTJUJPO Ξχϝʔγϣϯͷ ࠶։
Ξχϝʔγϣϯͷ ։࢝ࢭ αϜωΠϧಡΈࠐΈ
5IBOLZPV !TBUTVLJFT