diff --git a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/ClearRippleTheme.kt b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/ClearRippleTheme.kt
new file mode 100644
index 000000000..bc7d10bf8
--- /dev/null
+++ b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/ClearRippleTheme.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.samples.apps.nowinandroid.core.ui
+
+import androidx.compose.material.ripple.RippleAlpha
+import androidx.compose.material.ripple.RippleTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+
+object ClearRippleTheme : RippleTheme {
+
+ @Composable
+ override fun defaultColor(): Color = Color.Transparent
+
+ @Composable
+ override fun rippleAlpha() = RippleAlpha(
+ draggedAlpha = 0.0f,
+ focusedAlpha = 0.0f,
+ hoveredAlpha = 0.0f,
+ pressedAlpha = 0.0f,
+ )
+}
diff --git a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NiaScreens.kt b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NiaScreens.kt
deleted file mode 100644
index a3553ad65..000000000
--- a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NiaScreens.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.samples.apps.nowinandroid.core.ui
-
-import androidx.annotation.StringRes
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.MoreVert
-import androidx.compose.material.icons.filled.Search
-import androidx.compose.material.ripple.RippleAlpha
-import androidx.compose.material.ripple.RippleTheme
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
-
-@Composable
-fun NiaToolbar(
- modifier: Modifier = Modifier,
- @StringRes titleRes: Int,
- onSearchClick: () -> Unit = {},
- onMenuClick: () -> Unit = {},
-) {
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically,
- modifier = modifier.fillMaxWidth()
- ) {
- IconButton(onClick = { onSearchClick() }) {
- Icon(
- imageVector = Icons.Filled.Search,
- contentDescription = null
- )
- }
- Text(
- text = stringResource(id = titleRes),
- style = MaterialTheme.typography.titleLarge,
- fontWeight = FontWeight.Bold
- )
- IconButton(onClick = { onMenuClick() }) {
- Icon(
- imageVector = Icons.Filled.MoreVert,
- contentDescription = null
- )
- }
- }
-}
-
-object ClearRippleTheme : RippleTheme {
-
- @Composable
- override fun defaultColor(): Color = Color.Transparent
-
- @Composable
- override fun rippleAlpha() = RippleAlpha(
- draggedAlpha = 0.0f,
- focusedAlpha = 0.0f,
- hoveredAlpha = 0.0f,
- pressedAlpha = 0.0f,
- )
-}
diff --git a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/TopAppBar.kt b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/TopAppBar.kt
new file mode 100644
index 000000000..5a0caa2d2
--- /dev/null
+++ b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/TopAppBar.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.samples.apps.nowinandroid.core.ui.component
+
+import androidx.annotation.StringRes
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.MoreVert
+import androidx.compose.material.icons.filled.Search
+import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import com.google.samples.apps.nowinandroid.core.ui.R
+
+@Composable
+fun NiaTopAppBar(
+ @StringRes titleRes: Int,
+ navigationIcon: ImageVector,
+ navigationIconContentDescription: String?,
+ actionIcon: ImageVector,
+ actionIconContentDescription: String?,
+ modifier: Modifier = Modifier,
+ onNavigationClick: () -> Unit = {},
+ onActionClick: () -> Unit = {}
+) {
+ CenterAlignedTopAppBar(
+ title = { Text(text = stringResource(id = titleRes)) },
+ navigationIcon = {
+ IconButton(onClick = onNavigationClick) {
+ Icon(
+ imageVector = navigationIcon,
+ contentDescription = navigationIconContentDescription,
+ tint = MaterialTheme.colorScheme.onSurface
+ )
+ }
+ },
+ actions = {
+ IconButton(onClick = onActionClick) {
+ Icon(
+ imageVector = actionIcon,
+ contentDescription = actionIconContentDescription,
+ tint = MaterialTheme.colorScheme.onSurface
+ )
+ }
+ },
+ modifier = modifier
+ )
+}
+
+@Preview("Top App Bar")
+@Composable
+fun NiaTopAppBarPreview() {
+ NiaTopAppBar(
+ titleRes = R.string.top_app_bar_preview_title,
+ navigationIcon = Icons.Default.Search,
+ navigationIconContentDescription = "Navigation icon",
+ actionIcon = Icons.Default.MoreVert,
+ actionIconContentDescription = "Action icon"
+ )
+}
diff --git a/core-ui/src/main/res/values/strings.xml b/core-ui/src/main/res/values/strings.xml
index 46f144829..78412bb0a 100644
--- a/core-ui/src/main/res/values/strings.xml
+++ b/core-ui/src/main/res/values/strings.xml
@@ -19,4 +19,6 @@
Back
Open Resource Link
+
+ Title
diff --git a/feature-following/src/main/java/com/google/samples/apps/nowinandroid/feature/following/FollowingScreen.kt b/feature-following/src/main/java/com/google/samples/apps/nowinandroid/feature/following/FollowingScreen.kt
index 4ea98253b..a7df67fb3 100644
--- a/feature-following/src/main/java/com/google/samples/apps/nowinandroid/feature/following/FollowingScreen.kt
+++ b/feature-following/src/main/java/com/google/samples/apps/nowinandroid/feature/following/FollowingScreen.kt
@@ -18,6 +18,9 @@ package com.google.samples.apps.nowinandroid.feature.following
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.MoreVert
+import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
@@ -28,9 +31,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.google.samples.apps.nowinandroid.core.ui.LoadingWheel
-import com.google.samples.apps.nowinandroid.core.ui.NiaToolbar
import com.google.samples.apps.nowinandroid.core.ui.component.NiaTab
import com.google.samples.apps.nowinandroid.core.ui.component.NiaTabRow
+import com.google.samples.apps.nowinandroid.core.ui.component.NiaTopAppBar
@Composable
fun InterestsRoute(
@@ -69,7 +72,17 @@ fun FollowingScreen(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
- NiaToolbar(titleRes = R.string.interests)
+ NiaTopAppBar(
+ titleRes = R.string.interests,
+ navigationIcon = Icons.Filled.Search,
+ navigationIconContentDescription = stringResource(
+ id = R.string.top_app_bar_navigation_button_content_desc
+ ),
+ actionIcon = Icons.Filled.MoreVert,
+ actionIconContentDescription = stringResource(
+ id = R.string.top_app_bar_navigation_button_content_desc
+ )
+ )
when (uiState) {
FollowingUiState.Loading ->
LoadingWheel(
diff --git a/feature-following/src/main/res/values/strings.xml b/feature-following/src/main/res/values/strings.xml
index 7b0d5ef1a..4ba1d1ecd 100644
--- a/feature-following/src/main/res/values/strings.xml
+++ b/feature-following/src/main/res/values/strings.xml
@@ -21,4 +21,6 @@
"No available data"
Follow interest button
Unfollow interest button
+ Menu
+ Search
diff --git a/feature-foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt b/feature-foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt
index a98ddfebc..a9db3ab1f 100644
--- a/feature-foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt
+++ b/feature-foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt
@@ -23,9 +23,13 @@ import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.assertIsOff
import androidx.compose.ui.test.assertIsOn
+import androidx.compose.ui.test.hasScrollToNodeAction
+import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import androidx.compose.ui.test.onFirst
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performScrollToNode
import com.google.samples.apps.nowinandroid.core.model.data.Author
import com.google.samples.apps.nowinandroid.core.model.data.FollowableAuthor
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
@@ -37,6 +41,12 @@ class ForYouScreenTest {
@get:Rule
val composeTestRule = createAndroidComposeRule()
+ private val doneButtonMatcher by lazy {
+ hasText(
+ composeTestRule.activity.resources.getString(R.string.done)
+ )
+ }
+
@Test
fun circularProgressIndicator_whenScreenIsLoading_exists() {
composeTestRule.setContent {
@@ -142,8 +152,14 @@ class ForYouScreenTest {
.assertIsDisplayed()
.assertHasClickAction()
+ // Scroll until the Done button is visible
+ composeTestRule
+ .onAllNodes(hasScrollToNodeAction())
+ .onFirst()
+ .performScrollToNode(doneButtonMatcher)
+
composeTestRule
- .onNodeWithText(composeTestRule.activity.resources.getString(R.string.done))
+ .onNode(doneButtonMatcher)
.assertIsDisplayed()
.assertIsNotEnabled()
.assertHasClickAction()
@@ -241,8 +257,14 @@ class ForYouScreenTest {
.assertIsOff()
.assertHasClickAction()
+ // Scroll until the Done button is visible
composeTestRule
- .onNodeWithText(composeTestRule.activity.resources.getString(R.string.done))
+ .onAllNodes(hasScrollToNodeAction())
+ .onFirst()
+ .performScrollToNode(doneButtonMatcher)
+
+ composeTestRule
+ .onNode(doneButtonMatcher)
.assertIsDisplayed()
.assertIsEnabled()
.assertHasClickAction()
@@ -346,8 +368,14 @@ class ForYouScreenTest {
.assertIsOff()
.assertHasClickAction()
+ // Scroll until the Done button is visible
+ composeTestRule
+ .onAllNodes(hasScrollToNodeAction())
+ .onFirst()
+ .performScrollToNode(doneButtonMatcher)
+
composeTestRule
- .onNodeWithText(composeTestRule.activity.resources.getString(R.string.done))
+ .onNode(doneButtonMatcher)
.assertIsDisplayed()
.assertIsEnabled()
.assertHasClickAction()
diff --git a/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt b/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt
index 95affbbf6..6a44c2b79 100644
--- a/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt
+++ b/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt
@@ -33,6 +33,9 @@ import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Search
+import androidx.compose.material.icons.outlined.AccountCircle
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -64,6 +67,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.ui.LoadingWheel
import com.google.samples.apps.nowinandroid.core.ui.NewsResourceCardExpanded
import com.google.samples.apps.nowinandroid.core.ui.component.NiaToggleButton
+import com.google.samples.apps.nowinandroid.core.ui.component.NiaTopAppBar
import com.google.samples.apps.nowinandroid.core.ui.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.ui.theme.NiaTypography
import com.google.samples.apps.nowinandroid.feature.foryou.ForYouFeedUiState.PopulatedFeed
@@ -99,6 +103,19 @@ fun ForYouScreen(
LazyColumn(
modifier = modifier.fillMaxSize()
) {
+ item {
+ NiaTopAppBar(
+ titleRes = R.string.top_app_bar_title,
+ navigationIcon = Icons.Filled.Search,
+ navigationIconContentDescription = stringResource(
+ id = R.string.top_app_bar_navigation_button_content_desc
+ ),
+ actionIcon = Icons.Outlined.AccountCircle,
+ actionIconContentDescription = stringResource(
+ id = R.string.top_app_bar_navigation_button_content_desc
+ )
+ )
+ }
when (uiState) {
is ForYouFeedUiState.Loading -> {
item {
diff --git a/feature-foryou/src/main/res/values/strings.xml b/feature-foryou/src/main/res/values/strings.xml
index be136b32d..48c40620d 100644
--- a/feature-foryou/src/main/res/values/strings.xml
+++ b/feature-foryou/src/main/res/values/strings.xml
@@ -22,6 +22,9 @@
Navigate up
What are you interested in?
Updates from topics you follow will appear here. Follow some things to get started.
+ Now in Android
+ My account
+ Search
You are following