使用Kotlin開發Android應用(IV):自定義視圖和Android擴展
在讀完擴展函數和默認值這篇文章之后,那么接下來要介紹什么呢?在本系列第一篇文章中我們說過,Kotlin使得Android開發更加簡單,本文我們將進一步作介紹。
自定義視圖
你應該還記得,在說到Kotlin的局限性時,我們提到了在Kotlin早期版本(M10之前)是不支持自定義視圖的,因為當時只能為每個類創建一個構造函數。這通常是足夠的,因為使用可選參數,我們可以創建足夠多的構造函數變種,例如:
class MyClass(param: Int, optParam1: String = "", optParam2: Int = 1)
{
init {
// Initialization code
}
}
通過這一個構造函數,我們有如下四種方式創建這個類:
val myClass1 = MyClass(1)
val myClass2 = MyClass(1, "hello")
val myClass3 = MyClass(param = 1, optParam2 = 4)
val myClass4 = MyClass(1, "hello", 4)
正如你所見,使用可選參數我們得到了一堆的組合。但是通過繼承普通Views的方式來創建自定義Views時,我們可能會遇到問題。自定義Views需要重寫一個或者多個構造函數以便正常工作,但我們做不到這一點。幸運的是,自動Kotlin M11開始,我們可以聲明多個構造函數,類似Java。下面是一個正方形的ImageView:
class SquareImageView : ImageView {
public constructor(context: Context) : super(context) {
}
public constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
}
public constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val width = getMeasuredWidth()
setMeasuredDimension(width, width)
}
}
通過很簡單的代碼我們實現了自定義Views。
Kotlin Android擴展
從Kotlin M11開始增加的擴展插件使得Android開發者更容易取得XML文件中定義的Views。你可能會覺得它很像ButterKnife,但使用起來更簡單。
Kotlin Android擴展本質上是一個視圖綁定,使得開發者在代碼中通過id就可以使用XML文件中定義的Views。它將自動為Views創建屬性值,而不用使用第三方注解框架或者findViewById函數。
要使用這個特性,首先需要安裝插件“Kotlin Android Extension”,并在build.gradle文件的構建腳本依賴中增加一個新的classpath:
buildscript {
…
dependencies {
…
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
}
}
假如你定義了名為main.xml的布局文件:
<FrameLayout
xmlns:android="..."
android:id="@+id/frameLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/welcomeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
如果想在Activity中使用這個文件里面定義的Views,你只需要導入這個xml文件的synthetic屬性值,如下所示:
import kotlinx.android.synthetic.<xml_name>.*
具體到我們的例子,則如下所示:
import kotlinx.android.synthetic.main.*
這樣你就可以使用id來取得這些views的引用了:
override fun onCreate(savedInstanceState: Bundle?) {
super<BaseActivity>.onCreate(savedInstanceState)
setContentView(R.id.main)
frameLayout.setVisibility(View.VISIBLE)
welcomeText.setText("I′m a welcome text!!")
}
總結
這兩個新特性的引入,讓我們看到了Kotlin團隊致力于讓Android開發更簡單。他們也發布了一個名為Anko的函數庫,這個一門從Kotlin文件創建Android布局的領域特定語言(DSL)。我還沒有使用過它的主要功能,但當處理Android視圖時,你可以使用它來簡化代碼。在我上傳到Github上的開源項目Bandhook-Kotlin也有相關的例子。
下一篇文章將介紹lambda表達式的使用,以及它如何簡化代碼和擴展語言的特性。非常有趣的一個特性,在我看來,這是Kotlin相比Java 1.7最強大的方面。
歡迎關注我的微信公眾號