Add expandable card for product on long click

This commit is contained in:
LooKeR 2022-02-25 13:34:21 +05:30
parent 78aeab9f97
commit 63c075776f
3 changed files with 153 additions and 62 deletions

View File

@ -4,6 +4,8 @@ import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.Surface
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.looker.droidify.database.entity.Product import com.looker.droidify.database.entity.Product
@ -16,6 +18,7 @@ fun ProductsVerticalRecycler(
repositories: Map<Long, Repository>, repositories: Map<Long, Repository>,
onUserClick: (ProductItem) -> Unit = {} onUserClick: (ProductItem) -> Unit = {}
) { ) {
Surface(color = MaterialTheme.colorScheme.background){
LazyColumn( LazyColumn(
verticalArrangement = spacedBy(2.dp) verticalArrangement = spacedBy(2.dp)
) { ) {
@ -26,6 +29,7 @@ fun ProductsVerticalRecycler(
} }
} }
} }
}
@Composable @Composable
fun ProductsHorizontalRecycler( fun ProductsHorizontalRecycler(

View File

@ -6,22 +6,27 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ContentAlpha import androidx.compose.material.ContentAlpha
import androidx.compose.material.LocalContentAlpha import androidx.compose.material.LocalContentAlpha
import androidx.compose.material3.MaterialTheme import androidx.compose.material.icons.Icons
import androidx.compose.material3.Text import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material3.*
import androidx.compose.material3.ButtonDefaults.buttonColors
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.looker.droidify.R
import com.looker.droidify.database.entity.Repository import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.ProductItem import com.looker.droidify.entity.ProductItem
import com.looker.droidify.network.CoilDownloader import com.looker.droidify.network.CoilDownloader
import com.looker.droidify.ui.compose.components.ExpandableCard
import com.looker.droidify.ui.compose.components.NetworkImage import com.looker.droidify.ui.compose.components.NetworkImage
import com.looker.droidify.ui.compose.theme.AppTheme import com.looker.droidify.ui.compose.theme.AppTheme
import com.looker.droidify.ui.compose.theme.LocalShapes
@Composable @Composable
fun ProductRow( fun ProductRow(
@ -29,7 +34,6 @@ fun ProductRow(
repo: Repository? = null, repo: Repository? = null,
onUserClick: (ProductItem) -> Unit = {} onUserClick: (ProductItem) -> Unit = {}
) { ) {
val imageData by remember(item, repo) { val imageData by remember(item, repo) {
mutableStateOf( mutableStateOf(
CoilDownloader.createIconUri( CoilDownloader.createIconUri(
@ -42,16 +46,15 @@ fun ProductRow(
) )
} }
ExpandableCard(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
onClick = { onUserClick(item) },
expandedContent = { ExpandedItemContent(item = item) }
) {
Row( Row(
modifier = Modifier modifier = Modifier.fillMaxWidth(),
.padding(4.dp) horizontalArrangement = Arrangement.spacedBy(8.dp),
.fillMaxWidth() verticalAlignment = Alignment.CenterVertically
.background(
color = MaterialTheme.colorScheme.surface,
shape = RoundedCornerShape(LocalShapes.current.large)
)
.clickable(onClick = { onUserClick(item) })
.padding(8.dp)
) { ) {
NetworkImage( NetworkImage(
modifier = Modifier.size(56.dp), modifier = Modifier.size(56.dp),
@ -59,30 +62,23 @@ fun ProductRow(
) )
Column( Column(
modifier = Modifier modifier = Modifier.requiredHeight(56.dp)
.padding(start = 8.dp)
.align(Alignment.CenterVertically)
.requiredHeight(56.dp)
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.fillMaxHeight(0.6f), .fillMaxHeight(0.6f),
contentAlignment = Alignment.TopEnd
) { ) {
Text( Text(
text = item.name, text = item.name,
modifier = Modifier modifier = Modifier.align(Alignment.CenterStart),
.align(Alignment.CenterStart),
fontWeight = FontWeight.Bold,
softWrap = true, softWrap = true,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.titleMedium
) )
Text( Text(
text = item.version, text = item.version,
modifier = Modifier modifier = Modifier.align(Alignment.CenterEnd),
.align(Alignment.CenterEnd),
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.bodySmall style = MaterialTheme.typography.bodySmall
) )
@ -91,12 +87,14 @@ fun ProductRow(
Text( Text(
modifier = Modifier.fillMaxHeight(), modifier = Modifier.fillMaxHeight(),
text = item.summary, text = item.summary,
style = MaterialTheme.typography.bodySmall style = MaterialTheme.typography.bodySmall,
overflow = TextOverflow.Ellipsis
) )
} }
} }
} }
} }
}
@Composable @Composable
fun ProductColumn( fun ProductColumn(
@ -120,9 +118,9 @@ fun ProductColumn(
Column( Column(
modifier = Modifier modifier = Modifier
.padding(4.dp) .padding(4.dp)
.requiredSize(72.dp, 96.dp) .sizeIn(minWidth = 72.dp, minHeight = 96.dp, maxWidth = 110.dp)
.background(color = MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(8.dp))
.clip(shape = RoundedCornerShape(8.dp)) .clip(shape = RoundedCornerShape(8.dp))
.background(color = MaterialTheme.colorScheme.surface)
.clickable(onClick = { onUserClick(item) }) .clickable(onClick = { onUserClick(item) })
.padding(4.dp), .padding(4.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
@ -134,8 +132,7 @@ fun ProductColumn(
Text( Text(
text = item.name, text = item.name,
fontWeight = FontWeight.Bold, style = MaterialTheme.typography.bodySmall,
style = MaterialTheme.typography.bodyLarge,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
maxLines = 1 maxLines = 1
) )
@ -150,6 +147,44 @@ fun ProductColumn(
} }
} }
@Composable
fun ExpandedItemContent(
modifier: Modifier = Modifier,
item: ProductItem,
favourite: Boolean = false,
onFavourite: (ProductItem) -> Unit = {},
onInstallClicked: (ProductItem) -> Unit = {}
) {
Box(contentAlignment = Alignment.CenterEnd) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = { onFavourite(item) }) {
Icon(
imageVector = if (favourite) Icons.Default.Favorite else Icons.Default.FavoriteBorder,
contentDescription = "Add to Favourite",
tint = if (favourite) Color.Red else MaterialTheme.colorScheme.outline
)
}
FilledTonalButton(
colors = buttonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
),
onClick = { onInstallClicked(item) }
) {
Icon(
painter = painterResource(id = R.drawable.ic_download),
contentDescription = "Add to Favourite"
)
Text(text = "Install")
}
}
}
}
@Preview @Preview
@Composable @Composable
fun ProductColumnPreview() { fun ProductColumnPreview() {

View File

@ -0,0 +1,52 @@
package com.looker.droidify.ui.compose.components
import androidx.compose.animation.*
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import com.looker.droidify.ui.compose.theme.LocalShapes
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ExpandableCard(
modifier: Modifier = Modifier,
preExpanded: Boolean = false,
onClick: () -> Unit = {},
expandedContent: @Composable () -> Unit = {},
mainContent: @Composable () -> Unit
) {
var expanded by remember { mutableStateOf(preExpanded) }
Surface(
modifier = Modifier
.animateContentSize()
.clip(RoundedCornerShape(LocalShapes.current.large))
.combinedClickable(
onClick = onClick,
onLongClick = { expanded = !expanded }
),
color = MaterialTheme.colorScheme.background
) {
Box(modifier = modifier, contentAlignment = Alignment.CenterStart) {
Column {
mainContent()
AnimatedVisibility(
modifier = Modifier.align(Alignment.End),
visible = expanded,
enter = fadeIn() + expandIn(expandFrom = Alignment.TopEnd),
exit = fadeOut() + shrinkOut(shrinkTowards = Alignment.TopEnd)
) {
expandedContent()
}
}
}
}
}