Kotlin向けAndroid UI構築用ライブラリAnko Wiki要約

※[Understanding Anko](https://github.com/Kotlin/anko/wiki/Anko-Layouts#understanding-anko)をほぼ日本語訳しただけのものですが、ご了承ください。
※また、私自身、英語力には自信がありませんので、誤りがありましたらご指摘ください。

#基本
Ankoライブラリを利用するために、`org.jetbrains.anko.*`パッケージをインポートしましょう。

それでは、`onCreate()`の例を見てみましょう。

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    verticalLayout {
        padding = dip(30)
        editText {
            hint = "Name"
            textSize = 24f
        }
        editText {
            hint = "Password"
            textSize = 24f
        }
        button("Login") {
            textSize = 26f
        }
    }
}
```

Ankoでは、このようなDSLで記述できます。従来のように、`setContentView(R.layout.something)`を呼び出す必要はありません。
これを詳しく見れば、

- `hint`, `textSize`: JavaBeansのgetter/setter仕様に乗っ取った拡張プロパティ
- `padding`: Ankoの拡張プロパティ
- `verticalLayout`, `editText`, `button` : `View`インスタンスを生成し、親`View`に追加する拡張関数

であることがわかります。

このような記法は、Androidフレームワーク下のほぼ全ての`View`に採用され、`Activity`, `Fragment`, `Context`上で動作します。

#AnkoComponent
前項では、`onCreate()`内にDSLを記述しましたが、通常は別のクラスを作ったほうが良いでしょう。
以下のように、`onCreate()`内で、`AnkoComponent`インターフェースを実装したクラスのインスタンスの`setContentView()`を呼び出しましょう。

```kotlin
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}!") }
            }
        }
    }
}
```

#ブロックの省略
もし`View`にプロパティが不要であれば、{}を省略して、`button("Ok")`や`button()`とできます。

例:

```kotlin
verticalLayout {
    button("Ok")
    button(R.string.cancel)
}
```

また、以下のように、テンプレートを付加することもできます。

```kotlin
verticalLayout {
    themedButton("Ok", theme = R.style.myTheme)
}
```

※Themed blocksを利用し次第、書き改めます。

#レイアウトの記述
レイアウトを記述する際に、従来では、XML内に、

```xml
<ImageView 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="5dip"
    android:layout_marginTop="10dip"
    android:src="@drawable/something" />
```

のように記述していましたが、Ankoでは、`View`の後ろに`lparams()`を続けて、

```kotlin
linearLayout {
    button("Login") {
        textSize = 26f
    }.lparams(width = wrapContent) {
        horizontalMargin = dip(5)
        topMargin = dip(10)
    }
}
```

のように記述できます。`width`や`height`は、`lparams()`の名前付き引数として定義されており、省略した場合は、いずれも`wrapContext`のデフォルト値が使用されます。
また、

- `horizontalMargin` : 左右
- `verticalMargin` : 上下
- `margin` : 上下左右

のプロパティを用いることで、対応する余白が同時に指定できます。

`lparams()`の記述はレイアウト(`ViewGroup`)によって異なります。例えば、`RelativeLayout`であれば、

```kotlin
val ID_OK = 1

relativeLayout {
    button("Ok") {
        id = ID_OK
    }.lparams { alignParentTop() }
  
    button("Cancel").lparams { below(ID_OK) }
}
```

となります。

#Listeners
ボタンを作成する際、

```kotlin
button("Login") {
    onClick {
        // do something
    }
}
```

と記述していました。実はこれ、

```kotlin
button.setOnClickListener(object : OnClickListener {
    override fun onClick(v: View) {
    	launch(UI) {
    	    // do something
    	}
    }
})
```

とほぼ同じ記述なのです。つまり、拡張関数内でコルーチンが作成されるため、非同期処理をシームレスに記述することができるのです。

Ankoには、他にも可読性を向上させる記述方法があります。例えば、

```kotlin
seekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
        // Something
    }
    override fun onStartTrackingTouch(seekBar: SeekBar?) {
        // Just an empty method
    }
    override fun onStopTrackingTouch(seekBar: SeekBar) {
        // Another empty method
    }
})
```

を現在のAnkoでは、

```kotlin
seekBar {
    onSeekBarChangeListener {
        onProgressChanged { seekBar, progress, fromUser ->
            // Something
        }
    }
}
```

と記述できます。`onProgressChanged()`と`onStartTrackingTouch()`を同じ`View`内に記述することも可能です。同じ関数を呼び出した場合は、最後に呼び出したものが適用されます。

また、以下のように、自前のコルーチンコンテキストを利用することもできます。

```kotlin
button("Login") {
    onClick(yourContext) {
    	val user = myRetrofitService.getUser().await()
        showUser(user)
    }
}
```

#リソースの扱い

前項までの例では、文字列をそのまま用いていましたが、本来ならば、文字列データは`res/values/`ディレクトリ以下にあり、実行時に呼ばれるべきです。
もちろんAnkoでも、今まで、`getString(R.string.login)`と記述していたように、
`button(R.string.login)`
や
`button { textResource = R.string.login }`
と記述することが可能です。ここで注意しなければならないのが、`text`, `hint`, `image`ではなく、`textResource`, `hintResource`, `imageResource`を用いる必要があるということです。

#インスタンスの取得
Ankoでは、`ctx`と記述するだけで、`Context`インスタンスを取得できます。インナークラスであっても、`this@SomeActivity`と記述する必要はありません。また、`Activity`インスタンスは`act`で取得できます。

#DSL内でXMLを利用する
`include()`を用いて、

```kotlin
include<View>(R.layout.something) {
    backgroundColor = Color.RED
}.lparams(width = matchParent) { margin = dip(12) }
```

と記述することで、簡単にXMLをDSLに挿入できます。
`lparams()`はいつでも利用でき、`View`以外の特定の型を用いる場合も同じ記述ができます。

例:

```kotlin
include<TextView>(R.layout.textfield) {
    text = "Hello, world!"
}
```

#参考
https://github.com/Kotlin/anko/wiki/Anko-Layouts#understanding-anko