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
Ankoに はさんで はさまれて
Search
yamm800
July 10, 2016
Technology
0
320
Ankoに はさんで はさまれて
第一回 Kansai.kt 発表資料
AnkoとはKotlinのDSLでAndroidのUIを組み立てることができるJetBrains公式のライブラリです。
yamm800
July 10, 2016
Tweet
Share
More Decks by yamm800
See All by yamm800
Ankoに はさんで はさまれて 発表者ノート付き
yamm800
0
54
Other Decks in Technology
See All in Technology
作曲家がボカロを使うようにPdMはAIを使え
itotaxi
0
440
United airlines®️ USA Contact Numbers: Complete 2025 Support Guide
unitedflyhelp
0
100
Zero Data Loss Autonomous Recovery Service サービス概要
oracle4engineer
PRO
2
7.7k
Lazy application authentication with Tailscale
bluehatbrit
0
170
OPENLOGI Company Profile
hr01
0
67k
使いたいMCPサーバーはWeb APIをラップして自分で作る #QiitaBash
bengo4com
0
1.6k
Flutter向けPDFビューア、pdfrxのpdfium WASM対応について
espresso3389
0
130
KiCadでPad on Viaの基板作ってみた
iotengineer22
0
290
Backlog ユーザー棚卸しRTA、多分これが一番早いと思います
__allllllllez__
1
140
成長し続けるアプリのためのテストと設計の関係、そして意思決定の記録。
sansantech
PRO
0
100
Claude Code に プロジェクト管理やらせたみた
unson
5
2.5k
開発生産性を測る前にやるべきこと - 組織改善の実践 / Before Measuring Dev Productivity
kaonavi
6
1.5k
Featured
See All Featured
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.1k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
138
34k
Done Done
chrislema
184
16k
Visualization
eitanlees
146
16k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.8k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
730
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
20
1.3k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
A designer walks into a library…
pauljervisheath
207
24k
[RailsConf 2023] Rails as a piece of cake
palkan
55
5.7k
Measuring & Analyzing Core Web Vitals
bluesmoon
7
510
Transcript
"OLPʹ͞ΜͰ͞·Εͯ גࣜձࣾφνϡϥϧελΠϧ ࢁޱஐߦ
ࣗݾհ w ࢁޱஐߦ w גࣜձࣾφνϡϥϧελΠϧॴଐ
࡞͍ͬͯΔͷ w ϑΝογϣϯίʔσΟωʔτ ΞϓϦʮ8&"3ʯΛ࡞
w ͔͜͜Βຊ
"OLP w ,PUMJOͷ%4-Ͱ"OESPJEͷ6*ΛΈཱͯΔϥΠϒϥ Ϧ w +FU#SBJOTެࣜ w ·ͩόʔδϣϯ
"OLPͷϝϦοτ w 9.-Ͱͳ͍͜ͱʹΑΔϝϦοτ w 9.-Λύʔε͠ͳ͍͍ͯ͘ͷͰૣ͍ w pOE7JFX#Z*E͠ͳ͍͍ͯ͘ w ,PUMJOʹΑΔԸܙ w
ܕ҆શ w /VMM҆શ w ػೳ֦ு͕༰қ w ϥΠϒϥϦʹศརͳ͕ؔ༻ҙ͞Ε͍ͯΔ
ͪͳΈʹ1SFWJFXػೳ͍͍ͭͯ·͢
ͪͳΈʹ1SFWJFXػೳ͍͍ͭͯ·͢ ͍ͭͯ·͚͢Ͳ
όʔδϣϯͩͱ͏·͘ಈ͔ͳ͔ͬͨͷͰҙɻ ͳΒ͏·͘ಈ͖·ͨ͠
9.-Λࣗಈม͢Δπʔϧ͋Δ $PEF$POWFSUUP,PBO%4-
9.-Λࣗಈม͢Δπʔϧ͋Δ $PEF$POWFSUUP,PBO%4- "OLP͡Όͳͯ͘ ,PBOʹͳ͍ͬͯΔͷ͓͖ͯ͞
ෆຬ w %BUB#JOEJOHͱҰॹʹ͑ͳ͍ w %FMFHBUFE1SPQFSUJFTΛ͑ࣅͨΑ͏ͳ͜ͱ Ͱ͖Δ͚ΕͲͪΐͬͱ໘ w 1SFWJFXͰ9.-Ͱͷ5PPMTଐੑͷΑ͏ͳ͜ͱ͕Ͱ͖ ͳ͍ w
$POTUSBJOU-BZPVUͲ͏ͳΔ
͍͔ͨ
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) verticalLayout { val
name = editText() button("Say Hello") { // ボタンを押したらトーストを表示 onClick { ctx.toast("Hello, ${name.text}!") } } } } "DUJWJUZͷதͰ࡞Δྫ
class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?, persistentState:
PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) MyActivityUI().setContentView(this) } } class MyActivityUI : AnkoComponent<MyActivity> { override fun createView(ui: AnkoContext<MyActivity>) = with(ui) { verticalLayout { val name = editText() button("Say Hello") { onClick { ctx.toast("Hello, ${name.text}!") } } } } } ΫϥεΛ͚ͨྫ
class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?, persistentState:
PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) MyActivityUI().setContentView(this) } } class MyActivityUI : AnkoComponent<MyActivity> { override fun createView(ui: AnkoContext<MyActivity>) = with(ui) { verticalLayout { val name = editText() button("Say Hello") { onClick { ctx.toast("Hello, ${name.text}!") } } } } } ΫϥεΛ͚ͨྫ JOUFSGBDF"OLP$PNQPOFOU5\ GVODSFBUF7JFX VJ"OLP$POUFYU5 7JFX ^
class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?, persistentState:
PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) MyActivityUI().setContentView(this) } } class MyActivityUI : AnkoComponent<MyActivity> { override fun createView(ui: AnkoContext<MyActivity>) = with(ui) { verticalLayout { val name = editText() button("Say Hello") { onClick { ctx.toast("Hello, ${name.text}!") } } } } } ΫϥεΛ͚ͨྫ
class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?, persistentState:
PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) MyActivityUI().setContentView(this) } } class MyActivityUI : AnkoComponent<MyActivity> { override fun createView(ui: AnkoContext<MyActivity>) = with(ui) { verticalLayout { val name = editText() button("Say Hello") { onClick { ctx.toast("Hello, ${name.text}!") } } } } } ΫϥεΛ͚ͨྫ ΫϥεΛ͚ͯ1SFWJFXಈ͖·͢
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return UI { verticalLayout { val name = editText { } button("Say Hello") { onClick { ctx.toast("Hello, ${name.text}!") } } } }.view } 'SBHNFOUͰ͏ྫ
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return UI { verticalLayout { val name = editText { } button("Say Hello") { onClick { ctx.toast("Hello, ${name.text}!") } } } }.view } 6*\^WJFXͰ͞Ή 'SBHNFOUͰ͏ྫ
include<View>(R.layout.something) { backgroundColor = Color.RED } 9.-ΛJODMVEF
// 以下の2行を追加 (カスタムビューの中などで良い) // ViewManagerの拡張関数 inline fun ViewManager.customView(theme: Int
= 0) = customView(theme) {} inline fun ViewManager.customView(theme: Int = 0, init: CustomView.() -> Unit) = ankoView({ CustomView(it) }, theme, init) ΧελϜϏϡʔΛ"OLP%4-ͷதͰ͏
// 以下の2行を追加 (カスタムビューの中などで良い) // ViewManagerの拡張関数 inline fun ViewManager.customView(theme: Int
= 0) = customView(theme) {} inline fun ViewManager.customView(theme: Int = 0, init: CustomView.() -> Unit) = ankoView({ CustomView(it) }, theme, init) // これでカスタムビューをAnkoに はさめる frameLayout { customView { } } ΧελϜϏϡʔΛ"OLP%4-ͷதͰ͏
// 以下の2行を追加 (カスタムビューの中などで良い) // ViewManagerの拡張関数 inline fun ViewManager.customView(theme: Int
= 0) = customView(theme) {} inline fun ViewManager.customView(theme: Int = 0, init: CustomView.() -> Unit) = ankoView({ CustomView(it) }, theme, init) // これでカスタムビューをAnkoに はさめる // カスタムビューの中にも Ankoを はさめる frameLayout { customView { text = textView("Anko CustomView") } } ΧελϜϏϡʔΛ"OLP%4-ͷதͰ͏
relativeLayout { // 一意のidを生成 ids.xmlに指定しても良い var main_activity_text: Int = View.generateViewId()
textView = textView { id = main_activity_text } textView { text = "Bottom of R.id.main_activity_text" lparams { bottomOf(main_activity_text) } } } *%Λࢦఆͯ͠3FMBUJWF-BZPVUͰ͏
relativeLayout { // 一意のidを生成 ids.xmlに指定しても良い var main_activity_text: Int = View.generateViewId()
textView = textView { id = main_activity_text } textView { text = "Bottom of R.id.main_activity_text" lparams { bottomOf(main_activity_text) } } } *%Λࢦఆͯ͠3FMBUJWF-BZPVUͰ͏
relativeLayout { // 一意のidを生成 ids.xmlに指定しても良い var main_activity_text: Int = View.generateViewId()
textView = textView { id = main_activity_text } textView { text = "Bottom of R.id.main_activity_text" lparams { bottomOf(main_activity_text) } } } *%Λࢦఆͯ͠3FMBUJWF-BZPVUͰ͏
relativeLayout { // 一意のidを生成 ids.xmlに指定しても良い var main_activity_text: Int = View.generateViewId()
textView = textView { id = main_activity_text } textView { text = "Bottom of R.id.main_activity_text" lparams { bottomOf(main_activity_text) } } } *%Λࢦఆͯ͠3FMBUJWF-BZPVUͰ͏
// Toast toast(R.string.message) // アラートダイアログ alert("Hi, I'm Roy", "Have
you tried turning it off and on again?") { yesButton { toast("Oh…") } noButton {} }.show() // Activityの呼び出し startActivity<SomeOtherActivity>("id" to 5) ศརͳػೳ
// 非同期処理 doAsync { // 何か重い処理 // Acitivityがfinishしていたら呼ばれない
activityUiThreadWithContext { result.text = "Done" } } ศརͳػೳ
*NBHF7JFXͷ֦ுؔ fun ImageView.loadImage(imageUrl: String, error: Int) { Picasso.with(context).load(imageUrl).error(error).into(this) } //
Picassoを使ってイメージを読み込み imageView = imageView { loadImage("画像のURL", R.drawable.error) } ֦ுؔΛ༻͢Δ
*NBHF7JFXͷ֦ுؔ fun ImageView.loadImage(imageUrl: String, error: Int) { Picasso.with(context).load(imageUrl).error(error).into(this) } //
Picassoを使ってイメージを読み込み imageView = imageView { loadImage("画像のURL", R.drawable.error) } ֦ுؔΛ༻͢Δ ,PUMJOͷԸܙΛͦͷ··ड͚ΕΔײ͡Ͱྑ͍
͓ΘΓʹ w ,PUMJOͷΓ্͕͍ͬͯΔҹ
͓ΘΓʹ w "OLPͷͬͯ͋·Γฉ͔ͳ͍
͓ΘΓʹ w 2JJUBͰͷهࣄ݅ͱ͔ͩͬͨ͠
͓ΘΓʹ w "OLPͬͱʹͳΔͱ͍͍ͳʂ
͓ΘΓʹ w ͦΜͳΘ͚Ͱ
͓ΘΓʹ w "OLPͷ͞ΜͰ΄͍͠
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠
͕࣌ؒ͋ͬͨΒΔ
Ϩγʔό͖ؔϦςϥϧ ֦ுؔ ΛҾʹऔΔ ֦ுϓϩύςΟ ͍͍ͩͨ͜ͷΜͷػೳͰ࣮ݱ Ͳ͏͍ͬͯΔͷ͔
͘Θ͘͜͠ͷ͋ͨΓΛࢀর ,PUMJO,PBOTͷ#VJMEFSTͷষಛʹ)UNMCVJMEFSTͷ ෦ %4-ͷྫ ,PUMJO"OESPJE"#SBTT5BDLT&YQFSJNFOU (PPHMFͷਓ͕ॻ͍ͨهࣄӳޠ Ͳ͏͍ͬͯΔͷ͔
class MyListViewAdapter(var context:Context) : BaseAdapter() { override fun getView(position:Int,
convertView: View?, parent: ViewGroup?):View? { var newConvertView:View? if (convertView == null) { var ui = MyListItemUI(getItem(position), position) newConvertView = ui.createView(context.UI { }) newConvertView.tag = ui }else { newConvertView = convertView var ui = newConvertView.tag as MyListItemUI ui.label?.text = "List item: " + position newConvertView.tag = ui } return newConvertView } } class MyListItemUI(var user:User?,var position:Int) : AnkoComponent<Context> { var label : TextView? = null override fun createView(ui: AnkoContext<Context>) = with(ui) { verticalLayout { label = textView { text ="List item: " + position } } } } -JTU7JFXͰ͏ྫ
DMBTT.Z"DUJWJUZ"QQ$PNQBU"DUJWJUZ \ MB[ZΛͬͨ΄͏͕͍͍͔ WBMVJ.BJO"DUJWJUZ6JCZMB[Z\ .BJO"DUJWJUZ6J ^ PWFSSJEFGVOPO$SFBUF TBWFE*OTUBODF4UBUF#VOEMF QFSTJTUFOU4UBUF1FSTJTUBCMF#VOEMF
\ TVQFSPO$SFBUF TBWFE*OTUBODF4UBUF QFSTJTUFOU4UBUF VJTFU$POUFOU7JFX UIJT VJUFYU7JFX UFYUl"1*͔Βͱ͖ͬͯͨͱ͔z ^ ^ DMBTT.Z"DUJWJUZ6*"OLP$PNQPOFOU.Z"DUJWJUZ\ WBSUFYU7JFX5FYU7JFX OVMM PWFSSJEFGVODSFBUF7JFX VJ"OLP$POUFYU.Z"DUJWJUZ XJUI VJ \ লུ ^ ^ ΫϥεΛ͚ͨྫ
DMBTT.Z"DUJWJUZ"QQ$PNQBU"DUJWJUZ \ MB[ZΛͬͨ΄͏͕͍͍͔ WBMVJ.BJO"DUJWJUZ6JCZMB[Z\ .BJO"DUJWJUZ6J ^ PWFSSJEFGVOPO$SFBUF TBWFE*OTUBODF4UBUF#VOEMF QFSTJTUFOU4UBUF1FSTJTUBCMF#VOEMF
\ TVQFSPO$SFBUF TBWFE*OTUBODF4UBUF QFSTJTUFOU4UBUF VJTFU$POUFOU7JFX UIJT VJUFYU7JFX UFYUl"1*͔Βͱ͖ͬͯͨͱ͔z ^ ^ DMBTT.Z"DUJWJUZ6*"OLP$PNQPOFOU.Z"DUJWJUZ\ WBSUFYU7JFX5FYU7JFX OVMM PWFSSJEFGVODSFBUF7JFX VJ"OLP$POUFYU.Z"DUJWJUZ XJUI VJ \ লུ ^ ^ ΫϥεΛ͚ͨྫ
DMBTT.Z"DUJWJUZ"QQ$PNQBU"DUJWJUZ \ MB[ZΛͬͨ΄͏͕͍͍͔ WBMVJ.BJO"DUJWJUZ6JCZMB[Z\ .BJO"DUJWJUZ6J ^ PWFSSJEFGVOPO$SFBUF TBWFE*OTUBODF4UBUF#VOEMF QFSTJTUFOU4UBUF1FSTJTUBCMF#VOEMF
\ TVQFSPO$SFBUF TBWFE*OTUBODF4UBUF QFSTJTUFOU4UBUF VJTFU$POUFOU7JFX UIJT VJUFYU7JFX UFYUl"1*͔Βͱ͖ͬͯͨͱ͔z ^ ^ DMBTT.Z"DUJWJUZ6*"OLP$PNQPOFOU.Z"DUJWJUZ\ WBSUFYU7JFX5FYU7JFX OVMM PWFSSJEFGVODSFBUF7JFX VJ"OLP$POUFYU.Z"DUJWJUZ XJUI VJ \ লུ ^ ^ ΫϥεΛ͚ͨྫ
DMBTT.Z"DUJWJUZ"QQ$PNQBU"DUJWJUZ \ MB[ZΛͬͨ΄͏͕͍͍͔ WBMVJ.BJO"DUJWJUZ6JCZMB[Z\ .BJO"DUJWJUZ6J ^ PWFSSJEFGVOPO$SFBUF TBWFE*OTUBODF4UBUF#VOEMF QFSTJTUFOU4UBUF1FSTJTUBCMF#VOEMF
\ TVQFSPO$SFBUF TBWFE*OTUBODF4UBUF QFSTJTUFOU4UBUF VJTFU$POUFOU7JFX UIJT VJUFYU7JFX UFYUl"1*͔Βͱ͖ͬͯͨͱ͔z ^ ^ DMBTT.Z"DUJWJUZ6*"OLP$PNQPOFOU.Z"DUJWJUZ\ WBSUFYU7JFX5FYU7JFX OVMM PWFSSJEFGVODSFBUF7JFX VJ"OLP$POUFYU.Z"DUJWJUZ XJUI VJ \ লུ ^ ^ ΫϥεΛ͚ͨྫ
DMBTT.Z"DUJWJUZ"QQ$PNQBU"DUJWJUZ \ MB[ZΛͬͨ΄͏͕͍͍͔ WBMVJ.BJO"DUJWJUZ6JCZMB[Z\ .BJO"DUJWJUZ6J ^ PWFSSJEFGVOPO$SFBUF TBWFE*OTUBODF4UBUF#VOEMF QFSTJTUFOU4UBUF1FSTJTUBCMF#VOEMF
\ TVQFSPO$SFBUF TBWFE*OTUBODF4UBUF QFSTJTUFOU4UBUF VJTFU$POUFOU7JFX UIJT VJUFYU7JFX UFYUl"1*͔Βͱ͖ͬͯͨͱ͔z ^ ^ DMBTT.Z"DUJWJUZ6*"OLP$PNQPOFOU.Z"DUJWJUZ\ WBSUFYU7JFX5FYU7JFX OVMMຊ͜͜ͰOVMMΛೖΕͨ͘ͳ͍ʜʜԿ͔͍͍ํ๏ PWFSSJEFGVODSFBUF7JFX VJ"OLP$POUFYU.Z"DUJWJUZ XJUI VJ \ লུ ^ ^ ΫϥεΛ͚ͨྫ
class ViewBinder<M>(val function: (M) -> Unit) : ReadWriteProperty<Any, M> {
private var mValue: M? = null override fun getValue(thisRef: Any, property: KProperty<*>): M = mValue as M override fun setValue(thisRef: Any, property: KProperty<*>, value: M) { mValue = value function(value) } } /////////////////////////////////////// var user: User? by ViewBinder { // userのセッターが呼ばれた時にこの関数が呼ばれる // このときActivityがクローズされていたら? // activityUiThreadWithContextの中で呼ぶこと when (it) { null -> { } else -> { ui.textView?.apply { text = it?.name } } } } 7JFX#JOEFS