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
#22 CA × atmaCup 3rd 1st Place Solution
yumizu
1
140
『君の名は』と聞く君の名は。 / Your name, you who asks for mine.
nttcom
1
150
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
4
21k
SES向け、生成AI時代におけるエンジニアリングとセキュリティ
longbowxxx
0
310
ハッカソンから社内プロダクトへ AIエージェント ko☆shi 開発で学んだ4つの重要要素
leveragestech
0
610
会社紹介資料 / Sansan Company Profile
sansan33
PRO
11
390k
自己管理型チームと個人のセルフマネジメント 〜モチベーション編〜
kakehashi
PRO
5
2.4k
2025年 山梨の技術コミュニティを振り返る
yuukis
0
150
Introduction to Sansan Meishi Maker Development Engineer
sansan33
PRO
0
330
コールドスタンバイ構成でCDは可能か
hiramax
0
130
「アウトプット脳からユーザー価値脳へ」がそんなに簡単にできたら苦労しない #RSGT2026
aki_iinuma
9
4.5k
kintone開発のプラットフォームエンジニアの紹介
cybozuinsideout
PRO
0
470
Featured
See All Featured
The Limits of Empathy - UXLibs8
cassininazir
1
200
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Agile that works and the tools we love
rasmusluckow
331
21k
Technical Leadership for Architectural Decision Making
baasie
0
200
The Pragmatic Product Professional
lauravandoore
37
7.1k
Marketing to machines
jonoalderson
1
4.5k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.3k
Ethics towards AI in product and experience design
skipperchong
1
160
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
210
Game over? The fight for quality and originality in the time of robots
wayneb77
1
76
Code Reviewing Like a Champion
maltzj
527
40k
Designing for humans not robots
tammielis
254
26k
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