Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main into Compose-latest #965

Merged
merged 4 commits into from
Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions JetNews/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,9 @@ that scrolls vertically and horizontally.
See how to:

* Use `Row`s and `Column`s to arrange the contents of the UI
* Add an `AppBar`
* Use `MaterialTypography` and opacity to style the text
* Use `Shape` to round the corners of the images
* Use elevation to make the `Card`s stand out from the background
* Add a top app bar that elevates as the user scrolls
* Use Material's `Typography` and `ColorScheme` to style the text
* Use tonal elevation to make the `Card`s stand out from the background

[4]: app/src/main/java/com/example/jetnews/ui/home

Expand All @@ -53,7 +52,7 @@ See how to:
Package [`com.example.jetnews.ui.article`][5]

This screen dives into the Text API, showing how to use different fonts than the ones defined in
[`Typograhy`][6]. It also adds a bottom appbar, with custom actions.
[`Typography`][6]. It also adds a bottom app bar, with custom actions.

[5]: app/src/main/java/com/example/jetnews/ui/article
[6]: app/src/main/java/com/example/jetnews/ui/theme/Type.kt
Expand Down
43 changes: 29 additions & 14 deletions JetNews/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -97,17 +97,30 @@ dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.android)

implementation(libs.androidx.compose.foundation.layout)
implementation(libs.androidx.compose.material)
implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.compose.materialWindow)
implementation(libs.androidx.compose.animation)
implementation(libs.androidx.compose.ui.tooling.preview)
debugImplementation(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.compose.runtime.livedata)

implementation(libs.accompanist.swiperefresh)
implementation(libs.accompanist.systemuicontroller)
// TODO: Replace when all samples use the same Material3 & Compose version
implementation("androidx.compose.animation:animation:1.3.0-beta01")
implementation("androidx.compose.foundation:foundation-layout:1.3.0-beta01")
implementation("androidx.compose.material:material-icons-extended:1.3.0-beta01")
implementation("androidx.compose.material3:material3:1.0.0-beta01")
implementation("androidx.compose.material3:material3-window-size-class:1.0.0-beta01")
implementation("androidx.compose.runtime:runtime-livedata:1.3.0-beta01")
implementation("androidx.compose.ui:ui-tooling-preview:1.3.0-beta01")
debugImplementation("androidx.compose.ui:ui-test-manifest:1.3.0-beta01")
debugImplementation("androidx.compose.ui:ui-tooling:1.3.0-beta01")
// implementation(libs.androidx.compose.animation)
// implementation(libs.androidx.compose.foundation.layout)
// implementation(libs.androidx.compose.material.iconsExtended)
// implementation(libs.androidx.compose.material3)
// implementation(libs.androidx.compose.materialWindow)
// implementation(libs.androidx.compose.runtime.livedata)
// implementation(libs.androidx.compose.ui.tooling.preview)
// debugImplementation(libs.androidx.compose.ui.test.manifest)
// debugImplementation(libs.androidx.compose.ui.tooling)

implementation("com.google.accompanist:accompanist-swiperefresh:0.26.1-alpha")
implementation("com.google.accompanist:accompanist-systemuicontroller:0.26.1-alpha")
// implementation(libs.accompanist.swiperefresh)
// implementation(libs.accompanist.systemuicontroller)

implementation(libs.androidx.appcompat)
implementation(libs.androidx.activity.ktx)
Expand All @@ -121,8 +134,8 @@ dependencies {

implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.window)
debugImplementation(libs.androidx.compose.ui.test.manifest)

implementation(libs.google.android.material)

androidTestImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.core)
Expand All @@ -134,7 +147,9 @@ dependencies {
androidTestImplementation(libs.androidx.compose.ui.test)
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
// Robolectric dependencies
testImplementation(libs.androidx.compose.ui.test.junit4)
// TODO: Replace when all samples use the same Material3 & Compose version
implementation("androidx.compose.ui:ui-test-junit4:1.3.0-beta01")
// testImplementation(libs.androidx.compose.ui.test.junit4)
testImplementation(libs.robolectric)
}

Expand Down
138 changes: 37 additions & 101 deletions JetNews/app/src/main/java/com/example/jetnews/ui/AppDrawer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,30 @@
package com.example.jetnews.ui

