Here I’ll ilustrate the creation of a custom widget
through a pratical example: A Loading Button. A loading button is a
button with a spinning indicator. It’s useful for buttons that
trigger servers requests.
As our first step, let’s create a Java class called “LoadingButton”
that extends of RelativeLayout view. You may be asking why we are
extending of RelativeLayout instead of Button class. The quick answer
is Button doesn’t allow views inside of it, Layouts does, and we’re
going to need that functionality. :) (But don’t worry, that won’t make
our button less than a button!).
Simple like that! By using the “addView” method we are adding a new view to
our layout. But we still need to define things like: width,
height and style. For width and height, we’re going to use something called
LayoutParams, that acts the same as android:layout_* attributes on XML
It’s pretty straight-forward. We’re here setting width and height to
“wrap_content” and centering both widgets. Of course, we’re not going
to show both at the same time, that’s why I hid the progressbar using
the “setVisibility” method.
Now we just need two others methods, that either will display the spinning
indicator either will display the text.
Wait! Something is missing! We are using a RelativeLayout to simulate
a button, but layouts don’t have the attribute “android:text”. So how
do you set the text?
For that we’re going to need a styleable.
Styleable is, in short, a set of custom attributes. For example, when
you declare in your layouts xml files on your top-parent view the
xmlns:android="http://schemas.android.com/apk/res/android", you are
actually saying where are Android default styleables and naming it “android”,
so you can access the attributes through the prefix “android:”.
To create a new styleable, go to res > values > attrs.xml. If this
file is not created yet, create it with the following structure:
To create a new attribute just create a new tag of type <attr>
inside the <declare-styleable> tag. A tag has a name (the attribute
name) and a format, namely the input type it accepts. The format can
be of the several types, among them: string, integer, boolean, …
And we are done with styleables! If we need to pass more informations
for our button beyond its text, like, for example, text color, just
create a new attribute!
Now let’s go back to our Java class. Now we need to link our newly
created styleble to our class. For that create a method called
“setAttributes” that receives as parameter a variable of kind “Context”
and another of kind “AttributeSet” and returns void and calls this
method inside all constructors except the one that just receives one
I created a new class member called “mText” to store the string we are
going to get through the attribute “text”. To link to our styleable se
use the method “obtainStyledAttributes”, that receives as parameter
the set of attributes (attrs) and the styleable name. Finally, we
extract an attribute value calling the called “get*”, where * is the
type of attribute we want to extract. This type is related to the
“format” we defined on our XML file.
Now we just need to adjust the method “init” to now set the text of
EditText to our variable “mText”.
You must replace “PACKAGE_NAME” for the package where the
LoadingButton class is within. Also, notice I must define to where my
styleable is before using its attribute. You could pass the real path
(http://schemas.android.com/apk/res/values/attrs.xml), but the res-auto
automatically redirects to “attrs.xml”. After naming it “app”, I could
have access to the “text” attribute through the prefix “app:”.