热门标签 | 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 Studio项目中集成JNI(Java Native Interface),包括下载必要的NDK和构建工具,配置CMakeLists.txt文件,以及编写和调用JNI函数的具体步骤。 ... [详细]
  • 我有一个SpringRestController,它处理API调用的版本1。继承在SpringRestControllerpackagerest.v1;RestCon ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • 本文详细介绍了如何在 Android 开发中高效地管理和使用资源,包括本地资源和系统资源的访问方法。通过实例和代码片段,帮助开发者更好地理解和应用资源管理的最佳实践。 ... [详细]
  • Python 内存管理机制详解
    本文深入探讨了Python的内存管理机制,涵盖了垃圾回收、引用计数和内存池机制。通过具体示例和专业解释,帮助读者理解Python如何高效地管理和释放内存资源。 ... [详细]
  • 2018-2019学年第六周《Java数据结构与算法》学习总结
    本文总结了2018-2019学年第六周在《Java数据结构与算法》课程中的学习内容,重点介绍了非线性数据结构——树的相关知识及其应用。 ... [详细]
  • 在 Android 开发中,通过 Intent 启动 Activity 或 Service 时,可以使用 putExtra 方法传递数据。接收方可以通过 getIntent().getExtras() 获取这些数据。本文将介绍如何使用 RoboGuice 框架简化这一过程,特别是 @InjectExtra 注解的使用。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 本文详细介绍如何使用 Python 集成微信支付的三种主要方式:Native 支付、APP 支付和 JSAPI 支付。每种方式适用于不同的应用场景,如 PC 网站、移动端应用和公众号内支付等。 ... [详细]
  • 本文详细介绍了如何正确安装Java EE SDK,并解决在安装过程中可能遇到的问题,特别是关于servlet代码在Apache Tomcat 10中无法运行的情况。 ... [详细]
  • 微信小程序中实现位置获取的全面指南
    本文详细介绍了如何在微信小程序中实现地理位置的获取,包括通过微信官方API和腾讯地图API两种方式。文中不仅涵盖了必要的准备工作,如申请开发者密钥、下载并配置SDK等,还提供了处理用户授权及位置信息获取的具体代码示例。 ... [详细]
  • 本文介绍了一种利用WMI类Win32_SystemEnclosure中的ChassisTypes属性来识别计算机类型的简单方法,并提供了详细的脚本示例。 ... [详细]
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社区 版权所有