Some time ago I decided to try Kotlin in production and a few weeks ago I started developing an application that is the one, the one with Kotlin under the hood. When I discovered Anko library I was amazed by its simplicity and advantages over standard xml approach.

A lot of great articles were written about introduction to Anko (like here or here) and this series of mini posts shouldn’t be one of them. My idea is that this will be just a bunch of neat tips and tricks that I (or my colleagues) discover, use and we don’t want to hide under pillow.

Disclaimer: I am very new to Anko and Kotlin in general and it’s possible that sometimes I am reinventing the wheel or that some thing could be done in better way. Please, feel free to point it up in discussion. This feedback is very welcome (or any other feedback as well :))

Tip #1 — View Extension properties

Every designer loves to differentiate texts in application with typefaces — bold, medium, light, regular, italic and you can combine most of them. The Android framework provides few ways how to easily apply some typefaces to TextView like textStyle or fontFamily xml attribute. With textStyle you can make text bolditalic or bolditalic. This is just a subset of Roboto typefaces and if you want to make text for example medium typeface, you have to use other ways. fontFamily is other attribute that you can use. You define name of font family you want to use from predefined set of font families. The problem is that medium typeface mentioned above is added in Android Lollipop and be honest, do you have minSdk on 21? I don’t think so. The solution is to copy the font files (Roboto-Regular.ttf, Roboto-Bold.ttf, Roboto-Medium.ttf, …) into your application assets and set custom typeface to TextView. But you don’t want to set typeface to every TextView in your application in Java code.

So what is the solution for this problem? Calligraphy for the rescue!Calligraphy is Android library that injects itself into LayoutInflater and applies fonts you want to use to TextViews when building the layout.

Ok, but if you are using Anko you are not using LayoutInflater. What then? The first thought is to set Typeface to TextView with my custom font when creating the view.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    verticalLayout {
        padding = dip(16)
        textView {
            text = "My medium text"
            textSize = 24f
            typeface = Typeface.createFromAsset(context.assets, "fonts/Roboto-Medium.ttf")
       }
    }
}

Egh. That doesn’t look so good. Wouldn’t it be nicer this way?

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    verticalLayout {
        padding = dip(16)
        textView {
            text = "My medium text"
            textSize = 24f
            typeface = medium
       }
    }
}

But how to achieve that? We could use some cool language feature that Kotlin provides. Yes, extension properties! We define properties for different typefaces and then you can use this “shortcuts”


val TextView.light: Typeface get() = 
Typeface.createFromAsset(context.assets, "fonts/Roboto-Light.ttf")

val TextView.regular: Typeface get() = 
Typeface.createFromAsset(context.assets, "fonts/Roboto-Regular.ttf")

val TextView.medium: Typeface get() = 
Typeface.createFromAsset(context.assets, "fonts/Roboto-Medium.ttf")

val TextView.bold: Typeface get() = 
Typeface.createFromAsset(context.assets, "fonts/Roboto-Bold.ttf")

With this properties you can boost regular Views with additional artificial attributes. Another great example is View visibility. Typically you want to hide or show view based on some boolean. In java you’ve probably wrote this piece of code like a zanzillion times

void showProgress(boolean show) {
  progress.setVisibility(show ? View.VISIBLE : View.GONE);
}

In Kotlin it looks even messier without ternary operator

fun showProgress(show: Boolean) {
  progress.visibility = if(show) View.VISIBLE else View.GONE
}

But I want to write code like

fun showProgress(show: Boolean) {
  progress.show = show
}

Again — extension property

var View.show: Boolean
    get() = throw IllegalAccessException("show attribute just for set")
    set(value) {
        visibility = if (value) View.VISIBLE else View.GONE
    }

 

Conclusion

In this blogpost I’ve demonstrated how to use extension properties to achieve clean, readable code on custom TextView typefaces and View visibility attributes. In the next posts I’ll dive into topics like ViewHolder pattern, AnkoComponent reusing, custom views and probably much more. Looking forward!

 

Leave a Reply

Your email address will not be published. Required fields are marked *