--------------------- | Main Screen | | | | [Go to Second] | --------------------- --------------------- | Second Screen | | | | [Back to Main] | ---------------------
Navigation component setup in Android Kotlin - Mini App: Build & Ship
package com.example.navigationdemo import android.os.Bundle import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // TODO: Setup NavHostFragment in activity_main.xml } } // TODO: Create MainFragment.kt and SecondFragment.kt with basic layouts and buttons
package com.example.navigationdemo import android.os.Bundle import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } } // MainFragment.kt package com.example.navigationdemo import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import com.example.navigationdemo.databinding.FragmentMainBinding class MainFragment : Fragment() { private var _binding: FragmentMainBinding? = null private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = FragmentMainBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.buttonGoSecond.setOnClickListener { findNavController().navigate(R.id.action_mainFragment_to_secondFragment) } } override fun onDestroyView() { super.onDestroyView() _binding = null } } // SecondFragment.kt package com.example.navigationdemo import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import com.example.navigationdemo.databinding.FragmentSecondBinding class SecondFragment : Fragment() { private var _binding: FragmentSecondBinding? = null private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = FragmentSecondBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.buttonBackMain.setOnClickListener { findNavController().navigate(R.id.action_secondFragment_to_mainFragment) } } override fun onDestroyView() { super.onDestroyView() _binding = null } } // activity_main.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" tools:context=".MainActivity"> <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> // nav_graph.xml <?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph" app:startDestination="@id/mainFragment"> <fragment android:id="@+id/mainFragment" android:name="com.example.navigationdemo.MainFragment" android:label="Main Screen"> <action android:id="@+id/action_mainFragment_to_secondFragment" app:destination="@id/secondFragment" /> </fragment> <fragment android:id="@+id/secondFragment" android:name="com.example.navigationdemo.SecondFragment" android:label="Second Screen"> <action android:id="@+id/action_secondFragment_to_mainFragment" app:destination="@id/mainFragment" /> </fragment> </navigation> // fragment_main.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <Button android:id="@+id/buttonGoSecond" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Go to Second" /> </FrameLayout> // fragment_second.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <Button android:id="@+id/buttonBackMain" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Back to Main" /> </FrameLayout>
This solution sets up the Android Navigation Component with two fragments: MainFragment and SecondFragment.
The activity_main.xml contains a NavHostFragment which hosts the navigation graph defined in nav_graph.xml. This graph defines the two fragments and the actions to navigate between them.
Each fragment has a simple layout with a button. In MainFragment, the button navigates to SecondFragment using findNavController().navigate(). In SecondFragment, the button navigates back to MainFragment.
View binding is used for safe and easy access to views.
This setup follows Android best practices for navigation and keeps UI and navigation logic clean and simple.
--------------------- | Main Screen | | | | [Go to Second] | --------------------- User taps 'Go to Second' button --------------------- | Second Screen | | | | [Back to Main] | --------------------- User taps 'Back to Main' button Back to Main Screen
Practice
Solution
Step 1: Understand Navigation component role
The Navigation component is designed to simplify moving between screens in an app.Step 2: Compare with other options
Database, styling, and network are unrelated to navigation tasks.Final Answer:
To manage screen transitions and navigation paths easily -> Option AQuick Check:
Navigation component = screen transitions [OK]
- Confusing navigation with database handling
- Thinking it styles UI elements
- Assuming it manages network calls
Solution
Step 1: Identify the navigation graph element
The navigation graph XML uses the <navigation> root element to define screens and paths.Step 2: Check other elements
<navHost> and <navController> are not XML tags; <navGraph> is incorrect.Final Answer:
<navigation> -> Option BQuick Check:
Navigation graph XML uses <navigation> [OK]
- Using <navGraph> which is invalid
- Confusing NavHostFragment with XML tag
- Mistaking NavController for XML element
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nav_graph"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.example.HomeFragment" />
<fragment
android:id="@+id/detailFragment"
android:name="com.example.DetailFragment" />
</navigation>Solution
Step 1: Identify startDestination attribute
The navigation graph sets startDestination="@id/homeFragment", so HomeFragment is the first screen.Step 2: Confirm fragment IDs
HomeFragment and DetailFragment are defined; startDestination points to HomeFragment.Final Answer:
HomeFragment -> Option CQuick Check:
startDestination = HomeFragment [OK]
- Choosing DetailFragment by mistake
- Assuming no screen shows without NavHostFragment
- Confusing fragment IDs
findNavController().navigate(R.id.action_home_to_detail)What is the most likely cause?
Solution
Step 1: Check NavHostFragment presence
Without NavHostFragment in layout, navigation cannot work and causes crash.Step 2: Verify action ID and context
If action ID is wrong or findNavController() is called outside proper context, app crashes.Final Answer:
All of the above -> Option AQuick Check:
Missing NavHost, wrong ID, or wrong context cause crash [OK]
- Ignoring NavHostFragment setup
- Using wrong action ID
- Calling findNavController() in wrong place
Solution
Step 1: Define fragments and action in navigation graph
Both fragments and the action connecting them must be declared in nav_graph.xml.Step 2: Add NavHostFragment in activity layout
NavHostFragment hosts the navigation and displays fragments.Step 3: Use findNavController().navigate(actionId) in code
This triggers navigation along the defined action.Final Answer:
Define fragments and action in nav_graph.xml, add NavHostFragment in layout, call findNavController().navigate(actionId) -> Option DQuick Check:
Fragments + action + NavHost + navigate() = correct setup [OK]
- Skipping NavHostFragment in layout
- Not defining action in nav_graph.xml
- Calling navigate() without proper setup
Ready to prove it?
Pass the test and this pattern moves unknown
