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

原文地址: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.*。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值