In this task, you will add two more buttons to your user interface, and update the existing button.
How to add new views to your layout.
How to constrain the position of a view to another view.
1. In fragment_first.xml, look at the constraint properties for the TextView
These properties define the position of the TextView. Read them carefully.
You can constrain the top, bottom, left, and right of a view to the top, bottom, left, and right of other views.
2. Select textview_first in the Component Tree and look at the Constraint Widget in the Attributes panel.
The square represents the selected view. Each of the grey dots represents a constraint, to the top, bottom, left, and right; for this example, from the TextView to its parent, the ConstraintLayout, or to the Next button for the bottom constraint.
3. Notice that the blueprint and design views also show the constraints when a particular view is selected. Some of the constraints are jagged lines, but the one to the Next button is a squiggle, because it's a little different. You'll learn more about that in a bit.
You will adjust the button labeled Next, which Android Studio created for you when you created the project. The constraint between it and the TextView looks a little different, a wavy line instead of a jagged one, with no arrow. This indicates a chain, where the constraints link two or more objects to each other, instead of just one to another. For now, you'll delete the chained constraints and replace them with regular constraints.
In the design view or blueprint view, hold the Ctrl key (Command on a Mac) and move the cursor over the circle for the constraint until the circle highlights, then click the circle.
Or click on one of the constrained views, then right-click on the constraint and select Delete from the menu.
Or in the Attributes panel, move the cursor over the circle for the constraint until it shows an x, then click it.
If you delete a constraint and want it back, either undo the action, or create a new constraint.
Click on the Next button, and then delete the constraint from the bottom of the button to the TextView.
Click on the TextView, and then delete the constraint from the top of the text to the Next button.
Step 3: Add buttons
To learn how to use constraints to connect the positions of views to each other, you will add buttons to the layout. Your first goal is to add a button and some constraints, and change the constraints on the Next button.
Notice the Palette at the top left of the layout editor. Move the sides if you need to, so that you can see many of the items in the palette.
Click on some of the categories, and scroll the listed items if needed to get an idea of what's available.
Select Button, which is near the top, and drag and drop it onto the design view, placing it underneath the TextView near the other button. Notice that a Button has been added to the Component Tree under ConstraintLayout.
The constraint layout is small, and doesn't give room for design. Click ConstraintLayout in Pallette. Go to Attributes, and go to minHeight under Common Attributes. Set this value to 500dp. Notice that ConstraintLayout has lengthened (shown in the screenshot below).
Note that there is a red error sign to the right of button2. This means we have not yet set constraints for it. We will get to this in the next step.
1. Orient the components so that the Textview component is above the "Next" button component. The "Button" button should be directly to the right of the "Next" button
2. Constrain the bottom of the Textview component to the top of the "Next" button. Go to the XML code and scroll to the Textview code. Replace
app:layout_constraintBottom_toBottomOf="parent"
with
app:layout_constraintBottom_toTopOf="@id/button_first"
3. Now constrain the top of the "Next" button to the bottom of the Textview component . Scroll to the Button code corresponding to the "Next" button. Replace
app:layout_constraintTop_toTopOf="parent"
with
app:layout_constraintTop_toBottomOf="@id/textview_first"
4. Select the Textview component in the Design View and go to Attributes. Set the bottom constraint to 300dp. Add a top constraint of 100 dp by pressing the "+" and typing it in.
5. Set the top constraint of the "Next" button to 300 dp following the same process.
6. As mentioned before, the button2 button has been showing an error because constraints have not been added. Let us constrain the button to the bottom of the Textview component by adding app:layout_constraintTop_toBottomOf="@id/textview_first"
to the button's XML code.
Note that when you placed the button on the screen, there may be existing code to describe the location
EXAMPLE:
tools:layout_editor_absoluteX= "[some value]"
or
tools:layout_editor_absoluteY= "[some value]"
and constraints like
app:layout_constraintTop_toTopOf="parent"
Delete it.
7. Set the button's top constraint to 300 dp as done with the other button.
8. Constrain the button horizontally by adding the code
app:layout_constraintLeft_toRightOf="@id/button_first"
to the button's XML code. This constrains it to the right of the "Next" button.
9. Set the button's right constraint to 24 dp in Attributes. While in Attributes, change the id from button to random_button.
It may seem like the views are jumping around a lot, but that's normal as you add and remove constraints.
Your layout should now look something like this.
In the fragment_first.xml layout file, find the text property for the random_button button.
<Button
android:id="@+id/random_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
Notice that the text "Button" is directly in the layout field, instead of referencing a string resource as the TextView does. This will make it harder to translate your app to other languages.
To fix this, click the highlighted code. A light bulb appears on the left.
Click the lightbulb. In the menu that pops up, select Extract string resource.
In the dialog box that appears, change the resource name to toast_button_text and the resource value to Toast and click OK.
Notice that the value of the android:text property has changed to @string/random_button_text.
Go to the res > values > strings.xml file. Notice that a new string resource has been added, named random_button_text.
<resources>
...
<string name="random_button_text">Random</string>
</resources>
Run the app to make sure it displays as you expect it to.
You now know how to create new string resources by extracting them from existing field values. (You can also add new resources to the strings.xml file manually.) And you know how to change the id of a view.
Note: The id for a view helps you identify that view distinctly from other views. You'll use this later to find particular views using the findViewById() method in your Java code.
The Next button already has its text in a string resource, but you'll make some changes to the button to match its new role, which will be to generate and display a random number.
As you did for the Random button, change the id of the Next button from button_first to count_button in the Attributes panel.
If you get a dialog box asking to update all usages of the button, click Yes. This will fix any other references to the button in the project code.
In strings.xml, right-click on the next string resource.
Select Refactor > Rename... and change the name to random_button_text.
Click Refactor to rename your string and close the dialog.
Change the value of the string from Next to Count.
If you want, move count_button_text to below toast_button_text.
Your final layout will have three buttons, vertically constrained the same, and evenly spaced from each other.
In fragment_first.xml, add another button to the layout, and drop it to the left of the Count button and the Random button, below the TextView.
Add vertical constraints the same as the other two buttons. Constrain the top of the third button to the bottom of TextView.
Add horizontal constraints from the third button to the other buttons. Constrain the right side of the third button to the left side of the Count button.
Your layout should look something like this:
Examine the XML code for fragment_first.xml. Do any of the buttons have the attribute app:layout_constraintVertical_bias? It's OK if you do not see that constraint.
The "bias" constraints allows you to tweak the position of a view to be more on one side than the other when both sides are constrained in opposite directions. For example, if both the top and bottom sides of a view are constrained to the top and bottom of the screen, you can use a vertical bias to place the view more towards the top than the bottom.
Here is the XML code for the finished layout. Your layout might have different margins and perhaps some different vertical or horizontal bias constraints.The exact values of the attributes for the appearance of the TextView might be different for your app(The code for Count was moved to be aside the other two).
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/screenBackground"
tools:context=".FirstFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/screenBackground"
android:minHeight="500dp"
android:padding="16dp">
<TextView
android:id="@+id/textview_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:layout_marginBottom="300dp"
android:background="@color/cardview_dark_background"
android:fontFamily="sans-serif-condensed"
android:text="@string/lorem_ipsum"
android:textColor="@android:color/white"
android:textSize="20sp"
android:textStyle="bold|italic"
app:layout_constraintBottom_toTopOf="@id/count_first"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.514"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/count_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:text="@string/count_button_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textview_first" />
<Button
android:id="@+id/random_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:layout_marginTop="300dp"
android:text="@string/random_button_text"
app:layout_constraintLeft_toRightOf="@id/count_first"
app:layout_constraintTop_toBottomOf="@id/textview_first" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:layout_marginRight="24dp"
android:text="Button"
app:layout_constraintRight_toLeftOf="@id/count_first"
app:layout_constraintTop_toBottomOf="@id/textview_first" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
The next task is to make the buttons do something when they are pressed. First, you need to get the UI ready.
1. Change the text of the TextView to show 0 (the number zero).
2. Change the id of the last button you added, button2, to toast_button in the Attributes panel in the design editor.
3. In the XML, extract the string resource to toast_button_text and set the value to Toast.
4. Run the app.
If you edited the XML for the layout directly, you might see some errors.
The errors occur because the buttons have changed their id and now these constraints are referencing non-existent views.
If you have these errors, fix them by updating the id of the buttons in the constraints that are underlined in red.
app:layout_constraintEnd_toStartOf="@+id/random_button"
app:layout_constraintStart_toEndOf="@+id/toast_button"