翻开自己的CSDN,已经很久很久没有活动了,最近的关于PDF签章的博客还是16年写的。将近年关,工作内容阶段性告一段落,终于有时间写一下自己的东西。
废话少说,说说Kotlin。kotlin开发者给kotlin的定位---不是用来取代任何一种语言,而是 让开发者有更多的选择,更加便捷的开发自己的产品。kotlin不是学院派语言,而是工程性质的语言,kotlin并没有带给开发者更多的新奇的技术,而是把工程实践中,开发者觉得很便捷的技术特性 集成到kotlin中。
最初没有真正在项目中用到kotlin之前,我同大部分人的看法是一致的,以为kotlin无非是java的升级,语法糖而已。后来,抱着学习语言特性的想法,学习了kotlin,并用到自己项目中之后,才发现kotlin的真正牛掰之处。基于kotlin与java的无缝互操作,到目前为止,我已经很少写java代码了。
下边,开始kotlin + DSL(Anko),给大家开发时一个新思路
给大家介绍一下kotlin + anko的强大之处,文章比较长,希望对各位开发同学有所帮助
有所谓 仁者见仁智者见智,kotlin + anko还处于成长中,不一定适合所有开发环境。
我的建议是,可以在项目中 将xml和anko结合起来。 xml和anko各有优势,并且anko可以用include包含xml,anko的优势是 动态生成和复用。 二者结合,相信可以更加便捷的开发。
本文所用的源码demo,在码云上开源,地址如下
https://gitee.com/akai_liu/AkaiKotlinWithAnko
推荐几个地址,本文不说kotlin语法基础和如何构建项目,需要这方面的可以参考如下
kotlin极简教程
kotlin官方文档中文版
《Kotlin for android developers》中文版翻译
anko github
kotlin协程github
各位看到这里,估计心里会有嘀咕,这不是和写xml布局文件一样么,看不出来有什么差别。甚至连预览都那么麻烦。OK,这只是表面现象,下边,我们开始一步一步的揭示,anko的强大。
根据大家的经验,xml文件中只能写静态页面,如果有动态需求,就需要用java类动态生成,且不说java类写界面有多繁琐,单是与xml的交互,就没那么容易。
但是,这些事情,对于kotlin/Anko来说,易如反掌,天生支持。
上文说过,虽然anko写UI看起来类似xml中使用view标签,但是anko中其实每个‘标签’本质都是一个扩展函数,因此,在函数中写代码,绑定事件,动态生成布局,这是再正常不过的事情了,特别是anko为开发者封装了很多方便的工具。
基于上述的hello world项目,我们先来个简单的修改,给hello world绑定一个点击事件,土司一句话。如下截图
是不是很简单,这时,运行到模拟器上,textView就会有onclick事件了,弹出一个提示“我是hello world”。
同样,可以在textView 之后 直接用常规的 .setOnClicklistioner调用,不过,那样不么是显得啰嗦么。
onClick函数和 toast函数是 anko封装的扩展函数,就是为了减少开发时不必要的样板代码。
有了这个操作, 对于只执行简单操作的按钮 等控件view,点击事件 就可以顺手写在ui里。 比如只是为了跳转页面,直接在onclick中写 startActivity就好了,省去了定义id findview等很多麻烦。
看了上边的介绍,大家一定有这样的疑问,我们总不能把所有的代码都写到 UI类中吧,那样太傻了。
OK,下边就看看我们怎样在activity中操作view。
先在activity中定义view,然后在AnkoComponent中实例化view,最后,activity中就可以使用view了。
上文说过,AnkoComponent重写的函数createView 的入参ui ,包含了绑定的activity/fragment的实例,基于此,我们可以如下实现
类似如下过程,
为了不进行多余的 kotlin空指针处理,这里把textView定义为懒初始化属性。
然后在AnkoComponent中实例化,最后,就可以在 绑定ui之后 使用textView了。
这样,是不是省去了大量findView操作呢?
当然,我们同样可以 在UI中指定View的Id属性,在activity中使用findView的方式来实例化。然而,我们多数时候不会这样做,因为findViewbyId是比较消耗的操作,可以直接代码实例化的话,还是尽量不用findView。
配置View的id,不一定是为了findview才配置的。还有一个作用是在activity中区分不同的view,比如在activity中统一处理点击事件。
anko为我们封装好了 android原生包括support库design库用到的所有控件,能够完成我们大部分的工作。但是,很多时候我们需要自定义控件,那么,我们怎么在anko中使用自定义控件呢?
上文,有介绍framelayout源码的定义,其实,我们按照源码,就可以定义自己的anko控件了。
比如,我从网上找了一个 圆形imageview的自定义控件RoundImageView(java也好,kotlin也好,都不影响,因为kotlin与java无缝互操作),代码太长我就不贴了,可以到项目中查看。
那么,我需要怎样配置,才能在anko中使用呢?
为了方便,我单独为自定义view建一个配置用的kotlin file,叫ConfigMyView, 并仿照anko源码,定义RoundImageView的内联函数,如下截图,由于我是在AnkoComponent中使用这个函数,所以我只声明了ViewManager的扩展函数。
OK,有了这个定义后,我们就可以使用roundImageView标签了。我们稍微修改一下hello world项目,把自定义的view加进入,把原来hello world删除掉,把跟布局改为relativeLayout。先从网上下载一张png图片
然后,放到roundImageView里,看看是什么效果
好了,这样,自定义view也可以用了。
至此,我们基本可以正常使用akno进行开发了,但是,各位看官,是不是依旧没有看出anko的优势在哪里?别急,如下,就是见证奇迹的时刻。
根据经验,很多时候,同一个项目中,同一个布局样式会在很多处都出现,为了使用方便,我们会单独为这些布局写一个xml文件,然后在不同的地方使用include 的方式引用。 anko同样支持include操作引用xml文件,来实现xml与anko的交互。
但是,anko能做的不仅仅是这样。
我们来设定一个需求,做一个类似如下形式的输入框。 输入框背景可自定义,输入框头部图标可自定义,输入框提示文字可自定义,输入框会判断输入内容正确性,正确显示对号,错误显示红叉,输入时 显示灰色叉子,点击灰色叉子可以删除输入框内容。
然后,在项目中,这种类型的输入框,有好多个,那么怎么办?
我们想想这个要怎么实现,如果使用传统的xml方式, 我们可以单独写一个输入框布局,然后在每次include后,在activity中一个一个findview,然后设置对应控件的属性,例如头部图标图片,对号叉子图片,输入框提示内容,并且要指定输入框各个事件,让对号红叉可以正常显示 等等等。
上述过程,光想想都够酸爽,如果 项目中多处用到,呵呵。。。
当然,如果您是大拿,说直接自定义view实现,那我拜服。
ok,来看看使用kotlin anko可以怎样实现?
然后再下载3个图标 对号 ,红叉子,灰色叉子 作为 输入框尾部的图标
下边,我们根据需求,分析对应的输入框布局。
最外层linearlayout水平布局,头部放一个imageview,中间放个edittext,尾部 framelayout 中放3个imageview,OK,其实布局结构很简单,我们在MyInputEdit中添加一个函数getInputEdit(),用来生成这样的布局,入参viewManager。
接下来,就是分析事件绑定了,我们简单的实现一下。
1、edittext失去焦点时,判断 输入正确 错误,如果没有输入,则什么都不显示
2、在文本编辑时,显示 灰色叉子,一键清空输入内容
因此,edit需要绑定 onFocusChangeListener 和 textChangedListener
尾部删除imageView需要绑定点击事件
为了方便控制 尾部3个imageview的显示,我们增加一个函数来控制showInputCheckIcon
ok,让我们先来看 edit的onFocusChangeListener中的逻辑
再看看textChangeedListener中的逻辑
删除按钮的点击事件很简单,点击后 清空 edittext就行了
ok,完整的 函数代码,可以到 项目中查看,太长,就不贴了
除此之外,我们再增加一个获取输入内容的函数,方便后续使用
OK,至此,MyInputEdit类基本完成,整体如下
ok,我们再来一个 密码输入框,同样的方式,但因为是密码,我们需要多传一个参数,输入类型
运行后,如下效果
基于此,一般连同 注册页面, 登陆页面, 忘记密码页面,修改密码页面,我们可能需要很多个类似的输入框,使用kotlin anko,可以轻松的把实现 复杂的 输入框需求,并且不需要自定义view。
看到这里,您是不是开始有些明白anko的强大之处了呢?
我们来看看另外一种,实现布局复用的方式-----直接定义布局函数
第6节中,因为 子布局有很多事件需要处理,所以,我们直接建一个类来方便事件绑定
然而,对于一般没有很多事件处理的 复用布局,我们可以直接定义函数来进行复用。
比如这样的需求,我们项目中可能有 很多类似如下的 动作条 ,有时带有头部图标,优势带有尾部图标
并且有的还可以显示用户内容,用户内容可能是图片或者文字,文字有可能要经过特殊处理(如截图中手机号不完全显示),动作条本身又有点击事件。
基于此,我们定义一个类似如下的内联函数, 入参根据需求,暂时定如下这几个