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
Kyash Androidのイースターエッグ実装 / Kyash Android Easter...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
konifar
April 18, 2019
Programming
1.4k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Kyash Androidのイースターエッグ実装 / Kyash Android Easter Eggs
konifar
April 18, 2019
More Decks by konifar
See All by konifar
マネージャー版 "提案のレベル" を上げる
konifar
26
20k
AIで 浮いた時間で 何をする? 2026春 #devsumi
konifar
21
5.9k
登壇資料を作る時に意識していること #登壇資料_findy
konifar
7
3.1k
事業部のプロジェクト進行と開発チームの改善の “時間軸" のすり合わせ
konifar
12
4.5k
チーム開発の “地ならし"
konifar
8
17k
AIで 浮いた時間で 何をする? #プロヒス2025
konifar
27
17k
物語を動かす行動"量" #エンジニアニメ
konifar
19
7.3k
提案のレベルを上げる #QiitaConference
konifar
98
42k
目安箱の設置とワークさせるポイント
konifar
6
2.5k
Other Decks in Programming
See All in Programming
Old Dog, New Tricks: The Java 25 Reinvention - JNation
bazlur_rahman
0
150
New "Type" system on PicoRuby
pocke
1
810
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
200
CSC307 Lecture 17
javiergs
PRO
0
320
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
120
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
650
AIエージェントの隔離技術の徹底比較
kawayu
0
470
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
5
3.8k
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
250
Inside Stream API
skrb
1
680
Spec-Driven Development with AI-Agents: From High-Level Requirements to Working Software
antonarhipov
2
480
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
780
Featured
See All Featured
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.2k
Visualization
eitanlees
152
17k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
360
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
730
How to make the Groovebox
asonas
2
2.2k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.9k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
250
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
160
Mobile First: as difficult as doing things right
swwweet
225
10k
Side Projects
sachag
455
43k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
22k
Transcript
Kyash Android ͷ ΠʔελʔΤοά࣮ 2019/04/18 () Kyash Meetup #6 Kyash
Inc. @konifar
@konifar (Yusuke Konishi) • ೖࣾͯ͠14ϲ݄͘Β͍ http://konifar.hatenablog.com/entry/2019/03/22/222554 • AndroidΞϓϦ։ൃ͕ϝΠϯ • ೖ͙ࣾͯ͢͠ʹ39ΞχϝʔγϣϯΛ࣮
None
ΠʔελʔΤοά = ָ͓͠Έػೳ
ࡩΞχϝʔγϣϯ • ࡩͬΆ͍จࣈΛτϦΨʔ ʹͯ͠ɺࡩ͕͍ࢄΔʂ
http://konifar.hatenablog.com/entry/2018/06/14/173716 ࡩΞχϝʔγϣϯͷ͖͔͚ͬ
ࢭ·Βͳ͍ཉ
ࠓͨͿΜ 7छྨ͘Β͍͋Δ
ΠʔελʔΤοάͷ ίʔυ෦ͷΛ͠·͢
ੲͱࠓͷίʔυͷ
39Ξχϝʔγϣϯ͚ͩͷࠒ • ཤྺৄࡉը໘ͷViewModelͷҰ෦ʹͼ͜Δ is39() ϝιου • ࣌͜Μͳʹָ͠ΜͰΒ֦͑ͯு͍ͯ͘͠ͱࢥͬͯͳ͔ͬͨ
நԽ͢Δ
ΠʔελʔΤοάͷղ 1. ରͷॴʹ 2. ݅ʹԠͯ͡ 3. Կ͔Λදࣔ͢Δ
39Ξχϝʔγϣϯͷ߹ 1. ରͷॴʹʢૹۚྃը໘શମʹʣ 2. ݅ʹԠͯ͡ʢ39ԁͩͬͨ߹ʹʣ 3. Կ͔Λදࣔ͢ΔʢgifΛදࣔ͢Δʣ
ࡩΞχϝʔγϣϯͷ߹ 1. ରͷॴʹʢཤྺৄࡉը໘શମʹʣ 2. ݅ʹԠͯ͡ʢ࠷ޙͷϝοηʔδʹࡩͬΆ͍จࣈ͕ೖ͍ͬͯͨ߹ʹʣ 3. Կ͔Λදࣔ͢ΔʢՖͼΒͷը૾Λ߱ΒͤΔʣ
ࠓͷΞϯυϩΠυͷ࣮ 7JFX.PEFM 5JNFMJOF)FBEFS &BTUFS&HH'BDUPSZ &BTUFS&HH,FZXPSE .BUDIFS 5JNFMJOF)FBEFS &BTUFS&HH 5JNFMJOF)FBEFS &BTUFS&HH
5JNFMJOF)FBEFS &BTUFS&HH EasterEggΛදࣔ͢ΔViewModel͔Β Factoryܦ༝ͰEasterEggΦϒδΣΫτΛऔ Γग़͢ EasterEggΠϯλʔϑΣʔεΛ࣮ͯ͠ ʰදࣔ݅ʱͱʰදࣔ͢ΔϦιʔεʱΛࢦ ఆ͢Δ දࣔ݅ɺଞͷը໘ͷEasterEggΫϥε ͱڞ௨ͳͷͰɺMatcherΫϥεͱͯ͠Γ ग़͍ͯ͠Δ
|--keywords | |--EasterEggKeywordsMatcher.kt | |-—SakuraEasterEggKeywordsMatcher.kt | |…… |--timeline | |--NoTimelineHeaderEasterEgg.kt
| |--ThankYouReceiveTimelineHeaderEasterEgg.kt | |--TimelineHeaderEasterEgg.kt | |-—TimelineHeaderEasterEggFactory.kt | |…… |--transaction | |--NoTransactionEasterEgg.kt | |--ThankYouSendTransactionEasterEgg.kt | |--TransactionEasterEgg.kt | |--TransactionEasterEggFactory.kt | |…… • UIͷσΟϨΫτϦͷதʹeastereggsσΟϨΫτϦΛஔ͍͍ͯΔ
|--keywords | |--EasterEggKeywordsMatcher.kt | |-—SakuraEasterEggKeywordsMatcher.kt | |…… |--timeline | |--NoTimelineHeaderEasterEgg.kt
| |--ThankYouReceiveTimelineHeaderEasterEgg.kt | |--TimelineHeaderEasterEgg.kt | |-—TimelineHeaderEasterEggFactory.kt | |…… |--transaction | |--NoTransactionEasterEgg.kt | |--ThankYouSendTransactionEasterEgg.kt | |--TransactionEasterEgg.kt | |--TransactionEasterEggFactory.kt | |…… • ʮରͷॴʯ͝ͱʹEasterEggΫϥεͱFactoryΫϥεΛ࡞͍ͬͯΔ • timeline = ཤྺৄࡉը໘্෦ • transaction = ૹۚɾٻྃը໘શମ
interface TimelineHeaderEasterEgg { @DrawableRes fun getAnimationDrawableResId(): Int? fun shouldShow(): Boolean
} • λΠϜϥΠϯৄࡉͷ39ΞχϝʔγϣϯͷΠϯλʔϑΣʔε • Կදࣔ͠ͳ͍έʔεͷͨΊʹɺNullObjectύλʔϯͷΑ͏ͳܗͰ NoTransactionEasterEggΫϥε࡞͍ͬͯΔ class NoTransactionEasterEgg : TransactionEasterEgg { override fun getAnimationDrawableResId(): Int? = null override fun shouldShow() = false }
/** * डऔ࣌ͷ39Ξχϝʔγϣϯ */ class ThankYouReceiveTimelineHeaderEasterEgg( val amount: Long )
: TimelineHeaderEasterEgg { override fun getAnimationDrawableResId() = R.drawable.img_receive_39 override fun shouldShow() = amount == 39L } • 39ԁΛड͚औͬͨ߹ͷ࣮ • දࣔ݅ͱͳΔ shouldShow() ͷςετΛ͔ͬ͠Γॻ͍͍ͯΔ
class SakuraEasterEggKeywordsMatcher : EasterEggKeywordsMatcher { override fun getKeywords() = arrayListOf(
"͘͞Β", "αΫϥ", "ࡩ", "Ֆݟ", "ͳΈ", "ϋφϛ", "ԅ", String(byteArrayOf(-16, -97, -116, -72)) // ࡩͷemoji ) } • ͘͞ΒΞχϝʔγϣϯͷΩʔϫʔυΛఆٛ • JUnitͰParameterized TestΛॻ͘
@RunWith(Parameterized::class) class SakuraEasterEggKeywordsMatcherUnitTest( private val message: String, private val result:
Boolean ) { companion object { @JvmStatic @Parameterized.Parameters fun data(): List<Array<out Any?>> { return listOf( arrayOf("αΫϥ͕͘͞", true), arrayOf("", true), arrayOf("α Ϋϥ", false), …… ) } } @Test fun containsKeyword() { val subject = SakuraEasterEggKeywordsMatcher() assertEquals(result, subject.containsKeyword(message)) } }
class TimelineHeaderEasterEggFactory( val amount: Long, val message: String? ) {
// ద༻͞ΕΔॱʹϦετʹηοτ͍ͯ͠·͢ private val easterEggs = arrayListOf( … // ωλόϨʹͳΔͷͰφΠγϣ ThankYouReceiveTimelineHeaderEasterEgg(amount) ) fun createEasterEgg(): TimelineHeaderEasterEgg { easterEggs.forEach { if (it.shouldShow()) return it } return NoTimelineHeaderEasterEgg() } } • FactoryɺEasterEggͷϦετΛ࣋ͬͯɺ݅ʹԠͯ͡࠷ॳʹද ࣔ݅ʹ߹கͨ͠EasterEggΛฦ͢
val easterEgg = TimelineHeaderEasterEggFactory( amount, message ).createEasterEgg() …
@get:Bindable val headerEasterEggVisible: Boolean get() = easterEgg.shouldShow() @get:Bindable val headerEasterEggDrawable: Int? get() = easterEgg.getAnimationDrawableResId() • ViewModelͰEasterEggΛݩʹDataBindingͷΛܾΊͯBind • AnimationDrawableResIdgifͳͷͰɺGifDrawableΛbindͰ͖ ΔBindingAdapterΛ࡞͍ͬͯΔ https://github.com/koral--/android-gif-drawable
ࠓޙͷίʔυͷ
ʮͦͦαʔόʔαΠ υʹϩδοΫ͋Δ͖ ͡Όͳ͍ʁʯ
ʮͦ͏ͩͶʂʂʯ
ࠓޙͷ • Android/iOSʹϩδοΫ͕ࢄΒΒͳ͍Α͏ʹαʔ όʔαΠυʹϩδοΫΛدͤΔ = APIԽ • ΞχϝʔγϣϯϑΝΠϧΛΫϥΠΞϯτଆͰ࣋ͨͳ ͍Α͏ʹμϯϩʔυͷΈΛ༻ҙ͢Δ =
Ξϓ ϦαΠζͷݮ • ΫϥΠΞϯτͰͷநԽͰ༷͕ݻ·͖ͬͯͨࠓͳ Β͍͚ͬͯͦ͏
None
͍Ζ͍Ζࢼͯ͠܅͚ͩͷ ΠʔελʔΤοάΛ୳ͦ͏ʂ ※ ͪͳΈʹࣗͷkyash_id konifar ͩΑ
࠙ձͰฉ͍ͯΒ͑Ε Ͱ͖Δ͚ͩԿͰ͠·͢ ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