Kotlin玩Android第01篇 使用Anko Layout建立第一個App


情境(Context):

    此文章是記錄我用Kotlin學習Android應用的第一個紀錄,
將會採用Anko Layout的方式去設計我的App畫面。
    我曾在大一時學過Java,但我並沒有用它撰寫過Android程式(直到現在XD)。
    作業系統:OSX 10.13.2  
    開發環境:Android Studio 3.0.1 
    Anko版本: 0.10.4
    手機系統: Android 7.1.1

問題(Problem):

    首先Kotlin在Android一樣可以用layout資源裡的XML進行畫面排版,
雖然XML太難寫可讀性又很差,
但Android Studio可以透過拖曳物件的方式進行構圖,並且有很多視覺化的設計元件。
到底為什麼還要學Anko Layout的DSL?

    Anko Layout有說明不使用XML的幾個理由。

排除掉XML解析成Java程序要耗費手機CPU資源這類原因。
個人喜歡DSL的理由主要是:
1. DSL寫起來更符合Kotlin的簡潔風格,Layout的預設參數是好物。
2.邏輯排版 & 配合使用Anko函數都很簡單。
3. 帥!

缺點大概就是無法拖曳物件排版,據說可以用Plugin將排版完的xml轉成anko layout,但要反向轉換就沒辦法了。(個人沒試過將xml轉成DSL)

Anko小知識:
如果你想在AndroidStudio 中預覽Anko Layout的視覺構圖,
請點選"Preferences" -> "Plugin" -> "install JetBrains plugin" -> 安裝套件 Anko Support

言歸正傳,我們真正想研究的問題是如何用Anko寫一個App
功能包含 按鈕觸發、垂直排版、換頁、換頁傳遞資料

答案(Solution):

第零步:先安裝JDK8 然後安裝AndroidStudio 3

第一步:配置Anko環境

1-1 建立一個有Empty的Kotlin專案

1-2 配置Gradle

build.gradle(Project:專案名稱)檔案中buildscript的{ }內部添加一行。
ext.anko_version='0.10.4'
build.gradle(Module:App)檔案中
dependencies的{}中添加數行
    // Anko Commons
    compile "org.jetbrains.anko:anko-commons:$anko_version"

    // Anko Layouts
    compile "org.jetbrains.anko:anko-sdk25:$anko_version" // sdk15, sdk19, sdk21, sdk23 are also available
    compile "org.jetbrains.anko:anko-appcompat-v7:$anko_version"

    // Coroutine listeners for Anko Layouts
    compile "org.jetbrains.anko:anko-sdk25-coroutines:$anko_version"
    compile "org.jetbrains.anko:anko-appcompat-v7-coroutines:$anko_version"

第二步:撰寫Anko Layout


2-1 將DSL寫在onCreate()內部
// 設計一個垂直佈局,那就打個verticalLayout
verticalLayout {
// 一個輸入文字匡
editText {
hint = "請輸入訊息"
textSize = 26F
}
// 一個按鈕
button {
text = "確認" // 按鈕文字設定為 "確認"
textSize = 26F // 設定字體大小
}
}

2-2 按鈕想加一個點擊事件,加一個onClick{}
verticalLayout {
// 一個按鈕
button {
text = "確認" // 按鈕文字設定為 "確認"
textSize = 26F // 設定字體大小
onClick{ // 點擊監聽
toast("You click me") // Anko的Toast版,功用為跳出一段訊息"You click me"
}
}
}

2-3 將editText的文字內容傳給下一個Activity
// 設計一個垂直佈局,那就打個verticalLayout
verticalLayout {
// 將editText指定給變數 name
val name = editText {
hint = "請輸入訊息"
textSize = 26F
}
// 一個按鈕
button {
text = "確認" // 按鈕文字設定為 "確認"
textSize = 26F // 設定字體大小
onClick {
// 意思大致上為將name.text內容 傳給SecondActivity
startActivity<SecondActivity>("name" to name.text)
}
}
}

2-4 接收到intent參數(就是2-3傳遞的參數)
// 用toast訊息顯示 intent傳進來的name值
val name = intent.getStringExtra("name")
toast("name = $name")

完整程式碼:
manifests的設定:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ankoapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity"
android:parentActivityName=".MainActivity">
</activity>
</application>
</manifest>
view raw manifest.xml hosted with ❤ by GitHub
MainActivity的程式碼:
package com.example.ankoapp
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import org.jetbrains.anko.*
import org.jetbrains.anko.sdk25.coroutines.onClick
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_main)
verticalLayout{
val name = editText("姓名"){
hint="請輸入姓名"
textSize = 26F
}
button("確認"){
textSize = 26F
onClick{
val name_text = name.text.toString()
if(name_text == ""){
longToast("你沒有填入姓名")
return@onClick
}
startActivity<SecondActivity>("name" to name_text)
}
}
}
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

SecondActivity的程式碼:
package com.example.ankoapp
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.TextView
import org.jetbrains.anko.*
/**
* Created by guzongjia on 2018/1/29.
*/
val VIEW_ID = 1
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
SecondUI().setContentView(this)
// 用toast訊息顯示 intent傳進來的name值
val name = intent.getStringExtra("name")
toast("name = $name")
// 直接修改TextView的內容
find<TextView>(VIEW_ID).text = "你好啊!$name"
}
}
class SecondUI(): AnkoComponent<SecondActivity> {
override fun createView(ui: AnkoContext<SecondActivity>) = with(ui) {
verticalLayout{
textView {
id = VIEW_ID
textSize = 26F
}
seekBar {
}
}
}
}

留言

這個網誌中的熱門文章

Kotlin玩Android第03篇 Listview(01 ArrayAdapter)

使用Intent在Activity間傳遞資料(bundle)

golang本地測試如何繞過防火牆詢問允許