Please conduct the following tasks alone. For implementation details you can refer to the lecture slides or the Android developer website. Please do not hesitate to ask me or the tutor if you have any questions.
assignmentCode/assignment3 into the assignment3 folder of your Git repository. The
starter is the solution of assignment 2, restructured into packages, plus a NavHost with two screens.NavHostController, NavHost) to navigate between the home screen and a
search screen.ui/home/HomeScreen.kt, already implemented): shows a button with the test tag openSearchButton
above the list of saved movies. The list is empty on app start.ui/search/SearchScreen.kt): a TextField (test tag textField), a Button (test tag
searchButton) and a MovieList with the search results.TODOs of the starter:SearchScreen: when the search button is clicked, show all movies from MovieData.bondMovies whose title
contains the entered text (ignore case). Example: the search string "uss" shows only "From Russia with
Love". Results of the previous search must disappear.MainActivity: show the SearchScreen for the search route. When a result is clicked, add the movie to
savedMovies and navigate back to the home screen. Saved movies are shown in the order they were clicked
(first clicked on top).MainActivity: when a saved movie is clicked on the home screen, remove it from savedMovies.app/src/main/java/de/hdmstuttgart/movietracker/
├── MainActivity.kt Routes, NavHost and the hoisted state "savedMovies" <- TODO
├── model/Movie.kt data class Movie(title, year, actor)
├── model/MovieData.kt the five Bond movies as static data source
├── ui/home/HomeScreen.kt button + MovieList of the saved movies
├── ui/search/SearchScreen.kt TextField, Button, MovieList of the search results <- TODO
└── ui/composables/ MovieList and MovieItem from assignment 2
MovieTrackerNavHost with remember { mutableStateListOf<Movie>() } and
passed down to the screens as parameter (state hoisting). This way the list survives when you navigate between the
two screens.navController.navigate(Routes.SEARCH) opens the search screen, navController.popBackStack() closes it again.NavController.On app start:
With one saved movie:
With multiple saved movies:
When opened:
With search results:
The test is part of the starter (Assignment3Test.kt). It saves two movies, checks their order on the home screen
and removes the first one again:
package de.hdmstuttgart.movietracker
import androidx.compose.ui.test.assertTextContains
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import org.junit.Rule
import org.junit.Test
class Assignment3Test {
@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()
@Test
fun myTest() {
// Search "Gold", save the only result and check the home screen
composeTestRule.onNodeWithTag("openSearchButton").performClick()
composeTestRule.onNodeWithTag("textField").performTextInput("Gold")
composeTestRule.onNodeWithTag("searchButton").performClick()
composeTestRule.onAllNodesWithTag("movieItem")[0].assertTextContains("Goldfinger")
composeTestRule.onAllNodesWithTag("movieItem")[0].performClick()
composeTestRule.onAllNodesWithTag("movieItem")[0].assertTextContains("Goldfinger")
// Save a second movie, it has to appear below the first one
composeTestRule.onNodeWithTag("openSearchButton").performClick()
composeTestRule.onNodeWithTag("textField").performTextInput("From Russia with Love")
composeTestRule.onNodeWithTag("searchButton").performClick()
composeTestRule.onAllNodesWithTag("movieItem")[0].performClick()
composeTestRule.onAllNodesWithTag("movieItem")[0].assertTextContains("Goldfinger")
composeTestRule.onAllNodesWithTag("movieItem")[1].assertTextContains("From Russia with Love")
// Clicking a saved movie removes it
composeTestRule.onAllNodesWithTag("movieItem")[0].performClick()
composeTestRule.onAllNodesWithTag("movieItem")[0].assertTextContains("From Russia with Love")
}
}
The Navigation component is already part of the starter. These are the relevant lines, in case you want to add it to your own project later:
gradle/libs.versions.toml:
[versions]
navigationCompose = "2.9.8"
[libraries]
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
Module app/build.gradle.kts:
dependencies {
implementation(libs.androidx.navigation.compose)
// ...
}
assignment3 folder of your Git repository (assignment3/app/src/main/...).Assignment3Test.kt is replaced by the reference version and executed on a fresh emulator.