Anko for Android
Anko 是一個使開發Android應用更簡單更快捷的庫,Anko使你的程式碼簡潔易懂, 使開發者不用再在意Android SDK對Java版本的限制(目前還不支援Java8 =。= ).
Anko版本的 hello world
:
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
上面的程式碼建立了一個Button,放在 LinearLayout
內, 併為其設定了一個點選監聽器OnClickListener
.
上面是一個DSL(Domain Specific Language),使用的是 Kotlin語言.
DSL,即 Domain Specific Language,領域相關語言。什麼是 DSL,說白了它就是某個行業中的行話。
[TOC]
Why Anko?
為啥 DSL?
平時開發android, UI寫在xml中,這就導致了下面的幾個問題 :
- It is not typesafe
- It is not null-safe
- It forces you to write almost the same code for every layout you make
- XML is parsed on the device wasting CPU time and battery 渲染xml為物件過程耗時耗電
- Most of all, it allows no code reuse. 大部分不能重用
但是全部只在程式碼中寫UI,這很難,不僅程式碼醜,而且冗餘難維護,下面是 Ktolin版本的(Java甚至更長):
val act = this
val layout = LinearLayout(act)
layout.setOrientation(LinearLayout.VERTICAL)
val name = EditText(act)
val button = Button(act)
button.setText("Say Hello")
button.setOnClickListener {
Toast.makeText(act, "Hello, ${name.getText()}!", Toast.LENGTH_SHORT).show()
}
layout.addView(name)
layout.addView(button)
DSL 就不一樣類,相同的邏輯,但簡潔易懂, 易於編寫而且沒有執行開銷(runtime overhead)看下面的程式碼:
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
為啥不用 Scaloid?
Scaloid 是一個類似與 Scala 的庫, 有很多非常酷的特性可供 Scala 開發者使用. Anko主要是針對 Java 和 Kotlin developers.
相容已有的程式碼
不需要用Anko重寫所有的UI, 你可以保留原有的Java程式碼. 此外, 如果你想寫一個 Kotlin的activity類並且由於某些需求需要使用 inflate來渲染xml, 你完全可以按照原來的寫法:
// Same as findViewById(), simpler to use
val name = find<TextView>(R.id.name)
name.hint = "Enter your name"
name.onClick { /*do something*/ }
工作原理
There is no :tophat:. Anko 由一些 Kotlin的 擴充套件函式和屬性,被設定成型別安全(type-safe builders)的, under Type Safe Builders.
他們繁瑣的手工編寫所有這些擴充套件, 使用Android SDK的原始碼中的 android.jar 檔案自動生成
可擴充套件嗎?
答案是: yes.
例如. 你可能想使用 MapView
在DSL中.你可以編寫下面的程式碼(kotlin檔案中),然後就可已到處使用了
public inline fun ViewManager.mapView() = mapView {}
public inline fun ViewManager.mapView(init: MapView.() -> Unit): MapView {
return ankoView({ MapView(it) }, init)
}
{ MapView(it) }
是你自定義View的一個工廠方法View
. 接受一個 Context
.
frameLayout {
val mapView = mapView().lparams(width = matchParent)
}
如果你想建立一個 頂級的 DSL,看這裡Extending Anko.
使用 Gradle
這裡有個例子 template project 展示類如果在Android中Gradle配置.
基本上,你只需要配置 repository
和一個 compile dependency
:
dependencies {
compile 'org.jetbrains.anko:anko-sdk15:0.7.1' // sdk19, sdk21, sdk23 are also available
compile 'org.jetbrains.anko:anko-support-v4:0.7.1' // In case you need support.v4 bindings
}
當作 Jar library使用
加入你的專案不是基於Gradl, 不需要配置 Maven. 只要新增這裡 的jar包即可.
編譯 Anko
如何編譯看under Building.
理解 Anko
Anko 是使用 Kotlin語言編寫的.
如果不熟悉Kotlin看 kotlinlang.org.
Kotlin與Java很類似,所以很容易學.
基礎
Anko中, 你不需要繼承其他奇怪的類,只要標準的Activity
, Fragment
, FragmentActivity
或者其他任意的類
首先, 在使用Anko的DSL的類中匯入 org.jetbrains.anko.*
.
DSL 可以在 onCreate()
中使用:
override fun onCreate(savedInstanceState: Bundle?) {
super<Activity>.onCreate(savedInstanceState)
verticalLayout {
padding = dip(30)
editText {
hint = "Name"
textSize = 24f
}
editText {
hint = "Password"
textSize = 24f
}
button("Login") {
textSize = 26f
}
}
}
不需要顯示的呼叫 setContentView(R.layout.something)
, Anko 自動為Activity(只會對Activity)進行 set content view
padding
, hint
和 textSize
是 擴充套件屬性. 大多數 View
具有這些屬性,允許使用text = "Some text"
代替 setText("Some text")
.
verticalLayout
(一個豎直方向的 LinearLayout
), editText
和 button
are
擴充套件函式. 這些函式存在與ANdroid 框架中的大部View中, Activities
, Fragments
( android.support
包中的) 甚至 Context
同樣適用.
如果有一個 Context
例項, 可以寫出下面的DSL結構:
val name = with(myContext) {
editText {
hint = "Name"
}
}
變數 name
成為了 EditText
型別.
Helper 方法
你可能注意到了,前面章節中 button
方法接了一個字串引數,這樣的Helper方法同樣使用與 TextView
, EditText
, Button
, ImageView
.
如果你不需要 View
其他的屬性,你可以省略 {}
直接寫 button("Ok")
或只有 button()
:
verticalLayout {
button("Ok")
button("Cancel")
}
Layouts 和 LayoutParams
在父佈局中佈局控制元件可能需要使用 LayoutParams
. 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
來實現類似與xml的 LayoutParams
。
linearLayout {
button("Login") {
textSize = 26f
}.lparams(width = wrapContent) {
horizontalMargin = dip(5)
topMargin = dip(10)
}
}
如果指定了 lparams
,但是沒有指定 width
或者 height
, 預設是 WRAP_CONTENT
.但是你可以自己通過使用named arguments指定.
注意下面一些方便的屬性:
-
horizontalMargin
同時設定 left 和 right margins, -
verticalMargin
同時設定 top 和 bottom -
margin
同時設定4個方向的 margins.
注意 lparams
的使用在不同的佈局中是不同的, 例如在 RelativeLayout
中:
val ID_OK = 1
relativeLayout {
button("Ok") {
id = ID_OK
}.lparams { alignParentTop() }
button("Cancel").lparams { below(ID_OK) }
}
Listeners
設定listeners:
button("Login") {
onClick {
login(name, password)
}
}
下面的效果一樣:
button.setOnClickListener(object : OnClickListener {
override fun onClick(v: View) {
login(name, password)
}
})
當一個Listener有多個方法時,Anko就顯得很方便類. 看下面的程式碼(沒有使用Anko):
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:
seekBar {
onSeekBarChangeListener {
onProgressChanged { seekBar, progress, fromUser ->
// Something
}
}
}
如果你同時設定了onProgressChanged
和 onStartTrackingTouch
, 兩個方法將被合併. 對於多個相同的方法,最後的一個有效.
Resources, Colors 和 Dimensions
Using resource identifiers
前面的所有例子直接使用的 Java的字串,但是大多數時候字串都是放在 res/values/
目錄下,並且是執行時呼叫的,例如 getString(R.string.login)
.
幸運的是,Anko中可以使用以下兩個 helper方法 (button(R.string.login)
) 和 (button { textResource = R.string.login }
).
注意,這些屬性不是 text
, hint
, image
, 而是 textResource
, hintResource
and imageResource
.
Resource properties always throw
AnkoException
when read.
Colors
兩個簡單的擴充套件函式使程式碼更加易懂。
Function | Result |
---|---|
0xff0000.opaque |
<span style="color:#ff0000">non-transparent red</span> |
0x99.gray.opaque |
<span style="color:#999">non-transparent #999999 gray</span> |
Dimensions
你可以指定 dimension 的 dip (density-independent pixels) 或 sp (scale-independent pixels)值: dip(dipValue)
或 sp(spValue)
. 注意 textSize
屬性預設接受sp (textSize = 16f
). 使用 px2dip
和 px2sp
相互轉換.
Instance shorthands
在Activity中,有時你需要傳一個 Context
例項給一個 Android SDK中的方法,通常你會寫 this
, 如果在內部類呢?你可能寫SomeActivity.this
,如果你使用 Kotlin,你只需寫 this@SomeActivity
,
使用 Anko,你可以只寫 ctx
. ctx
是Activity
和 Service
或者 Fragment
(使用的 getActivity()
)內部的一個屬性. 你也可以使用act
擴充套件屬性獲取 Activity
例項.
UI wrapper
開始使用Anko 之前,將 UI
tag 作為 DSL 頂級元素:
UI {
editText {
hint = "Name"
}
}
這將更易於擴充套件 DSL ,因為你必須宣告一個函式 ViewManager.customView
.
看這裡 Extending Anko 獲取更多資訊.
Include tag
使用 include
tag 很容易向 DSL 插入 一個 XML layout :
include<View>(R.layout.something) {
backgroundColor = Color.RED
}.lparams(width = matchParent) { margin = dip(12) }
通常可以使用 lparams
, 如果型別不是 View
,仍然可以用 {}
:
include<TextView>(R.layout.textfield) {
text = "Hello, world!"
}
Styles
Anko 支援 styling: style
是一個簡單的函式,接受一個View
, 效果作用於這個 View
, 並且當這個View
是一個ViewGroup
時,可以可以遞迴的作用與 這個View的 child View:
verticalLayout {
editText {
hint = "Name"
}
editText {
hint = "Password"
}
}.style { view -> when(view) {
is EditText -> view.textSize = 20f
}}
相關文章
- 為什麼每個Android開發者都應該使用AnkoAndroid
- 帶你全方位使用Anko庫-上篇
- Golang 開源庫分享:anko - 給 Go 加點“指令碼魔法”Golang指令碼
- kotlin小白日記2「工具類的封裝,Anko簡化吐司,空值處理」Kotlin封裝
- Android學習—— Android佈局Android
- Android之android exported="false"作用AndroidExportFalse
- [Android元件化]Android app BundleAndroid元件化APP
- 聚焦 Android 11: Android 開發者工具Android
- 【Android】Android設計準則Android
- Android Transition(Android過渡動畫)Android動畫
- 愛上Android之初識AndroidAndroid
- [Android]Android原始碼下載Android原始碼
- [android]android命令列截圖Android命令列
- 迴歸Android Focus on Android.Android
- AndroidAndroid
- android:id="@android:id/tabhost" 、android:id="@+id/llRoot" 、android:id="@id/llRoot" 之間的區別Android
- android開發 之 Bolts-AndroidAndroid
- Android總結篇系列:Android ServiceAndroid
- Android APIs (Class Index - Android SDK)(一)AndroidAPIIndex
- Android APIs (Class Index - Android SDK)(二)AndroidAPIIndex
- Android元件---重新認識Android(2)Android元件
- 【Android】Android 簽名相關問題Android
- Android 面試(五):探索 Android 的 HandlerAndroid面試
- 【Android】神奇的android:clipChildren屬性Android
- 【Android】Android輸入子系統Android
- [Android]calabash-android再深入Android
- android之 Android訊息機制Android
- [android]android自動化測試Android
- [android]android-am命令的使用Android
- [Android]android自動化測試十六之calabash-androidAndroid
- Android Wear-Detecting Location on Android Wear,Requesting Permissions on Android WearAndroid
- [Android Pro] android 4.4 Android原生許可權管理:AppOpsAndroidAPP
- android之android:paddingLeft和android:layout_marginLeft區別: 分類: Android android開發實踐 Android入門教程 2011-0...Androidpadding
- 【Android SDK】在命令列管理Android SDKAndroid命令列
- Android之Service設定android:process作用Android
- Android Studio 2.0 to Android Studio 3.0Android
- Android非同步----重新認識Android(6)Android非同步
- Android屬性設定android:noHistory="true"Android