用Kotlin和Anko实现安卓UI(一)

来源:互联网 发布:淘宝客公司怎么样 编辑:程序博客网 时间:2024/06/02 06:03

原文地址:Building a UI with Kotlin and Anko
原文作者: Ankul Jain
译文出自:安卓巴士
译者:MrlLee-2

  开始做安卓UI开发一直是使用XML文件来实现。虽然理论上,UI可以使用Java语言来实现,但并没有太多的用处。不久前,JetBrains推出了Kotlin,一种面向JVM的现代语言,可以很好的实现安卓UI。  Jetbrains宣称Anko是Android中更快,更轻松的开发风格。Kotlin提供Anko库来作为DSL(领域专用语言)去设计安卓界面,一个简单的例子: 下面的界面由一个图片和一个按钮组成:    使用Anko实现如下:

[Java] 查看源文件 复制代码
verticalLayout{

   imageView(R.drawable.anko_logo).            lparams(width= matchParent) {                padding = dip(20)                margin = dip(15)    }    button("Tap to Like") {            onClick { toast("Thanks for the love!") }    }}  我们定义了一个垂直的线性布局作为容器包含图片和按钮,使用lparams定义了布局的位置信息,由Kotlin的内联函数也实现了按钮的点击事件。使用Anko的优点:

我们可以将UI布局嵌入到代码中,从而使其类型安全。
由于我们不用XML编写,所以它增加了效率,因为在分析XML浪费CPU时间。
在UI的程序化转换之后,我们可以将Anko DSL片段放入一个函数中。这样便于代码重用。
显然,代码更简洁,可读和可掌握性更高。
现在我们使用Anko Layout和Kotlin构建一个to-do app,来列出我们今天需要做的事。
你可以在GitHub上找到这个项目 to-do app
将Anko库添加到Android Studio:
在streamline-android-java-code-with-kotlin去学习如何添加Kotlin到你的安卓项目中,有了Kotlin,我们需要添加Anko依赖在app/build.gradle中,这样我们就可以顺利编译项目了。
[Java] 查看源文件 复制代码
compile [size=1em]’org.jetbrains.anko:anko-sdk15:0.8.3’

// sdk19,21,23 也可以使用

   可以根据你项目的minSdkVersion来添加这个依赖,上面的例子说明15<=minSdkVersion<19,你可以在Anko的GitHub库中找到自己需要的其他Anko依赖库。  我们准备使用下买按的依赖库:

[Java] 查看源文件 复制代码

compile ‘org.jetbrains.anko:anko-design:0.8.3’

compile ‘org.jetbrains.anko:anko-appcompat-v7:0.8.3’

在Activity中调用Anko布局: 我们不再使用XML来写布局文件,所以我们不需要XML View,所以也不需要findViewById()方法了。这里我们假设我们的Anko布局类为MainUI,然后我们可以开始写我们的activit内容:

[Java] 查看源文件 复制代码

var ui =MainUI() //MainUI类代替了XML布局

ui.setContentView(this) //this代表Activity类

现在我们创建一个Kotlin文件MainActivity.kt,写上如下代码:
[Java] 查看源文件 复制代码
import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import org.jetbrains.anko.*;

import java.util.*

class MainActivity : AppCompatActivity() {

   val task_list = ArrayList<String>()         //任务清单表   override fun onCreate(savedInstanceState: Bundle?) {      super.onCreate(savedInstanceState)      savedInstanceState?.let {          val arrayList = savedInstanceState.get("ToDoList")          task_list.addAll(arrayList as List<String>)      }      var adapter=TodoAdapter(task_list)      //定义适配器      var ui = MainUI(adapter)                //定义将要使用的Anko UI 布局      ui.setContentView(this)                 //给Activity设置Anko布局  }  override fun onSaveInstanceState(outState: Bundle?) {      outState?.putStringArrayList("ToDoList", task_list)      super.onSaveInstanceState(outState)    }}  task_list是ArrayList,将填充ListView的TodoAdapter。MainUI(adapter)是我们的Anko UI文件,它采用TodoAdapter类作为适配器参数。所以,接下来我们再创建一个TodoAdapter类。 用于ListView的TodoAdapter适配器  TodoAdapter类有一个ArrayList<String>类型的list,并且继承了BaseAdapter。所以我们需要重写一下四个方法:

[Java] 查看源文件 复制代码

