So far, you've focused on the first screen of your app. Next, you will update the Random button to display a random number between 0 and the current count on a second screen.
How to pass information to a second fragment.
1. Open fragment_second.xml (app > res > layout > fragment_second.xml) and switch to Design View if needed. Notice that it has a ConstraintLayout that contains a TextView and a Button.
2. Make the minHeight of the ConstraintLayout 500dp as we did with the first fragment.
3. Remove the chain constraints between the TextView and the Button.
4. Add another TextView from the palette and drop it near the middle of the screen. This TextView will be used to display a random number between 0 and the current count from the first Fragment.
5. Set the id to @+id/textview_random (textview_random in the Attributes panel.)
6. Constrain the top edge of the new TextView to the bottom of the first TextView, the left edge to the left of the screen, and the right edge to the right of the screen, and the bottom to the top of the Previous button. Orient the components so that the first Textview is above the new TextView above the button (make the specific locations to your liking!)
Note that you must add constraints horizontally and vertically to avoid errors.
7. Set both width and height of the new TextView to wrap_content.
8. Set the textColor to @android:color/white, set the textSize to 72sp, and the textStyle to bold.
9. Set the text to "R". This text is just a placeholder until the random number is generated.
10. Set the layout_constraintVertical_bias to 0.45.
11. Set the NestedScrollView background to the defined screen background color.
This TextView is constrained on all edges, so it's better to use a vertical bias than margins to adjust the vertical position, to help the layout look good on different screen sizes and orientations. 10. If you get a warning "Not Horizontally Constrained," add a constraint from the start of the button to the left side of the screen and the end of the button to the right side of the screen.
Here is the XML code for the TextView that displays the random number:
<TextView
android:id="@+id/textview_random"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="R"
android:textColor="@android:color/white"
android:textSize="72sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/button_second"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textview_second"
app:layout_constraintVertical_bias="0.45" />
1. In fragment_second.xml, select textview_second, which currently has the text "Hello second fragment. Arg: %1$s" in the hello_second_fragment string resource.
2. If android:text isn't set, set it to the hello_second_fragment string resource.
android:text="@string/hello_second_fragment"
3. Change the id to textview_header in the Attributes panel.
4. Set the width to match_constraint, but set the height to wrap_content, so the height will change as needed to match the height of the content.
5. Set top, left and right margins to 24dp. Left and right margins may also be referred to as "start" and "end" to support localization for right to left languages.
6. Remove any bottom constraint.
7. Set the text color to @color/black and the text size to 24sp.
8. In strings.xml, change hello_second_fragment to "Here is a random number between 0 and %d."
9. Use Refactor > Rename... to change the name of hello_second_fragment to random_heading.
Note that if you get an error in the other Textview, make sure to change the name in the constraint as well to random_heading
Here is the XML code for the TextView that displays the heading:
<TextView
android:id="@+id/textview_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginBottom="24dp"
android:layout_marginEnd="24dp"
android:text="@string/random_heading_text"
android:textColor="@color/black"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/textview_random"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
When you created your project, you chose Basic Activity as the template for the new project. When Android Studio uses the Basic Activity template for a new project, it sets up two fragments, and a navigation graph to connect the two. It also set up a button to send a string argument from the first fragment to the second. This is the button you changed into the Random button. And now you want to send a number instead of a string.
1. Open nav_graph.xml (app > res > navigation > nav_graph.xml).
A screen similar to the Layout Editor in Design view appears. It shows the two fragments with some arrows between them. You can zoom with + and - buttons in the lower right, as you did with the Layout Editor.
2. You can freely move the elements in the navigation editor. For example, if the fragments appear with SecondFragment to the left, drag FirstFragment to the left of SecondFragment so they appear in the order you work with them.
This will enable SafeArgs in Android Studio.
1. Open Gradle Scripts > build.gradle (Project: My First App)
2. Find the dependencies section In the buildscript section, and add the following lines after the other classpath entries:
buildscript {
repositories {
google()
}
dependencies {
val nav_version = "2.7.6"
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version")
}
}
3. Open Gradle Scripts > build.gradle (Module: app)
4. Just below the other lines that begin with apply plugin add a line to enable SafeArgs:
apply plugin: 'androidx.navigation.safeargs'
5. Android Studio should display a message about the Gradle files being changed. Click Sync Now on the right hand side.
After a few moments, Android Studio should display a message in the Sync tab that it was successful:
6. Choose Build > Make Project. This should rebuild everything so that Android Studio can find FirstFragmentDirections.
Troubleshooting: If the sync was not successful, confirm that you added the correct lines to the correct Gradle file. If there are still problems, check the developer's guide about Safe Args for an updated nav_version or other changes.
1. In the navigation graph, click on FirstFragment, and look at the Attributes panel to the right. (If the panel isn't showing, click on the vertical Attributes label to the right.)
2. In the Actions section, it shows what action will happen for navigation, namely going to SecondFragment.
3. Click on SecondFragment, and look at the Attributes panel.
The Arguments section shows Nothing to show.
4. Click on the + in the Arguments section.
5. In the Add Argument dialog, enter myArg for the name and set the type to Integer, then click the Add button.
The Next/Random button was set up by Android Studio to go from the first fragment to the second, but it doesn't send any information. In this step you'll change it to send a number for the current count. You will get the current count from the text view that displays it, and pass that to the second fragment.
1. Open FirstFragment.java (app > java > com.example.myfirstapp > FirstFragment)
Find the method onViewCreated() and notice the code that sets up the click listener to go from the first fragment to the second.
Replace the code in that click listener with a line to find the count text view, textview_first.
int currentCount = Integer.parseInt(showCountTextView.getText().toString());
Create an action with currentCount as the argument to actionFirstFragmentToSecondFragment().
FirstFragmentDirections.ActionFirstFragmentToSecondFragment action = FirstFragmentDirections.actionFirstFragmentToSecondFragment(currentCount);
Add a line to find the nav controller and navigate with the action you created.
NavHostFragment.findNavController(FirstFragment.this).navigate(action);
Here is the whole method, including the code you added earlier:
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.random_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int currentCount = Integer.parseInt(showCountTextView.getText().toString());
FirstFragmentDirections.ActionFirstFragmentToSecondFragment action = FirstFragmentDirections.actionFirstFragmentToSecondFragment(currentCount);
NavHostFragment.findNavController(FirstFragment.this).navigate(action);
}
});
view.findViewById(R.id.toast_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast myToast = Toast.makeText(getActivity(), "Hello toast!", Toast.LENGTH_SHORT);
myToast.show();
}
});
view.findViewById(R.id.count_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
countMe(view);
}
});
}
Run your app. Click the Count button a few times. Now when you press the Random button, the second screen shows the correct string in the header, but still no count or random number, because you need to write some code to do that.
You have written the code to send the current count to the second fragment. The next step is to add code to SecondFragment.java to retrieve and use the current count.
1. In the onViewCreated() method below the line that starts with super, add code to get the current count, get the string and format it with the count, and then set it for textview_header.
Integer count = SecondFragmentArgs.fromBundle(getArguments()).getMyArg();
String countText = getString(R.string.random_heading, count);
TextView headerView = view.getRootView().findViewById(R.id.textview_header);
headerView.setText(countText);
2. Get a random number between 0 and the count.
Random random = new java.util.Random();
Integer randomNumber = 0;
if (count > 0) {
randomNumber = random.nextInt(count + 1);
}
3. Add code to convert that number into a string and set it as the text for textview_random.
TextView randomView = view.getRootView().findViewById(R.id.textview_random);
randomView.setText(randomNumber.toString());
4. Run the app. Press the Count button a few times, then press the Random button. Does the app display a random number in the new activity?