Kotlin 结合 Anko 编写布局

什么是Anko?

Anko是由 Android Studio 的开发公司 jetBrains 官方出品的针对Kotlin语言,并且使开发Android程序更高效更简单的库,它可以使代码更简洁优雅。
它可以分为几个部分:

  • Anko Commons: 这个里面包括很多使用的工具,可以帮助我们减少代码量,包括intents ,dialog,log,还有好多....
  • Anko Layouts: 是一种快速,type-safe的动态 Android 布局方案
  • Anko SQLite: 帮助查询SQLite的DSL 解析器集合
  • Anko Coroutines:基于kotlin 协程的扩展工具

为什么要使用Anko来写布局呢?

在常规的Andorid开发中,我们都是用XML写布局,在这几个方面有点不方便:

  • 不是type-safe的;
  • 不是null-safe的;
  • 每个布局文件都要写好多重复的代码
  • 在Android设备上解析XML会更加耗时和耗电
  • 不能重用

而且当我们想用代码直接创建UI的时候,会使代码看起来很难维护,并且不够优雅。

val activity = this
val layout = LinearLayout(act)
layout.orientation = LinearLayout.VERTICAL
val button = Button(act)
button.text = "退出登录"
button.setOnClickListener {
    logout()
}
layout.addView(button)

上面是动态添加一个退出按钮的操作,已经是kotlin中简化的代码了,可以说是又丑可读性也差,如果用java写的话会更长。如果用Anko的DSL方式编写会是什么样呢?


verticalLayout {
    button("退出登录") {
        onClick { logout() }
    }
}

一个普通的设置界面

如果我们想要完成上面这样的界面,正常情况的XML是这样的:


image.png

首先是一个垂直的线性布局,里面一个自定义的Title,之后是五个 RelativeLayout, 最后是一个Button,那么如果利用Anko来进行编写是什么样的呢?

首先 创建一个实现 AnkoComponent接口的类(虽然可以直接在onCreate里面用DSL写,但是如果用这个 AnkoComponent,然后再安一个 Anko Support 的 插件 就有几率可以预览界面,但是经过实测,其实并不是那么好用 ,每次编辑完都要 build 一下才能预览 ,还不如直接在设备上调试。)