     public int getCount()     public Object getItem(int i)     public long getItemId(int i)     public View getView(int i, View view, ViewGroup viewGroup)    在getView()方法中我们需要使用Anko设计一个表元素的布局。

[Java] 查看源文件 复制代码
override fun getView(i : Int, v : View?, parent : ViewGroup?) : View {

          return with(parent!!.context) {          //任务数从1开始          var taskNum: Int = i +1         //清单表元素布局         linearLayout {               lparams(width = matchParent, height = wrapContent)               padding = dip(10)               orientation = HORIZONTAL               //任务号              textView {                   id = R.id.taskNum                   text=""+taskNum                   textSize = 16f                   typeface = Typeface.MONOSPACE                   padding =dip(5)              }              //任务名              textView {                    id = R.id.taskName                   text=list.get(i)                   textSize = 16f                   typeface = DEFAULT_BOLD                   padding =dip(5)              }         }     }  }

在这个方法中,我们返回一个包含一个horizontalListView布局列表项的视图。这是使用Kotlin的with语法完成的,它允许我们一次在对象实例上调用很多方法。
每个列表项包含两个textview用于显示任务号和任务名称。
linearLayout,textView是扩展功能。扩展功能使我们有能力启用具有新功能的任何类。
text,textSize,typeface在android.widget.TextView有getter和setter方法,padding是Anko添加的属性。
继续下一步,我们需要定义列表的操作功能。因此,我们需要在TodoAdapter中定义add(String)和delete(Int)方法。add(String)将任务名称作为参数添加到任务中。delete(Int)将任务所在的位置作为参数来删除任务。下面是具体的实现:
[Java] 查看源文件 复制代码

   //将任务添加到任务清单的方法       fun add(text: String) {                 list.add(list.size, text)                 notifyDataSetChanged()          //更新数据     }        //将任务从任务清单中移除的方法       fun delete(i:Int) {                list.removeAt(i)                 notifyDataSetChanged()          //更新数据       }

所以,现在我们设计了列表,我们也可以添加和删除项目到我们的列表中。接下来完成此适配器类的代码。
[Java] 查看源文件 复制代码

   import android.graphics.Typeface   import android.graphics.Typeface.DEFAULT_BOLD   import android.view.View   import android.view.ViewGroup   import android.widget.BaseAdapter   import android.widget.LinearLayout.HORIZONTAL   import org.jetbrains.anko.*   import java.util.*class     TodoAdapter(val list: ArrayList<String> = ArrayList<String>()) : BaseAdapter() {                     override fun getView(i : Int, v : View?, parent : ViewGroup?) : View {                                   return with(parent!!.context) {                                                 //taskNum will serve as the S.No. of the list starting from 1                                                 var taskNum: Int = i +1                                                 //Layout for a list view item                                                 linearLayout {                                                            id = R.id.listItemContainer                                                            lparams(width = matchParent, height = wrapContent)                                                            padding = dip(10)                                                            orientation = HORIZONTAL                                                               textView {                                                                         id = R.id.taskNum                                                                        text=""+taskNum                                                                        textSize = 16f                                                                       typeface = Typeface.MONOSPACE                                                                     padding =dip(5)                                                              }                                                            textView {                                                                       id = R.id.taskName                                                                       text=list.get(i)                                                                       textSize = 16f                                                                        typeface = DEFAULT_BOLD                                                                       padding =dip(5)                                                            }                                                 }                                          }                                }                override fun getItem(position : Int) : String {                                return list[position                  }                 override fun getCount() : Int {                               return list.size                 }                 override fun getItemId(position : Int) : Long {                               //can be used to return the item's ID column of table                               eturn 0L                  }                 //function to add an item to the list                 fun add(text: String) {                                  list.add(list.size, text)                             notifyDataSetChanged()                }                //function to delete an item from list               fun delete(i:Int) {                             list.removeAt(i)                             notifyDataSetChanged()               }  }  注意,使用Anko DSL类中必须要导入org.jetbrains.anko.*。