kotlin的伴生库-anko迭代了已经多个版本了,但是目前网上的资源主要集中在官方说明的机械翻译或者旧博客的复制/粘贴上。
本文带大家全方位的熟悉anko库的使用。anko库目前主要有四个核心库
anko-commons库,一些通用功能,集成方式:
dependencies { //anko_version脚本配置,下同,本文中,该值为0.10.0 compile "org.jetbrains.anko:anko-commons:$anko_version"}
anko-layout库,牛逼的dsl(领域特定语言)功能,布局的另一种代码方式,相对比较简洁,xml的简易替代。集成方式:
dependencies { // Anko Layouts compile "org.jetbrains.anko:anko-sdk25:$anko_version" // sdk15, sdk19, sdk21, sdk23 are also available compile "org.jetbrains.anko:anko-appcompat-v7:$anko_version" // 主要为兼容一些控件事件的协程,不过协程coroutines目前还不是kotlin的正式内容 compile "org.jetbrains.anko:anko-sdk25-coroutines:$anko_version" compile "org.jetbrains.anko:anko-appcompat-v7-coroutines:$anko_version"}
anko-coroutines库,集成方式:
dependencies { compile "org.jetbrains.anko:anko-coroutines:$anko_version"}
anko-sqlite库,见名知义,简化sqlite使用的库,集成方式:
dependencies { compile "org.jetbrains.anko:anko-sqlite:$anko_version"}
本篇主要介绍commons库和layout库的使用
这里先附上demo工程链接
跳转activity并传递参数,这些参数是作为extra属性传递过去的,%Context/Fragment类扩展函数%
//启动startActivity<IntentActivity>("name" to "小明", "age" to 12)//IntentActivity接收参数var name = intent.extras.getString("name")var age = intent.extras.getInt("age")//若有其它设置,则&intentFor方法&构建intentstartActivity(intentFor<IntentActivity>("name" to "小红", "age" to 13).singleTop())
快捷 浏览器,发短信,分享,发邮件操作,%Context/Fragment类扩展函数%
browse("http://m.baidu.com")
增强log输出,目前发现的最大好处是支持list和map,整数,空,自定义数据类等类型的打印。缺点是1-名称略长,tag设置不太灵活,不过tag设置也无所谓,毕竟log查看/过滤完全可以不用tag。2-使用略麻烦,要么实现AnkoLogger 类,要么拿到AnkoLogger(this)变量,然后调用方法,不过完全可以写个方法封装,全局共用,具体demo有。
verbose("tag-默认为调用类")//貌似不会打印,原因暂时未知debug(110)//貌似不会打印,原因暂时未知 warn(null)info(listOf<String>("today", "is", "a", "fine", "day"))error(HashMap<String, String>().apply { put("小明", "12") put("小红", "13") }) warn(CData("data", 100))...
这里可结合一种优雅打log的方式,定制一份很强大的log方式,记得模板要声明kotlin的applicable,比如
error("$method$($file$:$line$)\r\n -"+$text1$)
Dimensions类,重要的方法主要是单位换算,%Context/Fragment/View类扩展函数%
dip(100)//dp->pxpx2dip(100)//px->dp
Helper类,重要的方法主要有三个,挺实用的
//实用的attempt函数,{}若正常执行,则value返回{}的返回值,//若{}执行有异常,并不会闪退,只是会设置个error属性。很好的try..catch替代方案attempt { 3 }.value//结果3attempt { 1 / 0 }.error//还有sdk版本相关的doFromSdk(21) { info("从api 21开始打印") } doIfSdk(21) { //获得版本名也简单的多 packageManager.getPackageInfo(packageName, 0).versionName info("只有api 21才打印") }
对话框的优雅弹出,%Context/Fragment类扩展函数%
alert("this is the msg") { customTitle { verticalLayout {//用到了anko-layout库 imageView(R.mipmap.ic_launcher)//方便的设置内容 editText { hint = "hint_title" } } } okButton { toast("button-ok") } cancelButton { toast("button-cancel") } }.show()
列表selector的优雅实现,%Context/Fragment类扩展函数%
val countries = listOf("Russia", "USA", "England", "Australia") selector("Where are you from?", countries) { ds, i -> toast("So you're living in ${countries[i]}, right?") }
–其它的一些常用属性,代码能简洁不少,%Context/Fragment类扩展函数,有的是AnkoContext的类扩展属性%
displayMetrics,defaultSharedPreferences,act assets,ctx,contentView,resources//基本见名知义吧,不介绍了bundleOf("name" to "test")//just show bundle,return Bundle对象toast(".."'),progressDialog()..//使用很简单
以上,commons库的使用介绍完毕,应该是比较全了。
下面介绍layout库,网上有关这个的库的介绍比较多,主要是dsl比较cool比较潮吧,不过目前这个对简答的布局比较适用,复杂的还真不好说。权当语法糖熟悉下。这里尽量只列代码和使用,还有一些网上少见的用法。
先上个常规的用法,需要注意的点是find(BTN_ID),可以在dsl外部获得指定view
verticalLayout { padding = dip(30) editText { hint = "Name" textSize = 24f } editText { hint = "Password" textSize = 24f } button("Login") { textSize = 26f id = BTN_ID } }//note //id findviewfind<Button>(BTN_ID).setOnClickListener { toast("this is login button") }
布局不该放到activity中吧,否则那样太乱了,所以第二种方案来了:
//声明一个类继承AnkoComponent,对应泛型类到一个LayShowActivity,然后布局class LayoutActyUI : AnkoComponent<LayShowActivity> { val ET_ID = 0x1001 override fun createView(ui: AnkoContext<LayShowActivity>) = with(ui) { verticalLayout { val name = editText("LayoutActyUI") { id = ET_ID } button("Say Hello") { onClick { ctx.toast("Hello, ${name.text}!") name.textColor = 0xffff0000.toInt() } } } } }//然后在LayShowActivity调用下面的方法即可实现加载布局LayoutActyUI().setContentView(this)
引入布局参数和一些多函数控件事件监听器的简洁使用,具体解释见注释
verticalLayout { button("seekbar") { textSize = 26f }.lparams(width = wrapContent) {//布局参数 horizontalMargin = dip(15) topMargin = dip(20) } editText { hintResource = R.string.app_name//直接引用资源文件内容的方式 textChangedListener {多函数事件简单写法 onTextChanged { str, start, before, count -> ai(str) } } } }
这里补充下函数控件事件监听器,比如:
//原java方式用法,必须传入TextWatcher对象作为参数,而且有些函数根本用不上,比较麻烦。EditText(act).addTextChangedListener(object :TextWatcher{ override fun afterTextChanged(s: Editable?) { } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { } })//现在只需利用anko库的这个写法,使代码大大减少且清晰 EditText(act).textChangedListener { onTextChanged { str, start, before, count -> ai(str)//log..info } } onClick{},onCheckedChange{},onDateChange{} onDrawerOpen{},onItemClick{},onScrollChange{}等等都有类似用法