class SettingActivityUI(private val activity: BaseActivity) : AnkoComponent {
    override fun createView(ui: AnkoContext): View = with(ui) {
            verticalLayout {

                backgroundResource = R.color.bg_color

                commonTitle {
                    setLeftBackgroundResource(R.drawable.ic_return)
                    setTitle("设置")
                    setLeftClick { activity.finish() }
                }.lparams(width = matchParent, height = wrapContent)

                relativeLayout {
                    backgroundResource = R.color.white

                    textView {
                        id = ID_title
                        text = "个人设置"
                        textColorResource = R.color.c_333333
                        textSize = 15f
                        val leftDrawable = activity.resources.getDrawable(R.drawable.geren_icon)
                        leftDrawable.setBounds(0, 0, leftDrawable.minimumWidth, leftDrawable.minimumWidth)
                        setCompoundDrawables(leftDrawable, null, null, null)
                        compoundDrawablePadding = 16

                    }.lparams(wrapContent, wrapContent) {
                        centerVertically()
                        alignParentLeft()
                        setMargins(dip(16), 0, 0, 0)
                    }

                    imageView {
                        setImageResource(R.drawable.jiantou_you)
                    }.lparams(width = wrapContent, height = wrapContent) {
                        alignParentRight()
                        centerVertically()
                        setMargins(0, 0, dip(16), 0)
                    }

                }.lparams(matchParent, dip(50)).onClick {
                    find(ID_title).text = "点击了个人设置"
//                    mBundle?.putString("sex", sex)
//                    IntentUtils.startActivity(activity, UserSettingActivity::class.java, mBundle)
                }

                relativeLayout {
                    backgroundResource = R.color.white

                    textView {
                        text = "意见反馈"
                        textColorResource = R.color.c_333333
                        textSize = 15f
                        val leftDrawable = activity.resources.getDrawable(R.drawable.yijian_icon)
                        leftDrawable.setBounds(0, 0, leftDrawable.minimumWidth, leftDrawable.minimumWidth)
                        setCompoundDrawables(leftDrawable, null, null, null)
                        compoundDrawablePadding = 16

                    }.lparams(wrapContent, wrapContent) {
                        centerVertically()
                        alignParentLeft()
                        setMargins(dip(16), 0, 0, 0)
                    }

                    imageView {
                        setImageResource(R.drawable.jiantou_you)
                    }.lparams(width = wrapContent, height = wrapContent) {
                        alignParentRight()
                        centerVertically()
                        setMargins(0, 0, dip(16), 0)
                    }

                }.lparams(matchParent, dip(50)).onClick {
                    IntentUtils.startActivity(activity, FeedbackActivity::class.java)
                }

                relativeLayout {
                    backgroundResource = R.color.white

                    textView {
                        text = "帮助中心"
                        textColorResource = R.color.c_333333
                        textSize = 15f
                        val leftDrawable = activity.resources.getDrawable(R.drawable.help_icon)
                        leftDrawable.setBounds(0, 0, leftDrawable.minimumWidth, leftDrawable.minimumWidth)
                        setCompoundDrawables(leftDrawable, null, null, null)
                        compoundDrawablePadding = 16

                    }.lparams(wrapContent, wrapContent) {
                        centerVertically()
                        alignParentLeft()
                        setMargins(dip(16), 0, 0, 0)
                    }

                    imageView {
                        setImageResource(R.drawable.jiantou_you)
                    }.lparams(width = wrapContent, height = wrapContent) {
                        alignParentRight()
                        centerVertically()
                        setMargins(0, 0, dip(16), 0)
                    }

                }.lparams(matchParent, dip(50)).onClick {
                    IntentUtils.startActivity(activity, HelpActivity::class.java)
                }

                relativeLayout {
                    backgroundResource = R.color.white

                    textView {
                        text = "安全中心"
                        textColorResource = R.color.c_333333
                        textSize = 15f
                        val leftDrawable = activity.resources.getDrawable(R.drawable.anquan_icon)
                        leftDrawable.setBounds(0, 0, leftDrawable.minimumWidth, leftDrawable.minimumWidth)
                        setCompoundDrawables(leftDrawable, null, null, null)
                        compoundDrawablePadding = 16

                    }.lparams(wrapContent, wrapContent) {
                        centerVertically()
                        alignParentLeft()
                        setMargins(dip(16), 0, 0, 0)
                    }

                    imageView {
                        setImageResource(R.drawable.jiantou_you)
                    }.lparams(width = wrapContent, height = wrapContent) {
                        alignParentRight()
                        centerVertically()
                        setMargins(0, 0, dip(16), 0)
                    }

                }.lparams(matchParent, dip(50)).onClick {
                    IntentUtils.startActivityForResult(activity, SecurityCenterActivity::class.java, mBundle, 100)
                }

                relativeLayout {
                    backgroundResource = R.color.white

                    textView {
                        text = "当前版本"
                        textColorResource = R.color.c_333333
                        textSize = 15f
                        val leftDrawable = activity.resources.getDrawable(R.drawable.aboutme_icon)
                        leftDrawable.setBounds(0, 0, leftDrawable.minimumWidth, leftDrawable.minimumWidth)
                        setCompoundDrawables(leftDrawable, null, null, null)
                        compoundDrawablePadding = 16

                    }.lparams(wrapContent, wrapContent) {
                        centerVertically()
                        alignParentLeft()
                        setMargins(dip(16), 0, 0, 0)
                    }

                    textView {
                        text = "v.${BuildConfig.VERSION_NAME}"
                        textColor = Color.parseColor("#999999")
                        textSize = 14f
                    }.lparams(width = wrapContent, height = wrapContent) {
                        alignParentRight()
                        centerVertically()
                        setMargins(0, 0, dip(16), 0)
                    }

                }.lparams(matchParent, dip(50)) {
                    topMargin = dip(16)
                }.onClick {
                    toast("正在检测,请稍后")
                    VersionUpdateUtils
                            .newInstance()
                            .latestVersionIndex(activity, activity.supportFragmentManager, "1")

                }

                button {
                    backgroundResource = R.drawable.shape_btn_bg
                    text = "退出当前账号"
                    textColorResource = R.color.white
                }.lparams(dip(300), wrapContent) {
                    topMargin = dip(30)
                    gravity = Gravity.CENTER
                }.onClick {
                            activity.alert {
                                with(activity){
                                    mApp.spUtils.putString(Constants.CCUSERID, "")
                                    mApp.spUtils.putString(Constants.TOKEN, "")
                                    val intent = Intent(this, MainActivity::class.java)
                                    intent.putExtra("flag", "exit")
                                    intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
                                    startActivity(intent)
                                    finish()
                                }

                            }.show()
                        }
            }
        }
    }

}

上面的代码中有一个自定义的view:CommonTileView,这个在Anko中是没有支持的,所以要怎么才能把自己写好的View也支持Anko呢?
我们只需要在任何kt文件中写下扩展就好了:

inline fun ViewManager.commonTitle(): CommonTileView = commonTitle {}

inline fun ViewManager.commonTitle(init: (@AnkoViewDslMarker CommonTileView).() -> Unit): CommonTileView {
    return ankoView(
            { CommonTileView(it) },
            theme = 0,
            init = init
    )
}

然而~~! 如果你不想凭借自己的想象写Anko的布局,那么你可以在安装了 Anko Support 插件之后 ,通过转换编写完的XML文件 ,自动生成 Anko Layouts的代码 在XML界面 ,点击工具栏上面的 ‘Code’ --> 'Convert to Anko Layouts DSL' ,这样就可以转换大部分XML的代码,在通过一丢丢的修改,就可以了,非常简单。

你可能感兴趣的:(Kotlin 结合 Anko 编写布局)