-
-
Save parishsu/0348bfc8b2e931feba1d0d0ee20beb25 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.multimodal | |
import androidx.compose.runtime.mutableStateOf | |
import android.annotation.SuppressLint | |
import androidx.compose.foundation.Image | |
import androidx.compose.foundation.background | |
import androidx.compose.foundation.clickable | |
import androidx.compose.foundation.layout.Arrangement | |
import androidx.compose.foundation.layout.Box | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.ExperimentalLayoutApi | |
import androidx.compose.foundation.layout.FlowRow | |
import androidx.compose.foundation.layout.PaddingValues | |
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.height | |
import androidx.compose.foundation.layout.padding | |
import androidx.compose.foundation.lazy.LazyColumn | |
import androidx.compose.foundation.lazy.items | |
import androidx.compose.foundation.shape.RoundedCornerShape | |
import androidx.compose.material.icons.Icons | |
import androidx.compose.material.icons.filled.BookmarkBorder | |
import androidx.compose.material.icons.filled.Favorite | |
import androidx.compose.material.icons.filled.Home | |
import androidx.compose.material.icons.filled.Search | |
import androidx.compose.material.icons.outlined.Settings | |
import androidx.compose.material3.Button | |
import androidx.compose.material3.ButtonDefaults | |
import androidx.compose.material3.ExperimentalMaterial3Api | |
import androidx.compose.material3.Icon | |
import androidx.compose.material3.IconButton | |
import androidx.compose.material3.MaterialTheme | |
import androidx.compose.material3.NavigationBar | |
import androidx.compose.material3.NavigationBarItem | |
import androidx.compose.material3.Scaffold | |
import androidx.compose.material3.Surface | |
import androidx.compose.material3.Text | |
import androidx.compose.material3.TopAppBar | |
import androidx.compose.material3.TopAppBarDefaults | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.mutableIntStateOf | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.setValue | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.draw.clip | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.layout.ContentScale | |
import androidx.compose.ui.res.painterResource | |
import androidx.compose.ui.text.font.FontWeight | |
import androidx.compose.ui.text.style.TextAlign | |
import androidx.compose.ui.tooling.preview.Preview | |
import androidx.compose.ui.unit.dp | |
import androidx.compose.ui.unit.sp | |
import java.text.SimpleDateFormat | |
import java.util.Date | |
import java.util.Locale | |
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi | |
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass | |
import androidx.compose.runtime.CompositionLocalProvider | |
import androidx.compose.runtime.staticCompositionLocalOf | |
import androidx.compose.ui.platform.LocalConfiguration | |
/** | |
* Data class to represent an article. | |
*/ | |
data class Article( | |
val id: Int, | |
val title: String, | |
val date: Date, | |
val tags: List<String>, | |
val content: String, | |
val imageResId: Int, | |
val isBookmarked: Boolean = false | |
) | |
/** | |
* Static composition local to manage the current Article selected. | |
*/ | |
val LocalSelectedArticle = staticCompositionLocalOf<Article?> { null } | |
/** | |
* Main composable function for the "Now in Android" screen. | |
* | |
* This function structures the layout of the app's main screen, | |
* including the top app bar, a list of articles, and a bottom navigation bar. | |
*/ | |
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class, | |
ExperimentalMaterial3WindowSizeClassApi::class | |
) | |
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") | |
@Composable | |
fun ArticleScreen(windowSize: WindowWidthSizeClass) { | |
// Sample articles data | |
val articles = remember { | |
listOf( | |
Article( | |
id = 1, | |
title = "The new Google Pixel Watch is here — start building for Wear OS!", | |
date = SimpleDateFormat("MMM dd, yyyy", Locale.US).parse("Oct 6, 2022") | |
?: Date(), | |
tags = listOf("HEADLINES", "WEAR OS", "COMPOSE"), | |
content = "We launched the Google Pixel Watch, powered by Wear OS 3.5, at the Made by Google event — the perfect device to showcase apps built with Compose for Wear OS. With Compose for Wear OS, the Tiles Material library, and the tools in Android Studio Dolphin, it's now simpler and more efficient than ever to make apps for WearOS.", | |
imageResId = R.drawable.placeholder_koala | |
), | |
Article( | |
id = 2, | |
title = "Android Studio Electric Eel (2022.1.1) is now stable", | |
date = SimpleDateFormat("MMM dd, yyyy", Locale.US).parse("Dec 15, 2022") | |
?: Date(), | |
tags = listOf("ANDROID STUDIO", "HEADLINES"), | |
content = "Android Studio Electric Eel (2022.1.1) is now stable", | |
imageResId = R.drawable.placeholder_iguana | |
), | |
Article( | |
id = 3, | |
title = "Now in Android: Episode 80", | |
date = SimpleDateFormat("MMM dd, yyyy", Locale.US).parse("Feb 2, 2023") | |
?: Date(), | |
tags = listOf("NOW IN ANDROID"), | |
content = "Episode 80 of Now in Android is out now!", | |
imageResId = R.drawable.placeholder_dolphin | |
) | |
) | |
} | |
var selectedItem by remember { mutableIntStateOf(0) } | |
val items = listOf("For you", "Saved", "Interests") | |
var selectedArticle by remember { mutableStateOf<Article?>(null) } | |
// To manage the different window sizes | |
CompositionLocalProvider(LocalSelectedArticle provides selectedArticle) { | |
Scaffold( | |
topBar = { | |
TopAppBar( | |
title = { | |
Text( | |
text = "Now in Android", | |
fontWeight = FontWeight.Bold, | |
fontSize = 20.sp | |
) | |
}, | |
navigationIcon = { | |
IconButton(onClick = { /*TODO*/ }) { | |
Icon( | |
imageVector = Icons.Filled.Search, | |
contentDescription = "Search" | |
) | |
} | |
}, | |
actions = { | |
IconButton(onClick = { /*TODO*/ }) { | |
Icon( | |
imageVector = Icons.Outlined.Settings, | |
contentDescription = "Settings" | |
) | |
} | |
}, | |
colors = TopAppBarDefaults.topAppBarColors( | |
containerColor = MaterialTheme.colorScheme.surface | |
) | |
) | |
}, | |
bottomBar = { | |
NavigationBar( | |
containerColor = MaterialTheme.colorScheme.surface | |
) { | |
items.forEachIndexed { index, item -> | |
NavigationBarItem( | |
icon = { | |
when (item) { | |
"For you" -> Icon( | |
imageVector = Icons.Filled.Home, | |
contentDescription = item | |
) | |
"Saved" -> Icon( | |
imageVector = Icons.Filled.BookmarkBorder, | |
contentDescription = item | |
) | |
"Interests" -> Icon( | |
imageVector = Icons.Filled.Favorite, | |
contentDescription = item | |
) | |
} | |
}, | |
label = { Text(item) }, | |
selected = selectedItem == index, | |
onClick = { selectedItem = index } | |
) | |
} | |
} | |
}, | |
modifier = Modifier.fillMaxSize() | |
) { innerPadding -> | |
Surface( | |
modifier = Modifier | |
.fillMaxSize() | |
.padding(innerPadding) | |
.background(MaterialTheme.colorScheme.surface) | |
) { | |
// List of articles | |
LazyColumn( | |
modifier = Modifier.fillMaxSize(), | |
contentPadding = PaddingValues(16.dp), | |
verticalArrangement = Arrangement.spacedBy(16.dp) | |
) { | |
items(articles) { article -> | |
ArticleItem(article = article, onArticleClick = { | |
selectedArticle = article | |
}) | |
} | |
} | |
if (windowSize != WindowWidthSizeClass.Compact) { | |
DetailArticle() | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Composable function for displaying a single article item. | |
* | |
* @param article The article data to display. | |
*/ | |
@OptIn(ExperimentalLayoutApi::class) | |
@Composable | |
fun ArticleItem(article: Article, onArticleClick: (Article) -> Unit) { | |
val configuration = LocalConfiguration.current | |
val screenWidth = configuration.screenWidthDp.dp | |
Column( | |
modifier = Modifier | |
.fillMaxWidth() | |
.background(MaterialTheme.colorScheme.surfaceVariant, RoundedCornerShape(16.dp)) | |
.clickable { onArticleClick(article) } | |
.padding(16.dp) | |
) { | |
Image( | |
painter = painterResource(id = article.imageResId), | |
contentDescription = null, | |
modifier = Modifier | |
.fillMaxWidth() | |
.height(screenWidth / 2) | |
.clip(RoundedCornerShape(16.dp)), | |
contentScale = ContentScale.Crop | |
) | |
Spacer(modifier = Modifier.height(16.dp)) | |
Text( | |
text = article.title, | |
style = MaterialTheme.typography.titleMedium, | |
fontWeight = FontWeight.Bold, | |
color = MaterialTheme.colorScheme.onSurfaceVariant | |
) | |
Spacer(modifier = Modifier.height(8.dp)) | |
Row(verticalAlignment = Alignment.CenterVertically) { | |
Text( | |
text = SimpleDateFormat("MMM dd, yyyy", Locale.US).format(article.date), | |
style = MaterialTheme.typography.bodySmall, | |
color = MaterialTheme.colorScheme.onSurfaceVariant | |
) | |
Text( | |
modifier = Modifier.padding(start = 4.dp), | |
text = "• Article", | |
style = MaterialTheme.typography.bodySmall, | |
color = MaterialTheme.colorScheme.onSurfaceVariant | |
) | |
Spacer(modifier = Modifier.weight(1f)) | |
Icon( | |
imageVector = Icons.Filled.BookmarkBorder, | |
contentDescription = "Bookmark", | |
tint = MaterialTheme.colorScheme.onSurfaceVariant | |
) | |
} | |
Spacer(modifier = Modifier.height(8.dp)) | |
Text( | |
text = article.content, | |
style = MaterialTheme.typography.bodyMedium, | |
color = MaterialTheme.colorScheme.onSurfaceVariant, | |
maxLines = 3 | |
) | |
Spacer(modifier = Modifier.height(16.dp)) | |
FlowRow( | |
horizontalArrangement = Arrangement.spacedBy(8.dp) | |
) { | |
article.tags.forEach { tag -> | |
TagButton(tag = tag) | |
} | |
} | |
} | |
} | |
/** | |
* Composable function for displaying a tag button. | |
* | |
* @param tag The tag text to display. | |
*/ | |
@Composable | |
fun TagButton(tag: String) { | |
Button( | |
onClick = { /*TODO*/ }, | |
modifier = Modifier, | |
shape = RoundedCornerShape(16.dp), | |
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp), | |
colors = ButtonDefaults.buttonColors( | |
containerColor = MaterialTheme.colorScheme.tertiaryContainer, | |
contentColor = MaterialTheme.colorScheme.onTertiaryContainer | |
) | |
) { | |
Text(text = tag, fontSize = 12.sp) | |
} | |
} | |
@Composable | |
fun DetailArticle(){ | |
val selectedArticle = LocalSelectedArticle.current | |
selectedArticle?.let { | |
Box( | |
modifier = Modifier | |
.fillMaxSize() | |
.background(Color.Gray) // Example color | |
) { | |
Text( | |
text = it.title, | |
style = MaterialTheme.typography.headlineLarge, | |
color = Color.White, // Example color | |
textAlign = TextAlign.Center, | |
modifier = Modifier.align(Alignment.Center) | |
) | |
} | |
} | |
} | |
/** | |
* Preview function to display NowInAndroidScreen in the IDE. | |
*/ | |
@Preview(showBackground = true) | |
@Composable | |
fun ArticleScreenPreview() { | |
MaterialTheme { | |
ArticleScreen(WindowWidthSizeClass.Compact) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment