热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

androidanko,AnkoforAndroid

Anko是一个使开发Android应用更简单更快捷的库,Anko使你的代码简洁易懂,使开发者不用再在意AndroidSDK对Java版本的限制(目前还不支持Java8。).Anko

Anko 是一个使开发Android应用更简单更快捷的库,Anko使你的代码简洁易懂, 使开发者不用再在意Android SDK对Java版本的限制(目前还不支持Java8 =。= ).

Anko版本的 hello world :

verticalLayout {

val name = editText()

button("Say Hello") {

onClick { toast("Hello, ${name.text}!") }

}

}

上面的代码创建了一个Button,放在 LinearLayout 内, 并为其设置了一个点击监听器OnClickListener .

oYYBAFYnZ7GAHENVAATT_iv8nqY107.gif

上面是一个DSL(Domain Specific Language),使用的是 Kotlin语言.

DSL,即 Domain Specific Language,领域相关语言。什么是 DSL,说白了它就是某个行业中的行话。

[TOC]

Why Anko?

为啥 DSL?

平时开发android, UI写在xml中,这就导致了下面的几个问题 :

It is not typesafe

It is not null-safe

It forces you to write almost the same code for every layout you make

XML is parsed on the device wasting CPU time and battery 渲染xml为对象过程耗时耗电

Most of all, it allows no code reuse. 大部分不能重用

但是全部只在代码中写UI,这很难,不仅代码丑,而且冗余难维护,下面是 Ktolin版本的(Java甚至更长):

val act = this

val layout = LinearLayout(act)

layout.setOrientation(LinearLayout.VERTICAL)

val name = EditText(act)

val button = Button(act)

button.setText("Say Hello")

button.setOnClickListener {

Toast.makeText(act, "Hello, ${name.getText()}!", Toast.LENGTH_SHORT).show()

}

layout.addView(name)

layout.addView(button)

DSL 就不一样类,相同的逻辑,但简洁易懂, 易于编写而且没有运行开销(runtime overhead)看下面的代码:

verticalLayout {

val name = editText()

button("Say Hello") {

onClick { toast("Hello, ${name.text}!") }

}

}

为啥不用 Scaloid?

Scaloid 是一个类似与 Scala 的库, 有很多非常酷的特性可供 Scala 开发者使用. Anko主要是针对 Java 和 Kotlin developers.

兼容已有的代码

不需要用Anko重写所有的UI, 你可以保留原有的Java代码. 此外, 如果你想写一个 Kotlin的activity类并且由于某些需求需要使用 inflate来渲染xml, 你完全可以按照原来的写法:

// Same as findViewById(), simpler to use

val name = find(R.id.name)

name.hint = "Enter your name"

name.onClick { /*do something*/ }

工作原理

There is no :tophat:. Anko 由一些 Kotlin的 扩展函数和属性,被设置成类型安全(type-safe builders)的, under Type Safe Builders.

他们繁琐的手工编写所有这些扩展, 使用Android SDK的源码中的 android.jar 文件自动生成

可扩展吗?

答案是: yes.

例如. 你可能想使用 MapView 在DSL中.你可以编写下面的代码(kotlin文件中),然后就可已到处使用了

public inline fun ViewManager.mapView() = mapView {}

public inline fun ViewManager.mapView(init: MapView.() -> Unit): MapView {

return ankoView({ MapView(it) }, init)

}

{ MapView(it) } 是你自定义View的一个工厂方法View. 接受一个 Context .

frameLayout {

val mapView = mapView().lparams(width = matchParent)

}

如果你想创建一个 顶级的 DSL,看这里Extending Anko.

使用 Gradle

这里有个例子 template project 展示类如果在Android中Gradle配置.

基本上,你只需要配置 repository 和一个 compile dependency:

dependencies {

compile 'org.jetbrains.anko:anko-sdk15:0.7.1' // sdk19, sdk21, sdk23 are also available

compile 'org.jetbrains.anko:anko-support-v4:0.7.1' // In case you need support.v4 bindings

}

当作 Jar library使用

加入你的项目不是基于Gradl, 不需要配置 Maven. 只要添加这里 的jar包即可.

编译 Anko

理解 Anko

Anko 是使用 Kotlin语言编写的.

如果不熟悉Kotlin看 kotlinlang.org.

Kotlin与Java很类似,所以很容易学.

基础

Anko中, 你不需要继承其他奇怪的类,只要标准的Activity, Fragment, FragmentActivity 或者其他任意的类

首先, 在使用Anko的DSL的类中导入 org.jetbrains.anko.* .

DSL 可以在 onCreate()中使用:

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

verticalLayout {

padding = dip(30)

editText {

hint = "Name"

textSize = 24f

}

editText {

hint = "Password"

textSize = 24f

}

button("Login") {

textSize = 26f

}

}

}

不需要显示的调用 setContentView(R.layout.something), Anko 自动为Activity(只会对Activity)进行 set content view

padding, hint 和 textSize 是 扩展属性. 大多数 View 具有这些属性,允许使用text = "Some text" 代替 setText("Some text").

verticalLayout (一个竖直方向的 LinearLayout), editText 和 button are

扩展函数. 这些函数存在与ANdroid 框架中的大部View中, Activities, Fragments ( android.support 包中的) 甚至 Context同样适用.

如果有一个 Context 实例, 可以写出下面的DSL结构:

val name = with(myContext) {

editText {

hint = "Name"

}

}

变量 name 成为了 EditText类型.

Helper 方法

你可能注意到了,前面章节中 button 方法接了一个字符串参数,这样的Helper方法同样使用与 TextView, EditText, Button , ImageView.

如果你不需要 View 其他的属性,你可以省略 {} 直接写 button("Ok") 或只有 button():

verticalLayout {

button("Ok")

button("Cancel")

}

Layouts 和 LayoutParams

在父布局中布局控件可能需要使用 LayoutParams. xml中长这样:

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android_layout_marginLeft="5dip"

android_layout_marginTop="10dip"

android:src="@drawable/something" />

Anko中, 在View的后面使用 lparams来实现类似与xml的 LayoutParams。

linearLayout {

button("Login") {

textSize = 26f

}.lparams(width = wrapContent) {

horizontalMargin = dip(5)

topMargin = dip(10)

}

}

如果指定了 lparams,但是没有指定 width 或者 height, 默认是 WRAP_CONTENT.但是你可以自己通过使用named arguments指定.

注意下面一些方便的属性:

horizontalMargin 同时设置 left 和 right margins,

verticalMargin 同时设置 top 和 bottom

margin 同时设置4个方向的 margins.

注意 lparams 的使用在不同的布局中是不同的, 例如在 RelativeLayout中:

val ID_OK = 1

relativeLayout {

button("Ok") {

id = ID_OK

}.lparams { alignParentTop() }

button("Cancel").lparams { below(ID_OK) }

}

Listeners

设置listeners:

button("Login") {

onClick {

login(name, password)

}

}

下面的效果一样:

button.setOnClickListener(object : OnClickListener {

override fun onClick(v: View) {

login(name, password)

}

})

当一个Listener有多个方法时,Anko就显得很方便类. 看下面的代码(没有使用Anko):

seekBar.setOnSeekBarChangeListener(object: OnSeekBarChangeListener {

override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {

// Something

}

override fun onStartTrackingTouch(seekBar: SeekBar?) {

// Just an empty method

}

override fun onStopTrackingTouch(seekBar: SeekBar) {

// Another empty method

}

})

使用了Anko:

seekBar {

onSeekBarChangeListener {

onProgressChanged { seekBar, progress, fromUser ->

// Something

}

}

}

如果你同时设置了onProgressChanged 和 onStartTrackingTouch , 两个方法将被合并. 对于多个相同的方法,最后的一个有效.

Resources, Colors 和 Dimensions

Using resource identifiers

前面的所有例子直接使用的 Java的字符串,但是大多数时候字符串都是放在 res/values/ 目录下,并且是运行时调用的,例如 getString(R.string.login).

幸运的是,Anko中可以使用以下两个 helper方法 (button(R.string.login)) 和 (button { textResource = R.string.login }).

注意,这些属性不是 text, hint, image, 而是 textResource, hintResource and imageResource.

Resource properties always throw AnkoException when read.

Colors

两个简单的扩展函数使代码更加易懂。

Function

Result

0xff0000.opaque

non-transparent red

0x99.gray.opaque

non-transparent #999999 gray

Dimensions

你可以指定 dimension 的 dip (density-independent pixels) 或 sp (scale-independent pixels)值: dip(dipValue) 或 sp(spValue). 注意 textSize属性默认接受sp (textSize = 16f). 使用 px2dip 和 px2sp 相互转换.

Instance shorthands

