Announcing Anko for Android

Hadi Hariri

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:

Anko Designer

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:

Anko result form

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!

Comments below can no longer be edited.

53 Responses to Announcing Anko for Android

  1. 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/ […]

  2. Olivier Binda says:

    April 8, 2015

    What 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, 2015

      Whatever 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, 2015

        This 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 ?

  3. Olivier Binda says:

    April 8, 2015

    What about layout/styles/attr/values that depends from runtime parameters like :

    Right to left languages/locales
    Density/width
    free/premium…

  4. Eugen says:

    April 8, 2015

    This 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

  5. Samuel Barbosa says:

    April 8, 2015

    I just love you guys!

  6. Oleg says:

    April 8, 2015

    Who Anko? =)

  7. Dr.Optix says:

    April 9, 2015

    I did not test it, but can layout parameters be set like this:

    button("Sign up") {
                textSize = 20f
                onClick { login(login.text) }
               layoutParams { topMargin = dip(8) }
     }
    

    instead of:

    
    button("Sign up") {
                textSize = 20f
                onClick { login(login.text) }
     }.layoutParams { topMargin = dip(8) }
    
    • Yan Zhulanow says:

      April 9, 2015

      You 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.

  8. Kirill says:

    April 9, 2015

    It gives
    Failed to resolve: org.jetbrains.kotlin:anko:0.5-15

    • Yan Zhulanow says:

      April 9, 2015

      What dependency repository do you use in build.gradle?
      Anko is available on jcenter, Android Studio uses this repository by default.

      • Kirill says:

        April 9, 2015

        For me it was mavenCentral() by default. I switched to jcenter(), but the same error occurs.

        • Vishnu Rajeevan says:

          April 9, 2015

          This also occurs for me, using jcenter(). The other kotlin deps work just fine.

          • Leland Takamine says:

            April 9, 2015

            Also getting this error

          • Yan Zhulanow says:

            April 9, 2015

            Sorry for the wrong artifact name. The correct name is:
            org.jetbrains.anko:anko:0.5-15

  9. Sungcheol Kim says:

    April 9, 2015

    Thank you for your best! It’s really great!

  10. Даниил Водопьян says:

    April 9, 2015

    Could you explain the reason for naming the container class like _LinearLayout ? Why the underscore?

    • Yan Zhulanow says:

      April 9, 2015

      Name 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.

  11. БУТАКОВ ИГОРЬ says:

    April 9, 2015

    ДОЛЖНО БЫТЬ
    НЕ ТАК
    “org.jetbrains.kotlin:anko:0.5-15”
    А ТАК
    “org.jetbrains.ANKO:anko:0.5-15”

  12. Tsuharesu says:

    April 10, 2015

    I 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, 2015

      I don’t have much experience developing for Andoid, so what follows is from my general experience:

      • 100 loc is not really a big class (even in Kotlin, let alone in Java)
      • You can still separate concerns with Anko, because the layout code can be factored out as a function (or many composable functions) and put into separate file(s). The difference is: you have a choice, that is, admittedly, one more thing to think about, so many people won’t say it’s a benefit.
      • Having it represented as code or some other kind of text (e.g. XML) does not make much of a difference, apart from the fact that code, unlike XML, is reusable. Well, again, keeping the code clean requires discipline, which may be a downside for some people
      • Riley says:

        May 13, 2015

        XML in Android is reusable via include tags

  13. Johan Pelgrim says:

    April 10, 2015

    I 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, 2015

      To 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, 2015

      I 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, 2015

      I 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, 2015

      Maybe 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):

      _LinearLayout.myLayout_1(): Unit {
        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) }
      
      }
      
      _LinearLayout.myLayout_2(): Unit {...}
      
      class MainActivity : Activity() {
      
        override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
      
          if(landscape)
            verticalLayout(myLayout_1)
          else
            verticalLayout(myLayout_2)
      }
      
  14. Julys Pablo says:

    April 12, 2015

    Hi! Great work. I’m trying o use the DSL Preview plugin, but it don’t show the preview!

    • Nigel H says:

      April 16, 2015

      I’m having the same problem. Did you find a solution?

      • Yan Zhulanow says:

        April 16, 2015

        Preview 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, 2015

          I was extending from ActionbarActivity instead of Activity. I changed it and now it works. Is this expected behaviour?

          • Yan Zhulanow says:

            April 17, 2015

            Unfortunately, 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.

  15. Aksha says:

    April 13, 2015

    Does this anko works only with Kotlin? Does it support normal java to do all those simple stuff easily?

    • Andrey Breslav says:

      April 13, 2015

      Anko 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

  16. Rheza Satria says:

    April 15, 2015

    I 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, 2015

      iOS development in Kotlin is possible through RoboVM

      • Reza Shah says:

        April 21, 2015

        Yes, 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?

  17. 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 […]

  18. Serge Zaitsev says:

    April 16, 2015

    Hi!

    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:

    class MyView(c: Context) : RenderableView(c) {
    
        var count = 0
    
        public override fun view() =
            v(javaClass(),
                orientation(LinearLayout.VERTICAL),
    
                v(javaClass(),
                    text("Count: " + count)),
    
                v(javaClass(),
                    onClick({ count++ }),
                    text("Click me")))
    }
    

    • Serge Zaitsev says:

      April 16, 2015

      Ok, I abused some operator overloading and made my Anvil code look really cool:

        public override fun view() =
              v {
                  - size(FILL, FILL)
                  - orientation(LinearLayout.VERTICAL)
      
                  v {
                      - text("Clicked: " + count)
                  }
                  v {
                      - text("Click me")
                      - onClick {
                          println("Button clicked")
                          count++
                      }
                  }
              }
      

      More details here: http://zserge.com/blog/anvil-kotlin.html

  19. Damian Petla says:

    April 19, 2015

    Anko 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?

  20. Jan Kovar says:

    April 22, 2015

    I 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.

    class SomeComponent  {
        private val login = inputField("Username")
        private val email = inputField("E-mail")
    
        fun doLogin() {
            doLogin(login.text, email.text)
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            verticalLayout {
                padding = dip(16)
                +login 
                +email
                button("Sign up") {
                    textSize = 20f
                    onClick { doLogin() }
                }
            }
    
    
        }
    }
    
    • Yan Zhulanow says:

      April 23, 2015

      It requires you to have an underlying Context instance fully initialized which is quite not true until onCreate() method of an Activity. 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.

  21. Tahmid says:

    May 20, 2015

    Love you guys. I always wanted a declarative DSL for describing android views.

  22. Sorin Irimies says:

    October 9, 2015

    Awesome. Would it be possible to integrate in anko, more extension functions. Suh as Fragment lifecycle management or Boradcast Receiver extension methods to reduce boilerplate.