美文网首页kotlin
Kotlin 结合 Anko 编写布局

Kotlin 结合 Anko 编写布局

作者: 高级复制工程师 | 来源:发表于2018-09-12 11:20 被阅读294次

    什么是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<SettingAnkoActivity> {
        override fun createView(ui: AnkoContext<SettingAnkoActivity>): 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<TextView>(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的代码,在通过一丢丢的修改,就可以了,非常简单。

    相关文章

      网友评论

      • plus彭于晏:这意思是靠编写代码来完成UI吗
        高级复制工程师:@lmy小明 是的,但是不会再解析XML文件了
        Alimin利民:@高级复制工程师 编译之后还是会变成普通代码的
        高级复制工程师:@墨辰lyb 可以这样理解,XML布局是在运行时解析的。也就是说XML需要从资源文件中获取,然后XmlPullParser需要解析所有的元素并一个一个的创建它们。还要解析元素的属性,然后设置。直接写在kotlin文件中可以使布局效率更高。

      本文标题:Kotlin 结合 Anko 编写布局

      本文链接:https://www.haomeiwen.com/subject/bxbygftx.html