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
290
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
50
Other Decks in Technology
See All in Technology
MapLibreとAmazon Location Service
dayjournal
1
130
最近たまに見かけるTiDBってなんだ? - Findy
pingcap0315
2
740
開発生産性大幅アップ!Postman VS Code拡張機能
nagix
2
350
長期間TiDBを使ってきた話 @ 私たちはなぜNewSQLを使うのかTiDB選定5社が語る選定理由と活用LT / Experiences with TiDB Over Time
chibiegg
2
850
SIEMを用いて、セキュリティログ分析の可視化と分析を実現し、PDCAサイクルを回してみた
coconala_engineer
0
270
コードを書く隙間を見つけて生きていく技術/Findy 思考の現在地
fujiwara3
27
5.7k
AOAI をきっかけに 社内の Azure 管理を見直した話
recruitengineers
PRO
1
190
VS CodeでAWSを操作しよう
smt7174
7
1.6k
Terraformあれやこれ/terraform-this-and-that
emiki
8
1.3k
20240416_devopsdaystokyo
kzkmaeda
1
200
複雑な構成要素を持つUIとの向き合い方 〜新・支出グラフでの実例〜 / B43 TECH TALK
nakamuuu
0
130
DevOpsメトリクスとアウトカムの接続にトライ!開発プロセスを通して計測できるメトリクスの活用方法
ham0215
2
230
Featured
See All Featured
The Cult of Friendly URLs
andyhume
74
5.7k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
5
1.5k
Build your cross-platform service in a week with App Engine
jlugia
225
17k
Embracing the Ebb and Flow
colly
79
4.1k
The Power of CSS Pseudo Elements
geoffreycrofte
59
5k
Adopting Sorbet at Scale
ufuk
67
8.6k
Building Adaptive Systems
keathley
30
1.9k
How to train your dragon (web standard)
notwaldorf
72
5.1k
Building a Scalable Design System with Sketch
lauravandoore
455
32k
How GitHub Uses GitHub to Build GitHub
holman
468
290k
Designing Experiences People Love
moore
136
23k
The Language of Interfaces
destraynor
151
23k
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