Announcing Anko for Android
We’re excited to announce a library we’ve been working on for Android development, which, among other things allows the creation of Application Interfaces in a type-safe and dynamic way using a DSL.
A Sample Taste
Here is a small example describing some of Anko’s possibilities. Imagine we need to create a simple sign-up form consisting of an EditText
for a username and a “Sign up” Button
. The code for this, using Anko would be:
import kotlinx.android.anko.* class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) verticalLayout { padding = dip(16) textView("Username:") { textSize = 18f }.layoutParams { verticalMargin = dip(4) } val login = editText() button("Sign up") { textSize = 20f onClick { login(login.text) } }.layoutParams { topMargin = dip(8) } } } }
Anko makes extensive use of Kotlin’s extension functions and properties arranged into type-safe builders to describe the user interface. In return, we get conciseness and type-safety at compile time.
Of course, we can also see a preview during design time using the Anko Preview plugin, available for both IntelliJ IDEA and Android Studio:
If we now want to add another text input widget, for instance an email, we could probably create another pair of textView()
and editText()
function calls. However, a nicer approach would be to extract the corresponding DSL fragment into a new function:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) verticalLayout { padding = dip(16) val login = inputField("Username") val email = inputField("E-mail") button("Sign up") { textSize = 20f onClick { login(login.text) } }.layoutParams { topMargin = dip(8) } } } fun _LinearLayout.inputField(name: String): TextView { textView("$name:") { textSize = 18f }.layoutParams { verticalMargin = dip(4) } return editText() }
Any additional inputs only require a single function call.
End result of the form would be:
Partially defined listeners
Anko is very helpful when you are using Android listeners with lots of methods. Consider the following code written that does not use 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 } })
Here’s the version using Anko:
seekBar { onProgressChanged { (seekBar, progress, fromUser) -> // Something } }
Methods that have empty bodies no longer require, well, empty implementations. Also, if setting onProgressChanged()
and onStartTrackingTouch()
for the same View, these two “partially defined” listeners will be merged.
More than a DSL
Anko is not just a DSL but a library which facilitates Android development in different areas. It has many methods covering dialogs, asynchronous tasks, services, intents and even SQLite database access.
For instance, if you want to start a new Activity
:
// Without Anko val intent = Intent(this, javaClass<MyActivity>()) intent.putExtra("id", 5) startActivity(intent) // With Anko startActivity<MyActivity>("id" to 5)
Or activate vibrator:
// Without Anko val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator vibrator.vibrate(500) // With Anko vibrator.vibrate(500)
Or even send a toast message:
// Without Anko Toast.makeText(this, "Download is complete!", Toast.LENGTH_SHORT).show() // With Anko toast("Download is complete!")
Existing code support
You can keep your old classes written in Java. Moreover, if you still want (or have) to write a Kotlin activity class and inflate an XML layout for some reason, you can use View
properties and listener helpers which would make things easier:
name.hint = "Enter your name" name.onClick { /* do something */ }
Benefits of Anko
Hopefully you can see that Anko offers a series of benefits, in particular:
- Everything is in one place. Instead of splitting layouts into static (XML) and dynamic parts and then trying to tie them together, we can just write everything we want using Kotlin. Compile-time type checking is a sweet bonus.
- Anko can make our code more concise and readable.
- It allows for easy re-use. We can just extract a part of the DSL into a function and use it multiple times.
Give it a try!
Anko is still in alpha stage but we want to release early to get your feedback, so please give it a try. We’ve made it as simple as possible to do so. It’s all published on Maven Central, and if you’re using Gradle, you can easily add the required dependencies to the build.gradle
file:
dependencies { compile 'org.jetbrains.anko:anko:0.5-15' }
The Anko Preview plugin is available both for IntelliJ IDEA and Android Studio. You can download it directly from the Plugin Repository.
There are binaries targeting both raw Android (SDK version 15, Ice Cream Sandwich) and Android with a support-v4 package.
Also, last but not least, much like everything related to Kotlin, Anko is fully Open Source. The repository is on GitHub and as always, contributions are welcome!
1p – Anko for Android | Exploding Ads says:
April 8, 2015[…] https://blog.jetbrains.com/kotlin/2015/04/announcing-anko-for-android/ […]
4 – Anko for Android | WhatCall.com says:
April 8, 2015[…] Read about this mobile article here: https://blog.jetbrains.com/kotlin/2015/04/announcing-anko-for-android/ […]
Olivier Binda says:
April 8, 2015What about layout/values that depends from runtime parameters like :
Right to left languages/locales
Density/width
free/premium…
what about loc
Yan Zhulanow says:
April 8, 2015Whatever you want to check, you could write a simple condition using Kotlin. There is already some syntactic sugar for checking orientation and density, and more will come soon!
Olivier Binda says:
April 8, 2015This looks very interesting.
There is a minor drawback (building with just style changes is way faster than compiling with code changes, especially with proguard-multidex) but it might be a potential big step forward.
What about min sdk api ? support lib compatibility ? testing ?
What about the mortar + flow + dagger + views – fragments way ?
Olivier Binda says:
April 8, 2015What about layout/styles/attr/values that depends from runtime parameters like :
Right to left languages/locales
Density/width
free/premium…
Eugen says:
April 8, 2015This is huge. Congratulations to the Kotlin Team. You’ve taken Android layout specifications out of the “XML shadow world”: http://gbracha.blogspot.de/2014/09/a-domain-of-shadows.html
Samuel Barbosa says:
April 8, 2015I just love you guys!
Oleg says:
April 8, 2015Who Anko? =)
Andrey Breslav says:
April 8, 2015http://www.savoryjapan.com/recipes/dessert/anko.html
Pranav says:
April 18, 2015I thought it stood for ANdroidKOtlin 😛
Dr.Optix says:
April 9, 2015I did not test it, but can layout parameters be set like this:
instead of:
Yan Zhulanow says:
April 9, 2015You could though it is not recommended.
Suppose you have a LinearLayout inside a RelativeLayout container, and you want to set LayoutParams for the inner LinearLayout. In this case, layoutParams() function you write inside the inner {} would be LinearLayout.layoutParams() and you might not notice this fact some time.
Kirill says:
April 9, 2015It gives
Failed to resolve: org.jetbrains.kotlin:anko:0.5-15
Yan Zhulanow says:
April 9, 2015What dependency repository do you use in build.gradle?
Anko is available on jcenter, Android Studio uses this repository by default.
Kirill says:
April 9, 2015For me it was mavenCentral() by default. I switched to jcenter(), but the same error occurs.
Vishnu Rajeevan says:
April 9, 2015This also occurs for me, using jcenter(). The other kotlin deps work just fine.
Leland Takamine says:
April 9, 2015Also getting this error
Yan Zhulanow says:
April 9, 2015Sorry for the wrong artifact name. The correct name is:
org.jetbrains.anko:anko:0.5-15
Sungcheol Kim says:
April 9, 2015Thank you for your best! It’s really great!
Даниил Водопьян says:
April 9, 2015Could you explain the reason for naming the container class like
_LinearLayout
? Why the underscore?Yan Zhulanow says:
April 9, 2015Name starting with an underscore is short (just one extra symbol), it doesn’t get in the way when using auto-completion (Linea
^
), and it is clear that the name is synthetic.БУТАКОВ ИГОРЬ says:
April 9, 2015ДОЛЖНО БЫТЬ
НЕ ТАК
“org.jetbrains.kotlin:anko:0.5-15”
А ТАК
“org.jetbrains.ANKO:anko:0.5-15”
Andrey Breslav says:
April 9, 2015Fixed. Thank you!
Tsuharesu says:
April 10, 2015I don’t know if I liked it or not.
I like that you are doing amazing work for the Android community; creating new ways of doing things (like Facebook is doing with React Native); primarily the new methods for toast, listeners and this things (lambdas are already awesome, and this is even better)
But I can’t say that I’m not afraid of what kind of monster this will create. I already have some really big Activities (100+ loc) and this is not making them thinner. Maybe I’m developing the wrong way, maybe not (of what I see on OS apps, that’s normal).
And this is kind of a grip I have with iOS, that sometimes the only way to achieve something is doing “by hand” on the code. Doesn’t seem to separate concerns.
What can you say?
Andrey Breslav says:
April 10, 2015I don’t have much experience developing for Andoid, so what follows is from my general experience:
Riley says:
May 13, 2015XML in Android is reusable via include tags
Johan Pelgrim says:
April 10, 2015I think it looks great for whenever you want to create small UI parts in code, but the big (BIG!) advantage of using layout code in XML is the fact that the Android framework knows from which resource folder to get the XML layout resource from. Simple case, if you want to distinguish between landscape or portrait you already get a big mess specifying your UI in code. Let alone distinguishing UIs for phones, phablets, tablets, etc. So this basically means rewriting the whole resource qualifier logic which the Android framework gives to you for free…
http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources
Eugenio Marletti says:
April 13, 2015To be fair, when you have a lot of qualifiers it becomes a NIGHTMARE to change anything or even understand what’s going on! While having everything in one place, with custom logic deciding how to modify the resource based on the qualifiers, would be a dream…
John Cart says:
April 13, 2015I can also say +1 for this, XML is better for me, so what I really needed is to use groovy-lang and some interesting ast-transformations from:
So my layers are still the same: XML for UI elements, syntax sugar from groovy and ast-transforms for reducing 60% java verbosity.
danijoo says:
April 14, 2015I absolutly agree on that. Being able to quickly define a small layout is awesome, but you (or at least me) really dont want to do that for large xmls file. If you have like 3 different xmls to support multiple screensizes and densities, this will make your activity class monstrous. Thats why we have those xmls.
Nevertheless, I really like the other features Anko provides (logging, toasts, asyncs)
Даниил Водопьян says:
April 15, 2015Maybe I look on that from a wrong angle, but what is the problem with separated XMLs? Nobody makes you merge layouts for portscape and landscape. If you wish, you can create two different Anko layouts in two different files (or folders):
Julys Pablo says:
April 12, 2015Hi! Great work. I’m trying o use the DSL Preview plugin, but it don’t show the preview!
Nigel H says:
April 16, 2015I’m having the same problem. Did you find a solution?
Yan Zhulanow says:
April 16, 2015Preview image is shown after pressing “Refresh”, it does not appear automatically because code compilation is required.
However, in case if you already pressed the “Refresh” button and nothing is shown, does it display an error instead of the preview?
Nigel H says:
April 17, 2015I was extending from ActionbarActivity instead of Activity. I changed it and now it works. Is this expected behaviour?
Yan Zhulanow says:
April 17, 2015Unfortunately, Android support-v7 and ActionBarSherlock Activities are not supported yet.
Preview uses Robolectric under the hood which does not work with such Activities, but it seems it will be supported in the next version.
Recursos imprescindibles para desarrolladores Android (XIX) | Bauber.com says:
April 12, 2015[…] Anko […]
Recursos imprescindibles para desarrolladores Android (XIX) - ANDROID DOMINICANO - Blog sobre el sistema operativo móvil de Google says:
April 12, 2015[…] Anko […]
Recursos imprescindibles para desarrolladores Android (XIX) | WWW.THEALEXITO.COM says:
April 13, 2015[…] Anko […]
Aksha says:
April 13, 2015Does this anko works only with Kotlin? Does it support normal java to do all those simple stuff easily?
Andrey Breslav says:
April 13, 2015Anko is a DSL written in Kotlin. Most of its power comes from the power of the language. Most features won’t work in plain Java
Rheza Satria says:
April 15, 2015I am wondering if i can use Kotlin (+ Anko) for iOS and Facebook React-Native. I think i would be awesome.
Andrey Breslav says:
April 16, 2015iOS development in Kotlin is possible through RoboVM
Reza Shah says:
April 21, 2015Yes, it’s possible. I have tried converting RoboVM default project to kotlin and run it.
Anko for RoboVM would be nice.
Is it easy to reuse Anko part to generete iOS DSL based on Kotlin?
Revue de Presse Xebia | Blog Xebia France says:
April 16, 2015[…] 8 avril, JetBrains a annoncé la sortie de sa toute nouvelle librairie nommée Anko. Elle permet de créer facilement et dynamiquement vos […]
Serge Zaitsev says:
April 16, 2015Hi!
I’m writing a similar library in pure Java: https://github.com/zserge/anvil
The idea of using declarative layout in code instead of XML is really great, but I think you can make it even better by adding automatic rendering and data-binding via virtual layout approach.
That would be a big and breaking change because the type-safe builders would build a virtual tree of nodes instead of a real layout, and then some renderer will convert it into a real android layout. But the benefit would be great – the whole app architecture would become more clear, readable and testable because data and UI will always be in sync:
class MyView(c: Context) : RenderableView(c) {
var count = 0
fun view() =
linearLayout {
orientation(LinearLayout.VERTICAL),
textView {
text("Count: " + count)
}
button {
text("Click me")
// UI will be updated on every click showing the new count value
onClick({ count++ })
}
}
}
Anvil already can be used with Kotlin, but it looks somewhat ugly, so if you have any ideas how to make it more pleasant – let me know:
Serge Zaitsev says:
April 16, 2015Ok, I abused some operator overloading and made my Anvil code look really cool:
More details here: http://zserge.com/blog/anvil-kotlin.html
Damian Petla says:
April 19, 2015Anko advertisement focus on creating UI from the code but there is more useful features described in Advanced section of Anko docs which I like much more. In case UI I will probably stick with XML, especially for complex layouts. Although, I would like to see more handful non-UI features for Fragments, Activities, Services etc. Maybe it would be better to separate UI Anko and non-UI Anko into 2 libraries.
Btw, some functions are missing for support classes e.g.
android.support.v4.app.Fragment.withArguments()
is missing. I would like to contribute and add those missing but I found setting up Anko in Android Studio as a problem. Could you consider recording or writing instruction how to do it properly?Jan Kovar says:
April 22, 2015I use the Kotlin type safe builders in a similar way in my Yested framework (building HTML DOM) and I use them in slightly different way to Anko. I define UI components that need to be accessed later as a class private fields. This has a benefit that I can define a logic in a class method and not inline. That keeps UI Layout code kind of simple.
Yan Zhulanow says:
April 23, 2015It requires you to have an underlying
Context
instance fully initialized which is quite not true untilonCreate()
method of anActivity
. So, for example,dip()
method invoke will lead to an exception.But you could use, for example,
Delegates.lazy
for such properties to achieve this behavior.Tahmid says:
May 20, 2015Love you guys. I always wanted a declarative DSL for describing android views.
Sorin Irimies says:
October 9, 2015Awesome. Would it be possible to integrate in anko, more extension functions. Suh as Fragment lifecycle management or Boradcast Receiver extension methods to reduce boilerplate.