TextViews are one of the basis of Android UI framework. Buttons, EditTexts, RadioButtons are, indeed, TextViews. And they are also one of the most powerful tools we have to create our layouts. Knowing them in deep can help us save time, views and simplify our layouts, making our UI faster.
In this series, I will talk about TextView and its direct subclasses. I’m beginning with one of the most basic cases, that you may know. But If you don’t, you will love it.
There are a lot of situations where we need to use a TextView (or EditText, Button… remember they are subclasses) with a simple image at the left or right. That’s not that difficult, right? We simply need an ImageView plus a TextView inside a LinearLayout:
[xml]
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:gravity="center"
android:layout_gravity="center_horizontal"
>
<TextView
android:text="@string/my_contacts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:paddingLeft="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_add_group"
/>
</LinearLayout>
[/xml]
Lint already warns that there is a better way to do this by using a TextView and a compound drawable. What’s this? Our TextView has four properties that let us specify images to be set around it. These ones are: drawableLeft, drawableRight, drawableTop and drawableBottom. We also can use another one which defines the padding among the text and the images: drawablePadding.
Ok then, let’s change the previous layout and get rid of LinearLayout and ImageView:
[xml]
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:text="@string/my_contacts"
android:drawableRight="@drawable/ic_action_add_group"
android:drawablePadding="8dp"
/>
[/xml]
Cool! We removed a level of complexity and made our XML much simpler. It’s almost as easy to set these drawables from code:
[java]
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_add_group, 0);
textView.setCompoundDrawablePadding(…);
[/java]
With this idea in mind, we can create very interesting layouts. Let’s create a simple username and password form:
[xml]
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:orientation="vertical"
android:layout_marginTop="16dp"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:hint="@string/user_name"
android:drawableLeft="@drawable/ic_action_person"
android:drawablePadding="8dp"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:hint="@string/password"
android:drawableLeft="@drawable/ic_action_accounts"
android:drawablePadding="8dp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/log_in"
android:drawableRight="@drawable/ic_action_accept"
/>
</LinearLayout>
[/xml]
Quite easy. Next episode will cover a way to make a drawable clickable, another trick to keep your layout simple by taking the most out of TextViews.
Awesome post, I wish I had known this when I was starting out. Would’ve saved a lot of time
awesome!
Great post!
Awesome, really useful post to save our time
THanks for the schweet tut
Good post.
But we have to keep in mind that these can only be useful in certain scenarios.
For example if we want to have a drawable at the start of a multiline textview it wont be possible unless you are targetting API 17.
I think it’s obsolete.
Why?
Thaks for providing tips for us…It is realy good and useful
¿Has probado a hacerlo en un Navigation Drawer con un custom adapter? No funciona bien, al menos a mí me hace cosas raras (a partir del tercer elemento repite todos los compounds drawables aunque las asignaciones sean distintas….)
Ya he conseguido que funcione. Retiro lo dicho.
Great,Really enjoyed that
Thanks, really neat!
great post.but how to make only drawable clickable
Good Job
Thanks a lot
Thanks alot
Simple and straight to the point. Great post. Thank you.
Hello,
You never wrote a part II to this. I am looking for a way to add click events to a text views drawables
EDIT: I have checked SO. A neat trick is to add an onTouchListener to the TextView and check if the motion even fals within the bounds of the drawable. The theory looks solid so I’ll try that out later.
New challenge: Draw a drawable based on its state…The problem here is that I have a custom drawable that is set as a TextView compoundDrawable. How can I draw my drawable based on the pressed state (I can andle the clicks with the above manner, I just need visual indication that the drawable has been pressed)
But how set the drawable size on image???
You can’t, that’s a limitation of drawables in TextViews. The image needs to have the final size.