import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.ListAlt
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.NavigationDrawerItemDefaults
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.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.jetnews.R
import com.example.jetnews.ui.components.JetnewsIcon
import com.example.jetnews.ui.components.NavigationIcon
import com.example.jetnews.ui.theme.JetnewsTheme

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppDrawer(
currentRoute: String,
Expand All @@ -57,110 +49,54 @@ fun AppDrawer(
closeDrawer: () -> Unit,
modifier: Modifier = Modifier
) {
Column(modifier = modifier.fillMaxSize()) {
JetNewsLogo(Modifier.padding(16.dp))
Divider(color = MaterialTheme.colors.onSurface.copy(alpha = .2f))
DrawerButton(
icon = Icons.Filled.Home,
label = stringResource(id = R.string.home_title),
isSelected = currentRoute == JetnewsDestinations.HOME_ROUTE,
action = {
navigateToHome()
closeDrawer()
}
ModalDrawerSheet(modifier) {
JetNewsLogo(
modifier = Modifier.padding(horizontal = 28.dp, vertical = 24.dp)
)

DrawerButton(
icon = Icons.Filled.ListAlt,
label = stringResource(id = R.string.interests_title),
isSelected = currentRoute == JetnewsDestinations.INTERESTS_ROUTE,
action = {
navigateToInterests()
closeDrawer()
}
NavigationDrawerItem(
label = { Text(stringResource(id = R.string.home_title)) },
icon = { Icon(Icons.Filled.Home, null) },
selected = currentRoute == JetnewsDestinations.HOME_ROUTE,
onClick = { navigateToHome(); closeDrawer() },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
NavigationDrawerItem(
label = { Text(stringResource(id = R.string.interests_title)) },
icon = { Icon(Icons.Filled.ListAlt, null) },
selected = currentRoute == JetnewsDestinations.INTERESTS_ROUTE,
onClick = { navigateToInterests(); closeDrawer() },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
}
}

@Composable
private fun JetNewsLogo(modifier: Modifier = Modifier) {
Row(modifier = modifier) {
JetnewsIcon()
Icon(
painterResource(R.drawable.ic_jetnews_logo),
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
Spacer(Modifier.width(8.dp))
Image(
Icon(
painter = painterResource(R.drawable.ic_jetnews_wordmark),
contentDescription = stringResource(R.string.app_name),
colorFilter = ColorFilter.tint(MaterialTheme.colors.onSurface)
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}

@Composable
private fun DrawerButton(
icon: ImageVector,
label: String,
isSelected: Boolean,
action: () -> Unit,
modifier: Modifier = Modifier
) {
val colors = MaterialTheme.colors
val textIconColor = if (isSelected) {
colors.primary
} else {
colors.onSurface.copy(alpha = 0.6f)
}
val backgroundColor = if (isSelected) {
colors.primary.copy(alpha = 0.12f)
} else {
Color.Transparent
}

val surfaceModifier = modifier
.padding(start = 8.dp, top = 8.dp, end = 8.dp)
.fillMaxWidth()
Surface(
modifier = surfaceModifier,
color = backgroundColor,
shape = MaterialTheme.shapes.small
) {
TextButton(
onClick = action,
modifier = Modifier.fillMaxWidth()
) {
Row(
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
NavigationIcon(
icon = icon,
isSelected = isSelected,
contentDescription = null, // decorative
tintColor = textIconColor
)
Spacer(Modifier.width(16.dp))
Text(
text = label,
style = MaterialTheme.typography.body2,
color = textIconColor
)
}
}
}
}

@Preview("Drawer contents")
@Preview("Drawer contents (dark)", uiMode = UI_MODE_NIGHT_YES)
@Composable
fun PreviewAppDrawer() {
JetnewsTheme {
Surface {
AppDrawer(
currentRoute = JetnewsDestinations.HOME_ROUTE,
navigateToHome = {},
navigateToInterests = {},
closeDrawer = { }
)
}
AppDrawer(
currentRoute = JetnewsDestinations.HOME_ROUTE,
navigateToHome = {},
navigateToInterests = {},
closeDrawer = { }
)
}
}
52 changes: 15 additions & 37 deletions JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,48 +21,34 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.add
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material.DrawerState
import androidx.compose.material.DrawerValue
import androidx.compose.material.MaterialTheme
import androidx.compose.material.ModalDrawer
import androidx.compose.material.rememberDrawerState
import androidx.compose.material3.DrawerState
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.rememberDrawerState
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.example.jetnews.data.AppContainer
import com.example.jetnews.ui.components.AppNavRail
import com.example.jetnews.ui.theme.JetnewsTheme
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun JetnewsApp(
appContainer: AppContainer,
widthSizeClass: WindowWidthSizeClass
) {
JetnewsTheme {
val systemUiController = rememberSystemUiController()
val darkIcons = MaterialTheme.colors.isLight
SideEffect {
systemUiController.setSystemBarsColor(Color.Transparent, darkIcons = darkIcons)
}

val navController = rememberNavController()
val navigationActions = remember(navController) {
JetnewsNavigationActions(navController)
Expand All @@ -77,32 +63,20 @@ fun JetnewsApp(
val isExpandedScreen = widthSizeClass == WindowWidthSizeClass.Expanded
val sizeAwareDrawerState = rememberSizeAwareDrawerState(isExpandedScreen)

ModalDrawer(
ModalNavigationDrawer(
drawerContent = {
AppDrawer(
currentRoute = currentRoute,
navigateToHome = navigationActions.navigateToHome,
navigateToInterests = navigationActions.navigateToInterests,
closeDrawer = { coroutineScope.launch { sizeAwareDrawerState.close() } },
modifier = Modifier
.statusBarsPadding()
.navigationBarsPadding()
closeDrawer = { coroutineScope.launch { sizeAwareDrawerState.close() } }
)
},
drawerState = sizeAwareDrawerState,
// Only enable opening the drawer via gestures if the screen is not expanded
gesturesEnabled = !isExpandedScreen
) {
Row(
Modifier
.fillMaxSize()
.statusBarsPadding()
.windowInsetsPadding(
WindowInsets
.navigationBars
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top)
)
) {
Row {
if (isExpandedScreen) {
AppNavRail(
currentRoute = currentRoute,
Expand All @@ -124,6 +98,7 @@ fun JetnewsApp(
/**
* Determine the drawer state to pass to the modal drawer.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun rememberSizeAwareDrawerState(isExpandedScreen: Boolean): DrawerState {
val drawerState = rememberDrawerState(DrawerValue.Closed)
Expand All @@ -144,8 +119,11 @@ private fun rememberSizeAwareDrawerState(isExpandedScreen: Boolean): DrawerState
* Determine the content padding to apply to the different screens of the app
*/
@Composable
fun rememberContentPaddingForScreen(additionalTop: Dp = 0.dp) =
fun rememberContentPaddingForScreen(
additionalTop: Dp = 0.dp,
excludeTop: Boolean = false
) =
WindowInsets.systemBars
.only(WindowInsetsSides.Bottom)
.only(if (excludeTop) WindowInsetsSides.Bottom else WindowInsetsSides.Vertical)
.add(WindowInsets(top = additionalTop))
.asPaddingValues()
Loading