Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ankoに はさんで はさまれて

yamm800
July 10, 2016

Ankoに はさんで はさまれて

第一回 Kansai.kt 発表資料

AnkoとはKotlinのDSLでAndroidのUIを組み立てることができるJetBrains公式のライブラリです。

yamm800

July 10, 2016
Tweet

More Decks by yamm800

Other Decks in Technology

Transcript

  1. "OLPͷϝϦοτ w 9.-Ͱͳ͍͜ͱʹΑΔϝϦοτ w 9.-Λύʔε͠ͳ͍͍ͯ͘ͷͰૣ͍ w pOE7JFX#Z*E͠ͳ͍͍ͯ͘ w ,PUMJOʹΑΔԸܙ w

    ܕ҆શ w /VMM҆શ w ػೳ֦ு͕༰қ w ϥΠϒϥϦʹศརͳؔ਺͕༻ҙ͞Ε͍ͯΔ
  2. override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 
 verticalLayout {
 val

    name = editText()
 button("Say Hello") {
 // ボタンを押したらトーストを表示
 onClick { ctx.toast("Hello, ${name.text}!") }
 }
 }
 } "DUJWJUZͷதͰ࡞Δྫ 
  3. 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}!") }
 }
 }
 }
 } ΫϥεΛ෼͚ͨྫ 
  4. 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 ^
  5. 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}!") }
 }
 }
 }
 } ΫϥεΛ෼͚ͨྫ 
  6. 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͸ಈ͖·͢
  7. 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Ͱ࢖͏ྫ 
  8. 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Ͱ࢖͏ྫ 
  9. // 以下の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-ͷதͰ࢖͏ 
  10. // 以下の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-ͷதͰ࢖͏ 
  11. // 以下の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-ͷதͰ࢖͏ 
  12. 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Ͱ࢖͏ 
  13. 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Ͱ࢖͏ 
  14. 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Ͱ࢖͏ 
  15. 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Ͱ࢖͏ 
  16. // 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) ศརͳػೳ 
  17. // 非同期処理
 
 doAsync {
 // 何か重い処理
 
 // Acitivityがfinishしていたら呼ばれない


    activityUiThreadWithContext {
 result.text = "Done"
 }
 } ศརͳػೳ 
  18. *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)
 } ֦ுؔ਺Λ࢖༻͢Δ 
  19. *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ͷԸܙΛͦͷ··ड͚ΕΔײ͡Ͱྑ͍
  20. 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Ͱ࢖͏ྫ 
  21. 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 \ লུ ^ ^ ΫϥεΛ෼͚ͨྫ 
  22. 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 \ লུ ^ ^ ΫϥεΛ෼͚ͨྫ 
  23. 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 \ লུ ^ ^ ΫϥεΛ෼͚ͨྫ 
  24. 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 \ লུ ^ ^ ΫϥεΛ෼͚ͨྫ 
  25. 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 \ লུ ^ ^ ΫϥεΛ෼͚ͨྫ 
  26. 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