diff --git a/JetNews/app/src/androidTest/java/com/example/jetnews/JetnewsUiTest.kt b/JetNews/app/src/androidTest/java/com/example/jetnews/JetnewsUiTest.kt index 8bc8f887fd..9d55fd0685 100644 --- a/JetNews/app/src/androidTest/java/com/example/jetnews/JetnewsUiTest.kt +++ b/JetNews/app/src/androidTest/java/com/example/jetnews/JetnewsUiTest.kt @@ -17,7 +17,6 @@ package com.example.jetnews import androidx.test.filters.MediumTest -import androidx.test.filters.Suppress import androidx.ui.test.assertIsDisplayed import androidx.ui.test.createComposeRule import androidx.ui.test.doClick @@ -41,19 +40,11 @@ class JetnewsUiTest { } @Test - fun avoidemptyTestSuite() { - // this is an empty test to make gradle pass the suite - // TODO(b/150728822): remove this after test runner is fixed - } - - @Test - @Suppress // TODO(b/150728822): re-enabled after test runner is fixed fun app_launches() { findByText("Jetnews").assertIsDisplayed() } @Test - @Suppress // TODO(b/150728822): re-enabled after test runner is fixed fun app_opensArticle() { findAllBySubstring("Manuel Vivo").first().doClick() findAllBySubstring("July 30 • 3 min read").first().assertIsDisplayed() diff --git a/JetNews/app/src/androidTest/java/com/example/jetnews/TestHelper.kt b/JetNews/app/src/androidTest/java/com/example/jetnews/TestHelper.kt index 8c96830ee8..8fcc48b9a5 100644 --- a/JetNews/app/src/androidTest/java/com/example/jetnews/TestHelper.kt +++ b/JetNews/app/src/androidTest/java/com/example/jetnews/TestHelper.kt @@ -18,7 +18,7 @@ package com.example.jetnews import androidx.compose.Composable import androidx.ui.material.MaterialTheme -import androidx.ui.material.surface.Surface +import androidx.ui.material.Surface import androidx.ui.test.ComposeTestRule import androidx.ui.test.SemanticsNodeInteraction import androidx.ui.test.findAll diff --git a/JetNews/app/src/main/java/com/example/jetnews/model/Post.kt b/JetNews/app/src/main/java/com/example/jetnews/model/Post.kt index 3eef03cd1f..0af63bc697 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/model/Post.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/model/Post.kt @@ -16,7 +16,7 @@ package com.example.jetnews.model -import androidx.ui.graphics.Image +import androidx.ui.graphics.ImageAsset data class Post( val id: String, @@ -28,8 +28,8 @@ data class Post( val paragraphs: List = emptyList(), val imageId: Int, val imageThumbId: Int, - val image: Image? = null, - val imageThumb: Image? = null + val image: ImageAsset? = null, + val imageThumb: ImageAsset? = null ) data class Metadata( diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt index 3c930b8944..4430cbbeef 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt @@ -20,21 +20,24 @@ import androidx.annotation.DrawableRes import androidx.compose.Composable import androidx.ui.animation.Crossfade import androidx.ui.core.Modifier -import androidx.ui.core.Text +import androidx.ui.foundation.Image +import androidx.ui.foundation.Text import androidx.ui.foundation.shape.corner.RoundedCornerShape +import androidx.ui.graphics.ColorFilter import androidx.ui.layout.Arrangement import androidx.ui.layout.Column -import androidx.ui.layout.LayoutGravity -import androidx.ui.layout.LayoutHeight -import androidx.ui.layout.LayoutPadding -import androidx.ui.layout.LayoutSize -import androidx.ui.layout.LayoutWidth import androidx.ui.layout.Row import androidx.ui.layout.Spacer +import androidx.ui.layout.fillMaxSize +import androidx.ui.layout.fillMaxWidth +import androidx.ui.layout.padding +import androidx.ui.layout.preferredHeight +import androidx.ui.layout.preferredWidth import androidx.ui.material.Divider import androidx.ui.material.MaterialTheme +import androidx.ui.material.Surface import androidx.ui.material.TextButton -import androidx.ui.material.surface.Surface +import androidx.ui.res.vectorResource import androidx.ui.tooling.preview.Preview import androidx.ui.unit.dp import com.example.jetnews.R @@ -56,7 +59,7 @@ fun JetnewsApp() { @Composable private fun AppContent() { Crossfade(JetnewsStatus.currentScreen) { screen -> - Surface(color = MaterialTheme.colors().background) { + Surface(color = MaterialTheme.colors.background) { when (screen) { is Screen.Home -> HomeScreen() is Screen.Interests -> InterestsScreen() @@ -71,49 +74,61 @@ fun AppDrawer( currentScreen: Screen, closeDrawer: () -> Unit ) { - Column(modifier = LayoutSize.Fill) { - Spacer(LayoutHeight(24.dp)) - Row(modifier = LayoutPadding(16.dp)) { - VectorImage( - id = R.drawable.ic_jetnews_logo, - tint = MaterialTheme.colors().primary - ) - Spacer(LayoutWidth(8.dp)) - VectorImage( - id = R.drawable.ic_jetnews_wordmark, - tint = MaterialTheme.colors().onSurface - ) - } - Divider(color = MaterialTheme.colors().onSurface.copy(alpha = .2f)) + Column(modifier = Modifier.fillMaxSize()) { + Spacer(Modifier.preferredHeight(24.dp)) + JetNewsLogo(Modifier.padding(16.dp)) + Divider(color = MaterialTheme.colors.onSurface.copy(alpha = .2f)) DrawerButton( icon = R.drawable.ic_home, label = "Home", - isSelected = currentScreen == Screen.Home - ) { - navigateTo(Screen.Home) - closeDrawer() - } + isSelected = currentScreen == Screen.Home, + action = { + navigateTo(Screen.Home) + closeDrawer() + } + ) DrawerButton( icon = R.drawable.ic_interests, label = "Interests", - isSelected = currentScreen == Screen.Interests - ) { - navigateTo(Screen.Interests) - closeDrawer() - } + isSelected = currentScreen == Screen.Interests, + action = { + navigateTo(Screen.Interests) + closeDrawer() + } + ) + } +} + +@Composable +private fun JetNewsLogo(modifier: Modifier = Modifier.None) { + Row(modifier = modifier) { + Image( + asset = vectorResource(R.drawable.ic_jetnews_logo), + colorFilter = ColorFilter.tint(MaterialTheme.colors.primary) + ) + Spacer(Modifier.preferredWidth(8.dp)) + Image( + asset = vectorResource(R.drawable.ic_jetnews_wordmark), + colorFilter = ColorFilter.tint(MaterialTheme.colors.onSurface) + ) } } @Composable private fun DrawerButton( - modifier: Modifier = Modifier.None, @DrawableRes icon: Int, label: String, isSelected: Boolean, - action: () -> Unit + action: () -> Unit, + modifier: Modifier = Modifier.None ) { - val colors = MaterialTheme.colors() + val colors = MaterialTheme.colors + val imageAlpha = if (isSelected) { + 1f + } else { + 0.6f + } val textIconColor = if (isSelected) { colors.primary } else { @@ -125,28 +140,26 @@ private fun DrawerButton( colors.surface } - val surfaceModifier = modifier + - LayoutPadding(start = 8.dp, top = 8.dp, end = 8.dp, bottom = 0.dp) + - LayoutWidth.Fill + val surfaceModifier = modifier + .padding(start = 8.dp, top = 8.dp, end = 8.dp) + .fillMaxWidth() Surface( modifier = surfaceModifier, color = backgroundColor, shape = RoundedCornerShape(4.dp) ) { - TextButton(onClick = action, modifier = LayoutWidth.Fill) { - Row(arrangement = Arrangement.Start, modifier = LayoutWidth.Fill) { - VectorImage( - modifier = LayoutGravity.Center, - id = icon, - tint = textIconColor + TextButton(onClick = action, modifier = Modifier.fillMaxWidth()) { + Row(arrangement = Arrangement.Start, modifier = Modifier.fillMaxWidth()) { + Image( + asset = vectorResource(icon), + colorFilter = ColorFilter.tint(textIconColor), + alpha = imageAlpha ) - Spacer(LayoutWidth(16.dp)) + Spacer(Modifier.preferredWidth(16.dp)) Text( text = label, - style = (MaterialTheme.typography()).body2.copy( - color = textIconColor - ), - modifier = LayoutWidth.Fill + style = MaterialTheme.typography.body2.copy(color = textIconColor), + modifier = Modifier.fillMaxWidth() ) } } diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/PreviewUtils.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/PreviewUtils.kt index 8c4a3306e1..c5a968dcf4 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/PreviewUtils.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/PreviewUtils.kt @@ -19,8 +19,8 @@ package com.example.jetnews.ui import androidx.compose.Composable import androidx.ui.material.ColorPalette import androidx.ui.material.MaterialTheme +import androidx.ui.material.Surface import androidx.ui.material.Typography -import androidx.ui.material.surface.Surface @Composable internal fun ThemedPreview( diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/Vectors.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/Vectors.kt deleted file mode 100644 index bfa287a958..0000000000 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/Vectors.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 Google, Inc. - * - * 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 - * - * http://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.example.jetnews.ui - -import androidx.annotation.DrawableRes -import androidx.compose.Composable -import androidx.ui.core.Modifier -import androidx.ui.foundation.Clickable -import androidx.ui.graphics.Color -import androidx.ui.graphics.vector.DrawVector -import androidx.ui.layout.Container -import androidx.ui.layout.LayoutSize -import androidx.ui.material.ripple.Ripple -import androidx.ui.res.vectorResource - -@Composable -fun VectorImageButton(@DrawableRes id: Int, onClick: () -> Unit) { - Ripple(bounded = false) { - Clickable(onClick = onClick) { - VectorImage(id = id) - } - } -} - -@Composable -fun VectorImage( - modifier: Modifier = Modifier.None, - @DrawableRes id: Int, - tint: Color = Color.Transparent -) { - val vector = vectorResource(id) - Container( - modifier = modifier + LayoutSize(vector.defaultWidth, vector.defaultHeight) - ) { - DrawVector(vector, tint) - } -} diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt index ec3c1cc0cf..4ae6ac0805 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt @@ -22,21 +22,26 @@ import androidx.annotation.DrawableRes import androidx.compose.Composable import androidx.compose.state import androidx.ui.core.ContextAmbient -import androidx.ui.core.Text -import androidx.ui.foundation.Clickable -import androidx.ui.graphics.vector.DrawVector -import androidx.ui.layout.Container -import androidx.ui.layout.LayoutHeight -import androidx.ui.layout.LayoutPadding -import androidx.ui.layout.LayoutSize +import androidx.ui.core.Modifier +import androidx.ui.foundation.Box +import androidx.ui.foundation.Icon +import androidx.ui.foundation.Text +import androidx.ui.foundation.contentColor import androidx.ui.layout.Row +import androidx.ui.layout.Spacer +import androidx.ui.layout.fillMaxSize +import androidx.ui.layout.padding +import androidx.ui.layout.preferredHeight +import androidx.ui.layout.preferredSize import androidx.ui.material.AlertDialog +import androidx.ui.material.IconButton import androidx.ui.material.MaterialTheme import androidx.ui.material.Scaffold +import androidx.ui.material.Surface import androidx.ui.material.TextButton import androidx.ui.material.TopAppBar -import androidx.ui.material.ripple.Ripple -import androidx.ui.material.surface.Surface +import androidx.ui.material.icons.Icons +import androidx.ui.material.icons.filled.ArrowBack import androidx.ui.res.vectorResource import androidx.ui.tooling.preview.Preview import androidx.ui.unit.dp @@ -46,7 +51,6 @@ import com.example.jetnews.data.posts import com.example.jetnews.model.Post import com.example.jetnews.ui.Screen import com.example.jetnews.ui.ThemedPreview -import com.example.jetnews.ui.VectorImageButton import com.example.jetnews.ui.darkThemeColors import com.example.jetnews.ui.home.BookmarkButton import com.example.jetnews.ui.home.isFavorite @@ -61,9 +65,7 @@ fun ArticleScreen(postId: String) { val post = posts.find { it.id == postId } ?: return if (showDialog) { - FunctionalityNotAvailablePopup { - showDialog = false - } + FunctionalityNotAvailablePopup { showDialog = false } } Scaffold( @@ -72,18 +74,19 @@ fun ArticleScreen(postId: String) { title = { Text( text = "Published in: ${post.publication?.name}", - style = MaterialTheme.typography().subtitle2 + // FIXME(b/143626708): this contentColor() is a bug workaround + style = MaterialTheme.typography.subtitle2.copy(color = contentColor()) ) }, navigationIcon = { - VectorImageButton(R.drawable.ic_back) { - navigateTo(Screen.Home) + IconButton(onClick = { navigateTo(Screen.Home) }) { + Icon(Icons.Filled.ArrowBack) } } ) }, bodyContent = { modifier -> - PostContent(modifier = modifier, post = post) + PostContent(post, modifier) }, bottomAppBar = { BottomBar(post) { showDialog = true } @@ -95,22 +98,16 @@ fun ArticleScreen(postId: String) { private fun BottomBar(post: Post, onUnimplementedAction: () -> Unit) { val context = ContextAmbient.current Surface(elevation = 2.dp) { - Container(modifier = LayoutHeight(56.dp) + LayoutSize.Fill) { + Box(modifier = Modifier.preferredHeight(56.dp).fillMaxSize()) { Row { - BottomBarAction(R.drawable.ic_favorite) { - onUnimplementedAction() - } + BottomBarAction(R.drawable.ic_favorite) { onUnimplementedAction() } BookmarkButton( isBookmarked = isFavorite(postId = post.id), onBookmark = { toggleBookmark(postId = post.id) } ) - BottomBarAction(R.drawable.ic_share) { - sharePost(post, context) - } - Container(modifier = LayoutFlexible(1f)) { } // TODO: Any element works - BottomBarAction(R.drawable.ic_text_settings) { - onUnimplementedAction() - } + BottomBarAction(R.drawable.ic_share) { sharePost(post, context) } + Spacer(modifier = Modifier.weight(1f)) + BottomBarAction(R.drawable.ic_text_settings) { onUnimplementedAction() } } } } @@ -121,15 +118,8 @@ private fun BottomBarAction( @DrawableRes id: Int, onClick: () -> Unit ) { - Ripple( - bounded = false, - radius = 24.dp - ) { - Clickable(onClick = onClick) { - Container(modifier = LayoutPadding(12.dp) + LayoutSize(24.dp, 24.dp)) { - DrawVector(vectorResource(id)) - } - } + IconButton(onClick = onClick, modifier = Modifier.padding(12.dp).preferredSize(24.dp, 24.dp)) { + Icon(vectorResource(id)) } } @@ -140,13 +130,11 @@ private fun FunctionalityNotAvailablePopup(onDismiss: () -> Unit) { text = { Text( text = "Functionality not available \uD83D\uDE48", - style = MaterialTheme.typography().body2 + style = MaterialTheme.typography.body2 ) }, confirmButton = { - TextButton( - onClick = onDismiss - ) { + TextButton(onClick = onDismiss) { Text(text = "CLOSE") } } diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/article/PostContent.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/article/PostContent.kt index 0f1a1a98ab..587bc09005 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/article/PostContent.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/article/PostContent.kt @@ -17,32 +17,36 @@ package com.example.jetnews.ui.article import androidx.compose.Composable -import androidx.ui.core.Clip +import androidx.ui.core.DensityAmbient +import androidx.ui.core.FirstBaseline import androidx.ui.core.Modifier -import androidx.ui.core.Text -import androidx.ui.core.toModifier +import androidx.ui.core.clip import androidx.ui.foundation.Box +import androidx.ui.foundation.Icon +import androidx.ui.foundation.Image +import androidx.ui.foundation.Text import androidx.ui.foundation.VerticalScroller import androidx.ui.foundation.contentColor import androidx.ui.foundation.shape.corner.CircleShape import androidx.ui.foundation.shape.corner.RoundedCornerShape import androidx.ui.graphics.Color import androidx.ui.graphics.ScaleFit -import androidx.ui.graphics.painter.ImagePainter import androidx.ui.layout.Column -import androidx.ui.layout.Container -import androidx.ui.layout.LayoutHeight -import androidx.ui.layout.LayoutPadding -import androidx.ui.layout.LayoutSize -import androidx.ui.layout.LayoutWidth import androidx.ui.layout.Row import androidx.ui.layout.Spacer +import androidx.ui.layout.fillMaxWidth +import androidx.ui.layout.padding +import androidx.ui.layout.preferredHeight +import androidx.ui.layout.preferredHeightIn +import androidx.ui.layout.preferredSize +import androidx.ui.layout.preferredWidth import androidx.ui.material.ColorPalette -import androidx.ui.material.EmphasisLevels +import androidx.ui.material.EmphasisAmbient import androidx.ui.material.MaterialTheme import androidx.ui.material.ProvideEmphasis +import androidx.ui.material.Surface import androidx.ui.material.Typography -import androidx.ui.material.surface.Surface +import androidx.ui.res.vectorResource import androidx.ui.text.AnnotatedString import androidx.ui.text.ParagraphStyle import androidx.ui.text.SpanStyle @@ -65,40 +69,31 @@ import com.example.jetnews.model.Paragraph import com.example.jetnews.model.ParagraphType import com.example.jetnews.model.Post import com.example.jetnews.ui.ThemedPreview -import com.example.jetnews.ui.VectorImage import com.example.jetnews.ui.darkThemeColors private val defaultSpacerSize = 16.dp @Composable -fun PostContent(modifier: Modifier = Modifier.None, post: Post) { - val typography = MaterialTheme.typography() +fun PostContent(post: Post, modifier: Modifier = Modifier.None) { VerticalScroller { - Column( - modifier = modifier + LayoutPadding( - start = defaultSpacerSize, - top = 0.dp, - end = defaultSpacerSize, - bottom = 0.dp - ) - ) { - Spacer(LayoutHeight(defaultSpacerSize)) + Column(modifier = modifier.padding(start = defaultSpacerSize, end = defaultSpacerSize)) { + Spacer(Modifier.preferredHeight(defaultSpacerSize)) PostHeaderImage(post) - Text(text = post.title, style = typography.h4) - Spacer(LayoutHeight(8.dp)) + Text(text = post.title, style = MaterialTheme.typography.h4) + Spacer(Modifier.preferredHeight(8.dp)) post.subtitle?.let { subtitle -> - ProvideEmphasis(emphasis = EmphasisLevels().medium) { + ProvideEmphasis(EmphasisAmbient.current.medium) { Text( text = subtitle, - style = typography.body2.merge(TextStyle(lineHeight = 20.sp)) + style = MaterialTheme.typography.body2.merge(TextStyle(lineHeight = 20.sp)) ) } - Spacer(LayoutHeight(defaultSpacerSize)) + Spacer(Modifier.preferredHeight(defaultSpacerSize)) } - PostMetadata(metadata = post.metadata) - Spacer(LayoutHeight(24.dp)) - PostContents(paragraphs = post.paragraphs) - Spacer(LayoutHeight(48.dp)) + PostMetadata(post.metadata) + Spacer(Modifier.preferredHeight(24.dp)) + PostContents(post.paragraphs) + Spacer(Modifier.preferredHeight(48.dp)) } } } @@ -106,41 +101,30 @@ fun PostContent(modifier: Modifier = Modifier.None, post: Post) { @Composable private fun PostHeaderImage(post: Post) { post.image?.let { image -> - // FIXME (dev07): This duplicate sizing is a workaround for the way Draw modifiers work in - // dev06. In a future release (dev07?) replace this with a single Image composable with a - // Clip modifier applied. - - // This sizing is currently applied twice to make the image expand propertly inside the - // Clip. - val sizingModifier = LayoutHeight.Min(180.dp) + LayoutWidth.Fill - Box(modifier = sizingModifier) { - Clip(shape = RoundedCornerShape(4.dp)) { - val imageModifier = ImagePainter(image).toModifier(scaleFit = ScaleFit.FillHeight) - Box(modifier = sizingModifier + imageModifier) - } - } - Spacer(LayoutHeight(defaultSpacerSize)) + val imageModifier = Modifier + .preferredHeightIn(minHeight = 180.dp) + .fillMaxWidth() + .clip(shape = RoundedCornerShape(4.dp)) + Image(image, imageModifier, scaleFit = ScaleFit.FillHeight) + Spacer(Modifier.preferredHeight(defaultSpacerSize)) } } @Composable private fun PostMetadata(metadata: Metadata) { - val typography = MaterialTheme.typography() + val typography = MaterialTheme.typography Row { - VectorImage( - id = R.drawable.ic_account_circle_black, - tint = contentColor() - ) - Spacer(LayoutWidth(8.dp)) + Icon(vectorResource(R.drawable.ic_account_circle_black)) + Spacer(Modifier.preferredWidth(8.dp)) Column { - Spacer(LayoutHeight(4.dp)) - ProvideEmphasis(emphasis = EmphasisLevels().high) { + ProvideEmphasis(EmphasisAmbient.current.high) { Text( text = metadata.author.name, - style = typography.caption + style = typography.caption, + modifier = Modifier.padding(top = 4.dp) ) } - ProvideEmphasis(emphasis = EmphasisLevels().medium) { + ProvideEmphasis(EmphasisAmbient.current.medium) { Text( text = "${metadata.date} • ${metadata.readTimeMinutes} min read", style = typography.caption @@ -163,10 +147,10 @@ private fun Paragraph(paragraph: Paragraph) { val annotatedString = paragraphToAnnotatedString( paragraph, - MaterialTheme.typography(), - MaterialTheme.colors().codeBlockBackground + MaterialTheme.typography, + MaterialTheme.colors.codeBlockBackground ) - Container(modifier = LayoutPadding(0.dp, 0.dp, 0.dp, bottom = trailingPadding)) { + Box(modifier = Modifier.padding(bottom = trailingPadding)) { when (paragraph.type) { ParagraphType.Bullet -> BulletParagraph( text = annotatedString, @@ -180,13 +164,13 @@ private fun Paragraph(paragraph: Paragraph) { ) ParagraphType.Header -> { Text( - modifier = LayoutPadding(4.dp), + modifier = Modifier.padding(4.dp), text = annotatedString, style = textStyle.merge(paragraphStyle) ) } else -> Text( - modifier = LayoutPadding(4.dp), + modifier = Modifier.padding(4.dp), text = annotatedString, style = textStyle ) @@ -201,11 +185,12 @@ private fun CodeBlockParagraph( paragraphStyle: ParagraphStyle ) { Surface( - color = MaterialTheme.colors().codeBlockBackground, - shape = RoundedCornerShape(4.dp) + color = MaterialTheme.colors.codeBlockBackground, + shape = RoundedCornerShape(4.dp), + modifier = Modifier.fillMaxWidth() ) { Text( - modifier = LayoutPadding(start = 0.dp, top = 16.dp, end = 0.dp, bottom = 0.dp), + modifier = Modifier.padding(16.dp), text = text, style = textStyle.merge(paragraphStyle) ) @@ -219,17 +204,25 @@ private fun BulletParagraph( paragraphStyle: ParagraphStyle ) { Row { - Box( - modifier = LayoutSize(8.dp, 8.dp), - backgroundColor = contentColor(), - shape = CircleShape - ) { - // empty box + with(DensityAmbient.current) { + // this box is acting as a character, so it's sized with font scaling (sp) + Box( + modifier = Modifier + .preferredSize(8.sp.toDp(), 8.sp.toDp()) + .alignWithSiblings { + // Add an alignment "baseline" 1sp below the bottom of the circle + 9.sp.toIntPx() + }, + backgroundColor = contentColor(), + shape = CircleShape + ) } Text( - modifier = LayoutFlexible(1f), - text = text, - style = textStyle.merge(paragraphStyle) + modifier = Modifier + .weight(1f) + .alignWithSiblings(FirstBaseline), + text = text, + style = textStyle.merge(paragraphStyle) ) } } @@ -242,7 +235,7 @@ private data class ParagraphStyling( @Composable private fun ParagraphType.getTextAndParagraphStyle(): ParagraphStyling { - val typography = MaterialTheme.typography() + val typography = MaterialTheme.typography var textStyle: TextStyle = typography.body1 var paragraphStyle = ParagraphStyle() var trailingPadding = 24.dp @@ -262,12 +255,9 @@ private fun ParagraphType.getTextAndParagraphStyle(): ParagraphStyling { textStyle = typography.h5 trailingPadding = 16.dp } - ParagraphType.CodeBlock -> textStyle = - (typography.body1) - .copy( - background = MaterialTheme.colors().codeBlockBackground, - fontFamily = FontFamily.Monospace - ) + ParagraphType.CodeBlock -> textStyle = typography.body1.copy( + fontFamily = FontFamily.Monospace + ) ParagraphType.Quote -> textStyle = typography.body1 ParagraphType.Bullet -> { paragraphStyle = ParagraphStyle(textIndent = TextIndent(firstLine = 8.sp)) diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeScreen.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeScreen.kt index dcf6c7f147..433e8d1f66 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeScreen.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeScreen.kt @@ -19,23 +19,25 @@ package com.example.jetnews.ui.home import androidx.compose.Composable import androidx.compose.remember import androidx.ui.core.Modifier -import androidx.ui.core.Opacity -import androidx.ui.core.Text import androidx.ui.foundation.Clickable import androidx.ui.foundation.HorizontalScroller +import androidx.ui.foundation.Icon +import androidx.ui.foundation.Text import androidx.ui.foundation.VerticalScroller import androidx.ui.layout.Column -import androidx.ui.layout.LayoutPadding import androidx.ui.layout.Row +import androidx.ui.layout.padding import androidx.ui.material.Divider import androidx.ui.material.DrawerState -import androidx.ui.material.EmphasisLevels +import androidx.ui.material.EmphasisAmbient +import androidx.ui.material.IconButton import androidx.ui.material.MaterialTheme import androidx.ui.material.ProvideEmphasis import androidx.ui.material.Scaffold import androidx.ui.material.ScaffoldState import androidx.ui.material.TopAppBar -import androidx.ui.material.ripple.Ripple +import androidx.ui.material.ripple.ripple +import androidx.ui.res.vectorResource import androidx.ui.tooling.preview.Preview import androidx.ui.unit.dp import com.example.jetnews.R @@ -44,42 +46,39 @@ import com.example.jetnews.model.Post import com.example.jetnews.ui.AppDrawer import com.example.jetnews.ui.Screen import com.example.jetnews.ui.ThemedPreview -import com.example.jetnews.ui.VectorImageButton import com.example.jetnews.ui.darkThemeColors import com.example.jetnews.ui.navigateTo @Composable fun HomeScreen(scaffoldState: ScaffoldState = remember { ScaffoldState() }) { - Column { - Scaffold( - scaffoldState = scaffoldState, - drawerContent = { - AppDrawer( - currentScreen = Screen.Home, - closeDrawer = { scaffoldState.drawerState = DrawerState.Closed } - ) - }, - topAppBar = { - TopAppBar( - title = { Text(text = "Jetnews") }, - navigationIcon = { - VectorImageButton(R.drawable.ic_jetnews_logo) { - scaffoldState.drawerState = DrawerState.Opened - } + Scaffold( + scaffoldState = scaffoldState, + drawerContent = { + AppDrawer( + currentScreen = Screen.Home, + closeDrawer = { scaffoldState.drawerState = DrawerState.Closed } + ) + }, + topAppBar = { + TopAppBar( + title = { Text(text = "Jetnews") }, + navigationIcon = { + IconButton(onClick = { scaffoldState.drawerState = DrawerState.Opened }) { + Icon(vectorResource(R.drawable.ic_jetnews_logo)) } - ) - }, - bodyContent = { modifier -> - HomeScreenBody(modifier = modifier, posts = posts) - } - ) - } + } + ) + }, + bodyContent = { modifier -> + HomeScreenBody(posts, modifier) + } + ) } @Composable private fun HomeScreenBody( - modifier: Modifier = Modifier.None, - posts: List + posts: List, + modifier: Modifier = Modifier.None ) { val postTop = posts[3] val postsSimple = posts.subList(0, 2) @@ -87,74 +86,76 @@ private fun HomeScreenBody( val postsHistory = posts.subList(7, 10) VerticalScroller { - Column(modifier = modifier) { - HomeScreenTopSection(post = postTop) - HomeScreenSimpleSection(posts = postsSimple) - HomeScreenPopularSection(posts = postsPopular) - HomeScreenHistorySection(posts = postsHistory) + Column(modifier) { + HomeScreenTopSection(postTop) + HomeScreenSimpleSection(postsSimple) + HomeScreenPopularSection(postsPopular) + HomeScreenHistorySection(postsHistory) } } } @Composable private fun HomeScreenTopSection(post: Post) { -ProvideEmphasis(emphasis = EmphasisLevels().high) { + ProvideEmphasis(EmphasisAmbient.current.high) { Text( - modifier = LayoutPadding(start = 16.dp, top = 16.dp, end = 16.dp, bottom = 0.dp), + modifier = Modifier.padding(start = 16.dp, top = 16.dp, end = 16.dp), text = "Top stories for you", - style = MaterialTheme.typography().subtitle1 + style = MaterialTheme.typography.subtitle1 ) } - Ripple(bounded = true) { - Clickable(onClick = { - navigateTo(Screen.Article(post.id)) - }) { - PostCardTop(post = post) - } + Clickable(modifier = Modifier.ripple(), onClick = { navigateTo(Screen.Article(post.id)) }) { + PostCardTop(post = post) } HomeScreenDivider() } @Composable private fun HomeScreenSimpleSection(posts: List) { - posts.forEach { post -> - PostCardSimple(post) - HomeScreenDivider() + Column { + posts.forEach { post -> + PostCardSimple(post) + HomeScreenDivider() + } } } @Composable private fun HomeScreenPopularSection(posts: List) { - ProvideEmphasis(emphasis = EmphasisLevels().high) { - Text( - modifier = LayoutPadding(16.dp), - text = "Popular on Jetnews", - style = MaterialTheme.typography().subtitle1 - ) - } - HorizontalScroller { - Row(modifier = LayoutPadding(top = 0.dp, start = 0.dp, end = 16.dp, bottom = 16.dp)) { - posts.forEach { post -> - PostCardPopular(modifier = LayoutPadding(start = 16.dp), post = post) + Column { + ProvideEmphasis(EmphasisAmbient.current.high) { + Text( + modifier = Modifier.padding(16.dp), + text = "Popular on Jetnews", + style = MaterialTheme.typography.subtitle1 + ) + } + HorizontalScroller { + Row(modifier = Modifier.padding(end = 16.dp, bottom = 16.dp)) { + posts.forEach { post -> + PostCardPopular(post, Modifier.padding(start = 16.dp)) + } } } + HomeScreenDivider() } - HomeScreenDivider() } @Composable private fun HomeScreenHistorySection(posts: List) { - posts.forEach { post -> - PostCardHistory(post) - HomeScreenDivider() + Column { + posts.forEach { post -> + PostCardHistory(post) + HomeScreenDivider() + } } } @Composable private fun HomeScreenDivider() { - Opacity(0.08f) { - Divider(modifier = LayoutPadding(start = 14.dp, top = 0.dp, end = 14.dp, bottom = 0.dp)) - } + Divider( + modifier = Modifier.padding(start = 14.dp, end = 14.dp), + color = MaterialTheme.colors.onSurface.copy(alpha = 0.08f)) } @Preview("Home screen") diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCardTop.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCardTop.kt index 3066625a5e..37d9c65248 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCardTop.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCardTop.kt @@ -17,22 +17,21 @@ package com.example.jetnews.ui.home import androidx.compose.Composable -import androidx.ui.core.Clip import androidx.ui.core.ContextAmbient -import androidx.ui.core.Text -import androidx.ui.core.toModifier -import androidx.ui.foundation.Box +import androidx.ui.core.Modifier +import androidx.ui.core.clip +import androidx.ui.foundation.Image +import androidx.ui.foundation.Text import androidx.ui.foundation.shape.corner.RoundedCornerShape import androidx.ui.graphics.ScaleFit -import androidx.ui.graphics.painter.ImagePainter import androidx.ui.layout.Column -import androidx.ui.layout.Container -import androidx.ui.layout.LayoutHeight -import androidx.ui.layout.LayoutPadding -import androidx.ui.layout.LayoutWidth import androidx.ui.layout.Spacer +import androidx.ui.layout.fillMaxWidth +import androidx.ui.layout.padding +import androidx.ui.layout.preferredHeight +import androidx.ui.layout.preferredHeightIn import androidx.ui.material.ColorPalette -import androidx.ui.material.EmphasisLevels +import androidx.ui.material.EmphasisAmbient import androidx.ui.material.MaterialTheme import androidx.ui.material.ProvideEmphasis import androidx.ui.tooling.preview.Preview @@ -48,39 +47,29 @@ import com.example.jetnews.ui.lightThemeColors @Composable fun PostCardTop(post: Post) { // TUTORIAL CONTENT STARTS HERE - val typography = MaterialTheme.typography() - Column(modifier = LayoutWidth.Fill + LayoutPadding(16.dp)) { + val typography = MaterialTheme.typography + Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) { post.image?.let { image -> - // FIXME (dev07): This duplicate sizing is a workaround for the way Draw modifiers work in - // dev06. In a future release (dev07?) replace this with a single Image composable with a - // Clip modifier applied. - - // This sizing is currently applied twice to make the image expand propertly inside the - // Clip. - val sizeModifier = LayoutHeight.Min(180.dp) + LayoutWidth.Fill - Container(modifier = sizeModifier) { - Clip(shape = RoundedCornerShape(4.dp)) { - val imageModifier = ImagePainter(image).toModifier(scaleFit = ScaleFit.FillHeight) - Box(modifier = sizeModifier + imageModifier) - } - } + val imageModifier = Modifier + .preferredHeightIn(minHeight = 180.dp) + .fillMaxWidth() + .clip(shape = RoundedCornerShape(4.dp)) + Image(image, modifier = imageModifier, scaleFit = ScaleFit.FillHeight) } - Spacer(LayoutHeight(16.dp)) + Spacer(Modifier.preferredHeight(16.dp)) - val emphasisLevels = EmphasisLevels() - ProvideEmphasis(emphasis = emphasisLevels.high) { + val emphasisLevels = EmphasisAmbient.current + ProvideEmphasis(emphasisLevels.high) { Text( text = post.title, style = typography.h6 ) - } - ProvideEmphasis(emphasis = emphasisLevels.high) { Text( text = post.metadata.author.name, style = typography.body2 ) } - ProvideEmphasis(emphasis = emphasisLevels.medium) { + ProvideEmphasis(emphasisLevels.medium) { Text( text = "${post.metadata.date} - ${post.metadata.readTimeMinutes} min read", style = typography.body2 diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCardYourNetwork.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCardYourNetwork.kt index 7ca97a12ab..26eb9415a3 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCardYourNetwork.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCardYourNetwork.kt @@ -18,20 +18,20 @@ package com.example.jetnews.ui.home import androidx.compose.Composable import androidx.ui.core.Modifier -import androidx.ui.core.Text -import androidx.ui.core.toModifier -import androidx.ui.foundation.Box import androidx.ui.foundation.Clickable +import androidx.ui.foundation.Image +import androidx.ui.foundation.Text import androidx.ui.foundation.shape.corner.RoundedCornerShape -import androidx.ui.graphics.painter.ImagePainter import androidx.ui.layout.Column -import androidx.ui.layout.LayoutHeight -import androidx.ui.layout.LayoutPadding -import androidx.ui.layout.LayoutSize +import androidx.ui.layout.fillMaxSize +import androidx.ui.layout.padding +import androidx.ui.layout.preferredHeight +import androidx.ui.layout.preferredSize +import androidx.ui.material.Card +import androidx.ui.material.EmphasisAmbient import androidx.ui.material.MaterialTheme import androidx.ui.material.ProvideEmphasis -import androidx.ui.material.ripple.Ripple -import androidx.ui.material.surface.Card +import androidx.ui.material.ripple.ripple import androidx.ui.res.imageResource import androidx.ui.text.style.TextOverflow import androidx.ui.tooling.preview.Preview @@ -45,44 +45,38 @@ import com.example.jetnews.ui.ThemedPreview import com.example.jetnews.ui.darkThemeColors import com.example.jetnews.ui.navigateTo -private val cardSize = LayoutSize(280.dp, 240.dp) - @Composable -fun PostCardPopular(modifier: Modifier = Modifier.None, post: Post) { - Card(modifier = modifier, shape = RoundedCornerShape(4.dp)) { - Ripple(bounded = true) { - Clickable(onClick = { - navigateTo(Screen.Article(post.id)) - }) { - Column(modifier = cardSize) { - val image = post.image ?: imageResource(R.drawable.placeholder_4_3) - val imageModifier = ImagePainter(image).toModifier() - Box(modifier = LayoutHeight(100.dp) + LayoutSize.Fill + imageModifier) - Column(modifier = LayoutPadding(16.dp)) { - val emphasisLevels = MaterialTheme.emphasisLevels() - ProvideEmphasis(emphasis = emphasisLevels.high) { - Text( - text = post.title, - style = MaterialTheme.typography().h6, - maxLines = 2, - overflow = TextOverflow.Ellipsis - ) - } - ProvideEmphasis(emphasis = emphasisLevels.high) { - Text( - text = post.metadata.author.name, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography().body2 - ) - } - ProvideEmphasis(emphasis = emphasisLevels.high) { - Text( - text = "${post.metadata.date} - " + - "${post.metadata.readTimeMinutes} min read", - style = MaterialTheme.typography().body2 - ) - } +fun PostCardPopular(post: Post, modifier: Modifier = Modifier.None) { + Card(modifier = modifier.preferredSize(280.dp, 240.dp), shape = RoundedCornerShape(4.dp)) { + Clickable( + modifier = Modifier.ripple(), + onClick = { navigateTo(Screen.Article(post.id)) } + ) { + Column { + val image = post.image ?: imageResource(R.drawable.placeholder_4_3) + Image(image, Modifier.preferredHeight(100.dp).fillMaxSize()) + Column(modifier = Modifier.padding(16.dp)) { + val emphasisLevels = EmphasisAmbient.current + ProvideEmphasis(emphasisLevels.high) { + Text( + text = post.title, + style = MaterialTheme.typography.h6, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + Text( + text = post.metadata.author.name, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.body2 + ) + } + ProvideEmphasis(emphasisLevels.high) { + Text( + text = "${post.metadata.date} - " + + "${post.metadata.readTimeMinutes} min read", + style = MaterialTheme.typography.body2 + ) } } } diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCards.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCards.kt index 2bc8d2da04..b0bfb0f334 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCards.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/home/PostCards.kt @@ -17,23 +17,24 @@ package com.example.jetnews.ui.home import androidx.compose.Composable +import androidx.compose.state import androidx.ui.core.Modifier -import androidx.ui.core.Text -import androidx.ui.core.toModifier -import androidx.ui.foundation.Box import androidx.ui.foundation.Clickable -import androidx.ui.foundation.selection.Toggleable -import androidx.ui.graphics.painter.ImagePainter +import androidx.ui.foundation.Icon +import androidx.ui.foundation.Image +import androidx.ui.foundation.Text import androidx.ui.layout.Column -import androidx.ui.layout.Container -import androidx.ui.layout.LayoutPadding -import androidx.ui.layout.LayoutSize import androidx.ui.layout.Row -import androidx.ui.material.EmphasisLevels +import androidx.ui.layout.fillMaxSize +import androidx.ui.layout.padding +import androidx.ui.layout.preferredSize +import androidx.ui.material.EmphasisAmbient +import androidx.ui.material.IconToggleButton import androidx.ui.material.MaterialTheme import androidx.ui.material.ProvideEmphasis -import androidx.ui.material.ripple.Ripple +import androidx.ui.material.ripple.ripple import androidx.ui.res.imageResource +import androidx.ui.res.vectorResource import androidx.ui.tooling.preview.Preview import androidx.ui.unit.dp import com.example.jetnews.R @@ -42,90 +43,76 @@ import com.example.jetnews.model.Post import com.example.jetnews.ui.JetnewsStatus import com.example.jetnews.ui.Screen import com.example.jetnews.ui.ThemedPreview -import com.example.jetnews.ui.VectorImage import com.example.jetnews.ui.darkThemeColors import com.example.jetnews.ui.navigateTo @Composable fun AuthorAndReadTime(post: Post) { Row { - - val textStyle = MaterialTheme.typography().body2 - ProvideEmphasis(emphasis = EmphasisLevels().medium) { + val textStyle = MaterialTheme.typography.body2 + ProvideEmphasis(EmphasisAmbient.current.medium) { Text(text = post.metadata.author.name, style = textStyle) - Text( - text = " - ${post.metadata.readTimeMinutes} min read", - style = textStyle - ) + Text(text = " - ${post.metadata.readTimeMinutes} min read", style = textStyle) } } } @Composable -fun PostImage(modifier: Modifier = Modifier.None, post: Post) { +fun PostImage(post: Post, modifier: Modifier = Modifier.None) { val image = post.imageThumb ?: imageResource(R.drawable.placeholder_1_1) - val imageModifier = ImagePainter(image).toModifier() - - Box(modifier = modifier + LayoutSize(40.dp, 40.dp) + imageModifier) + Image(image, modifier.preferredSize(40.dp, 40.dp)) } @Composable fun PostTitle(post: Post) { - ProvideEmphasis(emphasis = EmphasisLevels().high) { - Text(post.title, style = MaterialTheme.typography().subtitle1) + ProvideEmphasis(EmphasisAmbient.current.high) { + Text(post.title, style = MaterialTheme.typography.subtitle1) } } @Composable fun PostCardSimple(post: Post) { - Ripple(bounded = true) { - Clickable(onClick = { - navigateTo(Screen.Article(post.id)) - }) { - Row(modifier = LayoutPadding(16.dp)) { - PostImage( - modifier = LayoutPadding(start = 0.dp, top = 0.dp, end = 16.dp, bottom = 0.dp), - post = post - ) - Column(modifier = LayoutFlexible(1f)) { - PostTitle(post) - AuthorAndReadTime(post) - } - BookmarkButton( - isBookmarked = isFavorite(postId = post.id), - onBookmark = { toggleBookmark(postId = post.id) } - ) + Clickable( + modifier = Modifier.ripple(), + onClick = { navigateTo(Screen.Article(post.id)) } + ) { + Row(modifier = Modifier.padding(16.dp)) { + PostImage(post, Modifier.padding(end = 16.dp)) + Column(modifier = Modifier.weight(1f)) { + PostTitle(post) + AuthorAndReadTime(post) } + BookmarkButton( + isBookmarked = isFavorite(postId = post.id), + onBookmark = { toggleBookmark(postId = post.id) } + ) } } } @Composable fun PostCardHistory(post: Post) { - Ripple(bounded = true) { - Clickable(onClick = { - navigateTo(Screen.Article(post.id)) - }) { - Row(modifier = LayoutPadding(all = 16.dp)) { - PostImage( - modifier = LayoutPadding(start = 0.dp, top = 0.dp, end = 16.dp, bottom = 0.dp), - post = post - ) - Column(modifier = LayoutFlexible(1f)) { - ProvideEmphasis(emphasis = EmphasisLevels().medium) { - Text( - text = "BASED ON YOUR HISTORY", - style = MaterialTheme.typography().overline - ) - } - PostTitle(post = post) - AuthorAndReadTime(post) + Clickable( + modifier = Modifier.ripple(), + onClick = { navigateTo(Screen.Article(post.id)) } + ) { + Row(Modifier.padding(16.dp)) { + PostImage( + post, + Modifier.padding(end = 16.dp) + ) + Column(Modifier.weight(1f)) { + ProvideEmphasis(EmphasisAmbient.current.medium) { + Text( + text = "BASED ON YOUR HISTORY", + style = MaterialTheme.typography.overline + ) } - VectorImage( - modifier = LayoutPadding(start = 0.dp, top = 8.dp, end = 0.dp, bottom = 8.dp), - id = R.drawable.ic_more - ) + PostTitle(post = post) + AuthorAndReadTime(post) } + Modifier.padding(top = 8.dp, bottom = 8.dp) + Image(vectorResource(R.drawable.ic_more)) } } } @@ -135,22 +122,22 @@ fun BookmarkButton( isBookmarked: Boolean, onBookmark: (Boolean) -> Unit ) { - Ripple( - bounded = false, - radius = 24.dp - ) { - Toggleable(isBookmarked, onBookmark) { - Container(modifier = LayoutSize(48.dp, 48.dp)) { - if (isBookmarked) { - VectorImage(id = R.drawable.ic_bookmarked) - } else { - VectorImage(id = R.drawable.ic_bookmark) - } - } + IconToggleButton(checked = isBookmarked, onCheckedChange = onBookmark) { + if (isBookmarked) { + Icon(vectorResource(R.drawable.ic_bookmarked), Modifier.fillMaxSize()) + } else { + Icon(vectorResource(R.drawable.ic_bookmark), Modifier.fillMaxSize()) } } } +@Preview("Bookmark Button") +@Composable +fun PreviewBookmarkButton() { + val (bookmarked, updateBookmarked) = state { false } + BookmarkButton(isBookmarked = bookmarked, onBookmark = updateBookmarked) +} + @Preview("Simple post card") @Composable fun PreviewSimplePost() { @@ -159,6 +146,14 @@ fun PreviewSimplePost() { } } +@Preview("History post card") +@Composable +fun PreviewHistoryPost() { + ThemedPreview { + PostCardHistory(post = post3) + } +} + @Preview("Simple post card dark theme") @Composable fun PreviewSimplePostDark() { diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/interests/InterestsScreen.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/interests/InterestsScreen.kt index 22a3f57e96..8494d4bb67 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/interests/InterestsScreen.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/interests/InterestsScreen.kt @@ -19,30 +19,32 @@ package com.example.jetnews.ui.interests import androidx.compose.Composable import androidx.compose.remember import androidx.compose.state -import androidx.ui.core.Clip -import androidx.ui.core.Opacity -import androidx.ui.core.Text +import androidx.ui.core.Modifier +import androidx.ui.core.clip import androidx.ui.foundation.Box -import androidx.ui.foundation.SimpleImage +import androidx.ui.foundation.Icon +import androidx.ui.foundation.Image +import androidx.ui.foundation.Text import androidx.ui.foundation.VerticalScroller import androidx.ui.foundation.selection.Toggleable import androidx.ui.foundation.shape.corner.RoundedCornerShape import androidx.ui.layout.Column -import androidx.ui.layout.Container -import androidx.ui.layout.LayoutGravity -import androidx.ui.layout.LayoutPadding -import androidx.ui.layout.LayoutSize import androidx.ui.layout.Row +import androidx.ui.layout.RowAlign +import androidx.ui.layout.padding +import androidx.ui.layout.preferredSize import androidx.ui.material.Divider import androidx.ui.material.DrawerState +import androidx.ui.material.IconButton import androidx.ui.material.MaterialTheme import androidx.ui.material.Scaffold import androidx.ui.material.ScaffoldState import androidx.ui.material.Tab import androidx.ui.material.TabRow import androidx.ui.material.TopAppBar -import androidx.ui.material.ripple.Ripple +import androidx.ui.material.ripple.ripple import androidx.ui.res.imageResource +import androidx.ui.res.vectorResource import androidx.ui.tooling.preview.Preview import androidx.ui.unit.dp import com.example.jetnews.R @@ -53,7 +55,6 @@ import com.example.jetnews.ui.AppDrawer import com.example.jetnews.ui.JetnewsStatus import com.example.jetnews.ui.Screen import com.example.jetnews.ui.ThemedPreview -import com.example.jetnews.ui.VectorImageButton import com.example.jetnews.ui.darkThemeColors private enum class Sections(val title: String) { @@ -76,8 +77,8 @@ fun InterestsScreen(scaffoldState: ScaffoldState = remember { ScaffoldState() }) TopAppBar( title = { Text("Interests") }, navigationIcon = { - VectorImageButton(R.drawable.ic_jetnews_logo) { - scaffoldState.drawerState = DrawerState.Opened + IconButton(onClick = { scaffoldState.drawerState = DrawerState.Opened }) { + Icon(vectorResource(R.drawable.ic_jetnews_logo)) } } ) @@ -105,7 +106,7 @@ private fun InterestsScreenBody( updateSection(Sections.values()[index]) }) } - Container(modifier = LayoutFlexible(1f)) { + Box(modifier = Modifier.weight(1f)) { when (currentSection) { Sections.Topics -> TopicsTab() Sections.People -> PeopleTab() @@ -142,7 +143,7 @@ private fun PublicationsTab() { @Composable private fun TabWithTopics(tabName: String, topics: List) { VerticalScroller { - Column(modifier = LayoutPadding(top = 16.dp)) { + Column(modifier = Modifier.padding(top = 16.dp)) { topics.forEach { topic -> TopicItem( getTopicKey( @@ -168,8 +169,8 @@ private fun TabWithSections( sections.forEach { (section, topics) -> Text( text = section, - modifier = LayoutPadding(16.dp), - style = (MaterialTheme.typography()).subtitle1) + modifier = Modifier.padding(16.dp), + style = MaterialTheme.typography.subtitle1) topics.forEach { topic -> TopicItem( getTopicKey( @@ -188,43 +189,47 @@ private fun TabWithSections( @Composable private fun TopicItem(topicKey: String, itemTitle: String) { val image = imageResource(R.drawable.placeholder_1_1) - - Ripple(bounded = true) { - val selected = isTopicSelected(topicKey) - val onSelected = { it: Boolean -> - selectTopic(topicKey, it) - } - Toggleable(selected, onSelected) { - // TODO(b/150060763): Remove box after "Bug in ripple + modifiers." - Box { - Row( - modifier = LayoutPadding(start = 16.dp, top = 0.dp, end = 16.dp, bottom = 0.dp) - ) { - Container(modifier = LayoutGravity.Center + LayoutSize(56.dp, 56.dp)) { - Clip(RoundedCornerShape(4.dp)) { - SimpleImage(image = image) - } - } - Text( - text = itemTitle, - modifier = LayoutFlexible(1f) + LayoutGravity.Center + LayoutPadding(16.dp), - style = (MaterialTheme.typography()).subtitle1 - ) - SelectTopicButton( - modifier = LayoutGravity.Center, - selected = selected - ) - } - } + val selected = isTopicSelected(topicKey) + val onSelected = { it: Boolean -> + selectTopic(topicKey, it) + } + Toggleable( + value = selected, + onValueChange = onSelected, + modifier = Modifier.ripple() + ) { + Row( + modifier = Modifier.padding(start = 16.dp, end = 16.dp) + ) { + Image( + image, + Modifier + .gravity(RowAlign.Center) + .preferredSize(56.dp, 56.dp) + .clip(RoundedCornerShape(4.dp)) + ) + Text( + text = itemTitle, + modifier = Modifier + .weight(1f) + .gravity(RowAlign.Center) + .padding(16.dp), + style = MaterialTheme.typography.subtitle1 + ) + SelectTopicButton( + modifier = Modifier.gravity(RowAlign.Center), + selected = selected + ) } } } @Composable private fun TopicDivider() { - Opacity(0.08f) { - Divider(LayoutPadding(start = 72.dp, top = 8.dp, end = 0.dp, bottom = 8.dp)) - } + Divider( + modifier = Modifier.padding(start = 72.dp, top = 8.dp, bottom = 8.dp), + color = MaterialTheme.colors.surface.copy(alpha = 0.08f) + ) } private fun getTopicKey(tab: String, group: String, topic: String) = "$tab-$group-$topic" diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/interests/SelectTopicButton.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/interests/SelectTopicButton.kt index bcc4a60136..55d06af883 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/interests/SelectTopicButton.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/interests/SelectTopicButton.kt @@ -19,11 +19,10 @@ package com.example.jetnews.ui.interests import androidx.compose.Composable import androidx.ui.core.Modifier import androidx.ui.foundation.Box -import androidx.ui.foundation.contentColor +import androidx.ui.foundation.Icon import androidx.ui.foundation.shape.corner.CircleShape -import androidx.ui.graphics.vector.DrawVector -import androidx.ui.layout.LayoutPadding -import androidx.ui.layout.LayoutSize +import androidx.ui.layout.padding +import androidx.ui.layout.preferredSize import androidx.ui.material.ColorPalette import androidx.ui.material.MaterialTheme import androidx.ui.res.vectorResource @@ -40,35 +39,32 @@ fun SelectTopicButton( selected: Boolean = false ) { if (selected) { - SelectTopicButtonOn(modifier + LayoutSize(36.dp, 36.dp)) + SelectTopicButtonOn(modifier.preferredSize(36.dp, 36.dp)) } else { - SelectTopicButtonOff(modifier + LayoutSize(36.dp, 36.dp)) + SelectTopicButtonOff(modifier.preferredSize(36.dp, 36.dp)) } } @Composable private fun SelectTopicButtonOn(modifier: Modifier = Modifier.None) { Box( - backgroundColor = MaterialTheme.colors().primary, + backgroundColor = MaterialTheme.colors.primary, shape = CircleShape, modifier = modifier ) { - DrawVector(vectorResource(R.drawable.ic_check)) + Icon(vectorResource(R.drawable.ic_check)) } } @Composable private fun SelectTopicButtonOff(modifier: Modifier = Modifier.None) { - val borderColor = MaterialTheme.colors().onSurface.copy(alpha = 0.12f) + val borderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.12f) Box( backgroundColor = borderColor, shape = CircleShape, modifier = modifier ) { - DrawVector( - vectorImage = vectorResource(R.drawable.ic_add), - tintColor = contentColor() - ) + Icon(vectorResource(R.drawable.ic_add)) } } @@ -112,7 +108,7 @@ fun SelectTopicButtonPreviewOnDark() { private fun SelectTopicButtonPreviewTemplate(themeColors: ColorPalette, selected: Boolean) { ThemedPreview(themeColors) { SelectTopicButton( - modifier = LayoutPadding(32.dp), + modifier = Modifier.padding(32.dp), selected = selected ) } diff --git a/JetNews/app/src/main/res/drawable/ic_back.xml b/JetNews/app/src/main/res/drawable/ic_back.xml deleted file mode 100644 index e5d020efbc..0000000000 --- a/JetNews/app/src/main/res/drawable/ic_back.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - diff --git a/JetNews/build.gradle b/JetNews/build.gradle index 28a0d8ca0f..d1e9f9386e 100644 --- a/JetNews/build.gradle +++ b/JetNews/build.gradle @@ -17,7 +17,7 @@ buildscript { ext.kotlin_version = '1.3.71' - def compose_release_version = "dev06" + def compose_release_version = "dev08" ext.compose_version = "0.1.0-$compose_release_version" ext.compose_compiler_extension_version = "0.1.0-$compose_release_version"