在Activity中,有时你需要传一个 Context实例给一个 Android SDK中的方法,通常你会写 this, 如果在内部类呢?你可能写SomeActivity.this ,如果你使用 Kotlin,你只需写 this@SomeActivity ,

使用 Anko,你可以只写 ctx. ctx是Activity 和 Service 或者 Fragment (使用的 getActivity() )内部的一个属性. 你也可以使用act扩展属性获取 Activity实例.

UI wrapper

开始使用Anko 之前,将 UI tag 作为 DSL 顶级元素:

UI {

editText {

hint = "Name"

}

}

这将更易于扩展 DSL ,因为你必须声明一个函数 ViewManager.customView.

看这里 Extending Anko 获取更多信息.

Include tag

使用 include tag 很容易向 DSL 插入 一个 XML layout :

include(R.layout.something) {

backgroundColor = Color.RED

}.lparams(width = matchParent) { margin = dip(12) }

通常可以使用 lparams , 如果类型不是 View,仍然可以用 {}:

include(R.layout.textfield) {

text = "Hello, world!"

}

Styles

Anko 支持 styling: style 是一个简单的函数,接受一个View, 效果作用于这个 View , 并且当这个View 是一个ViewGroup 时,可以可以递归的作用与 这个View的 child View:

verticalLayout {

editText {

hint = "Name"

}

editText {

hint = "Password"

}

}.style { view -> when(view) {

is EditText -> view.textSize = 20f

}}

oYYBAFYnaXGAU36mAAA-AHHYR0Y038.png



推荐阅读
  • 协程作为一种并发设计模式,能有效简化Android平台上的异步代码处理。自Kotlin 1.3版本引入协程以来,这一特性基于其他语言的成熟理念,为开发者提供了新的工具,以增强应用的响应性和效率。 ... [详细]
  • 本文探讨了一种统一的语义数据模型,旨在支持物联网、建筑及企业环境下的数据转换。该模型强调简洁性和可扩展性,以促进不同行业间的插件化和互操作性。对于智能硬件开发者而言,这一模型提供了重要的参考价值。 ... [详细]
  • RTThread线程间通信
    线程中通信在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的值,另一个功能对此全局变量进行读取& ... [详细]
  • CentOS7通过RealVNC实现多人使用服务器桌面
    背景:公司研发团队通过VNC登录到CentOS服务器的桌面实现软件开发工作为防止数据外泄,需要在RealVNC设置禁止传输文件、访问粘贴板等策略过程&# ... [详细]
  • 深入解析RelativeLayout、LinearLayout与FrameLayout的性能差异
    本文详细分析了FrameLayout和LinearLayout的性能对比,通过具体的测量数据和源码解析,探讨了不同布局在不同场景下的性能表现。 ... [详细]
  • 英特尔推出第三代至强可扩展处理器及傲腾持久内存,AI性能显著提升
    英特尔在数据创新峰会上发布了第三代至强可扩展处理器和第二代傲腾持久内存,全面增强AI能力和系统性能。 ... [详细]
  • 本文介绍了如何使用 Gesture Detector 和 overridePendingTransition 方法来实现滑动界面和过渡动画。 ... [详细]
  • 作为一名Android应用开发新手,我在尝试将MediaPlayer处理逻辑从MainActivity分离到另一个类时遇到了问题。尽管搜索了很长时间,但仍未找到满意的解决方案。 ... [详细]
  • Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ... [详细]
  • GLiHT数据介绍
    GLiHT数据介绍 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文详细介绍了Java中HashSet的工作原理及其源码分析。HashSet实现了Set接口,内部通过HashMap来存储数据,不保证元素的迭代顺序,且允许null值的存在。文章不仅涵盖了HashSet的基本概念,还深入探讨了其内部实现细节。 ... [详细]
  • 本文探讨了在UIScrollView上嵌入Webview时遇到的一个常见问题:点击图片放大并返回后,Webview无法立即滑动。我们将分析问题原因,并提供有效的解决方案。 ... [详细]
  • 本文详细介绍了如何在Android应用中实现重复报警功能。示例代码可在以下路径找到:https://developer.android.com/samples/RepeatingAlarm/index.html。首先,我们将从Manifest文件开始分析。 ... [详细]
  • 本文介绍了读写锁(RWMutex)的基本概念、实现原理及其在Go语言中的应用。读写锁允许多个读操作并发执行,但在写操作时确保互斥,从而提高并发性能。 ... [详细]
author-avatar
韩庚plus
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有