Anko tips&tricks
November 08, 2016
Some time ago I'v 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) use, discover and I don’t want to hide them 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 bold,
italic
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 TextView
s 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 View
s 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.visible = show
}
Again — extension property
var View.visible: 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!