尝鲜使用Kotlin写了一段时间Android。说大幅度的减少了Java代码一点不夸张。用Java的时候动不动就new一个OnClickListener()
匿名类,动不动就类型转换的地方都可以省下很多。更不用说特殊的地方使用data class
更是少些不知道多少代码。
Jetbrains给Android带来的不仅是Kotlin,还有Anko。从Anko的官方说明来看这是一个雄心勃勃的要代替XML写Layout的新的开发方式。Anko最重要的一点是引入了DSL(Domain Specific Language)的方式开发Android界面布局。当然,本质是代码实现布局。不过使用Anko完全不用经历Java纯代码写Android的痛苦。因为本身是来自Kotlin的,所以自然的使用这种方式开发就具有了:
* 类型安全,不再需要那么多的findById()
之后的类型转换。
* null安全,Kotlin里,如果一个变量用?表示为可空,并且使用?之后再调用的时候,即使变量为空也不会引发异常。
* 无需设备解析XML,因为Anko本质是代码实现的界面和布局,所以省去了这些麻烦。
* 代码复用,可以通过继承AnkoComponent
的方式实现代码复用。XML布局是每一个Activity,每一个View各自专属一个,
代码复用比较少。
来一个列子看一下。为了不太墨迹,一些不必要的xml声明此处略去。
<RelativeLayout>
<TextView
android:id="@+id/sample_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="Sample text view"
android:textSize="25sp" />
<Button
android:id="@+id/sample_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/sample_text_view"
android:text="Sample button" />
</RelativeLayout>
relativeLayout {
val textView = textView("Sample text view") {
textSize = 25f
}.lparams {
width = matchParent
alignParentTop()
}
button("Sample button").lparams {
width = matchParent
below(textView)
}
}
准备工作
首先,安装一个Kotlin的插件是必须的。有了这个插件才可以使用Kotlin,然后才可以使用Anko。安装这个插件和Android Studio里安装别的插件市一样的。只需要使用Kotlin查找就可以找到,之后安装即可。
在build.gradle里添加下面的代码:
dependencies {
compile 'org.jetbrains.anko:anko-sdk15:0.8.3' // sdk19, sdk21, sdk23 are also available
compile 'org.jetbrains.anko:anko-support-v4:0.8.3' // In case you need support-v4 bindings
compile 'org.jetbrains.anko:anko-appcompat-v7:0.8.3' // For appcompat-v7 bindings
}
然后sync一把。配置的问题解决。
写一个ListView热身
首先创建一个ListView的item点击之后跳转的activity。这里叫做TabDemo1
。
现在就创建这个listview,并在listview的item点击之后调转到相应的activity去。
这个listview非常简单,只在一个竖直的布局中放置,并且宽度和高度都是填满竖直
布局。
// 1
verticalLayout {
padding = dip(16)
// 2
val list = listView() {
// 3
adapter = ArrayAdapter<String>(this@MainActivity, android.R.layout.simple_list_item_1, items)
// 4
onItemClickListener = object : AdapterView.OnItemClickListener {
override fun onItemClick(parent: AdapterView<*>?, v: View?, position: Int, id: Long) {
when (position) {
0 -> {
// 5
startActivity<TabDemo1>()
}
}
}
}
}.lparams(width = matchParent) { // 6
height = matchParent
}
}
分别解释:
1. 竖直布局。本质是LinearLayout
,并且orientation
的值为vertical
。但是
水平方向的就没有vetialLayout这种可以直接使用的了,需要自己写明orientation。
2. 创建一个listview。
3. 给这个listview添加adapter。这里简单实用ArrayAdapter<String>
。
4. 添加OnItemClickListener
。object : AdapterView.OnItemClickListener
用来
创建实现某个接口的匿名类。
5. startActivity<TabDemo1>()
,是Anko的语法糖。startActivity(SourceActivity.this, DestActivity.class)
可以直接简化为startActivity<DestActivity>()
。简单了不少。
6. 在lparams
中设置layout params相关的内容。默认的都是wrap content。这个设置为
宽、高都为match parent。
用Fragment写一个Tab布局
热身结束。我们来开始真正的开发阶段。
下面要开发的是一个日记App。一共有三个tab,第一个是日记列表,第二个tab是写日记,第三个tab可以设置一些字体大小等(这里只用来占位,不做实现)。
每一个tab都用一个Fragment
来展示内容。这三个tab分别HomeListFragment
, DetailFragment
,DiarySettingsFragment
。这个三个fragment都在一个叫做TabDemo1
的托管Activity里。
现在就从这个托管activity:TabDemo1
开始。这里我们不使用默认的ActionBar
,而是用完全自定义的方式来写一个我们自己的action bar。所以需要把界面设定为全屏模式。设置全屏的模式的方法有很多,我们用设置style的方式来实现。
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
</style>
之后把这个style应用在activity在AndroidManifest.xml配置中。
这个时候这个托管activity的界面布局就是一个完全的白板了。这个白板现在要分为上中下三部分。上部为我们自定义的action bar,最下面的是tab bar,剩下的部分就是每个tab的内容的fragment。
我们来看一下这个布局应该怎么写:
// 1
relativeLayout {
id = ID_RELATIVELAYOUT
backgroundColor = Color.LTGRAY
// 2
linearLayout {
id = ID_TOP_BAR
backgroundColor = ContextCompat.getColor(ctx, R.color.colorPrimary)
orientation = LinearLayout.HORIZONTAL
titleTextView = textView {
text = "Some Title"
textSize = 16f
textColor = Color.WHITE
gravity = Gravity