Here we will add a couple of button widgets to the screen and we will then see a fast way to make them actually do something. We will add a button in two different ways, firstly using the visual designer and secondly by adding to and editing the XML code directly.
Adding a button via the visual designer
To get started with adding our first button,fragment_first.xml
, open it in the editor and switch back to the design view by clicking theDesign tab (shown next):
Figure 2.7 – Design tab
Notice to the left-hand side of the layout we have a window that is called thePalette and is shown next:
Figure 2.8 – Palette window
The palette is divided into two parts. The left-hand list has the categories of UI elements and allows you to select a category, and then the right-hand side shows you all the available UI elements from the currently selected category.
Make sure that theCommon category is selected as shown in the previous figure. Now, left-click and hold on theButton widget and then drag it onto the layout somewhere near the top center.
It doesn't matter if it is not exact. It is good to practice getting it right, however. So, if you are not happy with the position of your button, then you can left-click it to select it on the layout and then tap theDelete key on the keyboard to get rid of it. Now you can repeat the previous step until you have a new neatly placed button that you are happy with, as here:
Figure 2.9 – Updating the layout
At this point, we could run theapp on the emulator or on a real device and the button would be there – kind of. If we clicked it, there would even be a simple animation to represent the button being pressed and released. Feel free to try this now if you like. If you do, you will notice that the button isn't positioned as you expect it to be:
Figure 2.10 – Button not positioned correctly
Don't concernyourself with this apparent anomaly for now; we will look into this over the next few sections.
Next, we are going to edit the attributes of our button in theAttributes window.
Editing the button's attributes
Make sure thebutton is selected by left-clicking it. Now find theAttributes window to the right of the editing window as shown next:
Figure 2.11 – Attributes window
In the previous figure, youcan see that we have access to a wide selection of attributes from the currently selected UI element. To reveal more of the attributes, we click the different categories of attributes and scroll through them using the scrollbar to the right. If they are not open already by default, left-click on theCommonAttributes andAll Attributes sections' arrows to reveal their options.
Now you can see the full details of the button and we can set about editing it. It might seem surprising the substantial number of attributes that something as simple as a button has. This is a sign of the versatility and power that the Android API provides for UI manipulation.
As you can see, there is a large array of different attributes that we can edit right here in the UI designer. InChapter 13, Anonymous Classes – Bringing Android Widgets to Life, we will also edit and manipulate these attributes using our Java code.
For now, we will edit just one attribute. Scroll theAttributes window until you see theonClick attribute in theCommon Attributes section and then left-click it to select it for editing, as shown here:
Figure 2.12 – Common Attributes section
Note
If you ever have trouble finding an attribute, you can always find it in theAll Attributes section, where attributes are arranged in alphabetical order. Therefore, theonClick attribute can also be found about two-thirds of the way down the lengthy list of theAll Attributes section.
TypetopClick
in theonClick attribute's edit box and pressEnter on the keyboard. Be sure to use the same case, including theslightly counterintuitive lowercaset
and uppercaseC
.
TheAttributes window will look like this when you are done:
Figure 2.13 – onClick option
What we have done here is named the Java method in our code that we want to call when this button is clicked by the user. The name is arbitrary but as this button is in the top part of the screen, the name seems meaningful and easy to remember. The odd casing that we used is a convention that will help us keep our code clear and easy to read. We will see the benefits of this as our code gets longer and more complicated.
Of course, thetopClick
method doesn't exist yet. Android Studio is very helpful, but there are some things we need to do ourselves. We will write this method using Java code after we have added another button to our UI. You could run the app at this point and it would still work. But if you click the button, it will crash, and you will get an error because the method does not exist. Android Studio is forewarning us of this impending crash by outlining theonClick attribute in red, as shown in the previous figure. If you hover the mouse cursor over this red outline, you will see the details of the problem:Corresponding method handler… Not found.
Examining the XML code for the new button
Before we add our final button for this project. Click theCode tab to switch back to seeing the XML code that makes our UI.
Notice that there is a new block of code among the XML that we examined earlier. Here is an image of the new block of code:
Figure 2.14 – New block of code among the XML
Also, notice the following details, which should correspond to what we know about XML and Android UI elements:
- The new code starts with the text
<Button
and ends with/>
. - The code has a range of attributes that define the button, including
layoutWidth
andlayoutHeight
. - The code includes the
onClick
attribute that we just added with a value of"topClick"
. - The
topClick
value of theonClick
attribute is underlined in red, showing the missing method error. - The start and end of the code representing the button are enclosed within the
ConstraintLayout
element.
As in the design view, you can hover the mouse cursor over the red-underlinedtopClick
code to reveal the details of the problem:Corresponding method handler… Not found.
Note
During the writing of this book, Android Studio updated the way it shows errors in XML. Currently, it highlights the error in red, not underlining in red as shown in the figures and descriptions. The underlining is clearer in black and white print so they have been left as they are.
We can see that the issue is that Android Studio expects a method calledtopClick
to be implemented within our Java code. We will do this as soon as we have added that second button.
Adding a button by editing the XML code
Just for variety and to prove that we can, we will now add another button using only XML code, not the UI designer. Most of the time, we will use the UI designer, but this quick exercise should cement in your mind the relationship between the UI designer and the underlying XML code.
We will achieve this by copying and pasting the code for the existing button. We will then make some minor edits to the pasted code.
Left-click just before the button code that starts<Button
. Notice that the beginning and end of the code now have a slight highlight:
Figure 2.15 – Button code
This has identified the part of the code we want to copy. Now left-click and drag to select all the button code, including the highlighted start and end, as shown in this next figure:
Figure 2.16 – Select all the button code
Press theCtrl + C keyboard combination to copy the highlighted text. Place the keyboard cursor below the existing button code and tap theEnter key a few times to leave some spare empty lines.
Press theCtrl + V keyboard combination to paste the button code. At this point, we have two buttons. There are a couple of problems, however:
Figure 2.17 – Additional error
We have anadditional error in both blocks of code that represent our buttons. Theid
attribute (in both blocks) is underlined in red. The reason for this error is that both buttons have anid
attribute that is the same. Theid
attribute is supposed to distinguish a UI element from all other UI elements. Let's fix that.
Giving the buttons unique id attributes
We could solve the problem by calling the second button,button2
, but it would be more meaningful to change them both. Edit the code in the first button to give it an ID ofbuttonTop
. To do so, find the following line of code (in the first button):
android:id="@+id/button"
Change it to this:
android:id="@+id/buttonTop"
Note
Notice the lowercaseb
inbutton
and the uppercaseT
inTop
.
Now identify this line of code in the second button:
android:id="@+id/button"
Change it to this:
android:id="@+id/buttonBottom"
The errors on theid
attribute lines are gone. At this point, you might think we can move on to solve our missing method problem.
However, if you run the app and take a quick glance at it, you will see we only appear to have one button. Not only that but (as alluded to previously) the buttons are not in the place we expected them to be either:
Figure 2.18 – Single button
The reason for this is we haven't explicitly positioned them, so they have defaulted to the top left. Theposition we see on theDesign tab is just a design-time position. Let's change that now.
Positioning the two buttons in the layout
The reason we can only seeone button is that both buttons are in the same position. The second button is exactly covering the first button. And even in theDesign tab (feel free to have a look), the buttons are still sat on top of each other, although they are in the middle of the screen.
Note
You might be wondering why the UI layout tool was designed in this apparently counterintuitive way. The reason is flexibility. As we will see in the next two chapters, not only is it possible to position UI elements differently at design time to when the app is running but there is also a whole bunch of different layout schemes that the app designer (that's you) can choose from to suit their plans. This flexibility results in a little awkwardness while learning about Android but great design power once you have got past the awkwardness. Don't worry: we will move a step at a time until you have this thing beaten.
We will make Android Studio solve the problem for us automatically by first adding to our code and then using the UI designer. First, let's get the design-time layout right. In the code for the second button, find this line of code:
tools:layout_editor_absoluteY="30dp" />
Edit it to be the same as this:
tools:layout_editor_absoluteY="100dp" />
This subtle change will move the second button down a little, but only for design time. If you look in theDesign tab, the button is positioned neatly underneath the first button, but if you run the app on the emulator, they are both still in the top-left corner and on top of one another.
Note
It is possible, even likely, that the exactdp
measurements in your layout will be slightly different to those shown in the book. As long as the second button'slayout_editor_absoluteY
attribute is about70dp
greater than the first, then all will be neat and tidy. Feel free to play with this attribute on both buttons while switching between theCode andDesign tabs until the buttons are positioned to your liking.
When you are satisfied with the position of the buttons, switch to theDesign tab and find theInfer constraints button, shown next:
Figure 2.19 – Infer constraints button
Click theInfer constraints button. Android Studio will edit the XML. Let's take a brief look at what has happened behind the scenes. From the end of both of the buttons, the following lines of code were removed.
If the constraints aren't being applied, hit theClear All Constraints button, which is to the left ofInfer constraints; sometimes Android Studio can get confused and needs to reset the existing constraints before inferring the rest:
tools:layout_editor_absoluteX="147dp"tools:layout_editor_absoluteY="30dp" />
These two lines of code were what positioned the buttons horizontally (…absoluteX
) and vertically (…absoluteY
).
Android Studio also added four lines of code to the first button and three to the second. Here is the code added near the start of the first button:
android:layout_marginTop="30dp"
This code causes the button to have a margin of 30 at the top. But at the top relative to what exactly? Look at these three lines of code that were added at the end of the first button:
app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />
Notice the new attributes oflayout_constraintEnd_toEndOf
,layout_constraintStart_toStartOf
, andlayout_constraintTop_toTopOf
. The value assigned to each of these attributes is"parent"
. This causes the first button to be positioned relative to theparent UI element. The parent is the containing layout: theConstraintLayout
element.
Now look at the three linesof code added to the second (bottom) button.
Near the start of the code, we see this:
android:layout_marginTop="22dp"
And at the end of the code for the second button, we see these two extra lines:
app:layout_constraintStart_toStartOf="@+id/buttonTop"app:layout_constraintTop_toBottomOf="@+id/buttonTop" />
This means that the second button is positioned with a margin of 22 relative to thebuttonTop
widget.
Note
Thedp
code is a unit of measurement/distance and will be discussed in more depth inChapter 5, Beautiful Layouts with CardView and ScrollView. The precise values for thedp
measurement will likely vary slightly on your layout.
Now run the app and you will see we have two distinct buttons. One has anid
attribute ofbuttonTop
and it is above the other button, with anid
attribute ofbuttonBottom
:
Figure 2.20 – Two button options
Clearly, there ismore to layouts than I have alluded to so far, but you have had your first glance at one of the options we have to design the UI of our apps. We will be taking a closer look at theConstraintLayout
layout element as well as exploring more layout options inChapter 4, Getting Started with Layouts and Material Design.
We want to make one more change in our XML code.
Making the buttons call different methods
Switch back to theCode tab and identify this next line of code in the second (buttonBottom
) button:
android:onClick="topClick"
Edit the code to this:
android:onClick="bottomClick"
Now we have two buttons, one above the other. The top one has anid
attribute ofbuttonTop
and anonClick
attribute with a value oftopClick
. The other has anid
attribute ofbuttonBottom
and anonClick
attribute with a value ofbottomClick
.
These last XML code changes now mean we need to code two methods (topClick
andbottomClick
) in our Java code.
Note
It is OK for two buttons to call the same method when they are clicked; it is not a syntax error. However, most buttons do have distinct purposes, so this exercise will be more meaningful if our buttons do different things.
We will do that soon, but before we do, let's learn a little bit more about Java comments and look at some Java code we can write to send messages. We will learn to send messages to the user to keep them informed and to ourselves for debugging purposes.