Skip to content

Commit d03144d

Browse files
committed
Change favourites to single grid and add animation
1 parent f06d29a commit d03144d

2 files changed

Lines changed: 64 additions & 100 deletions

File tree

app/src/main/java/dev/shorthouse/coinwatch/ui/screen/favourites/FavouritesScreen.kt

Lines changed: 64 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
package dev.shorthouse.coinwatch.ui.screen.favourites
22

33
import androidx.compose.animation.AnimatedVisibility
4+
import androidx.compose.animation.core.FastOutSlowInEasing
5+
import androidx.compose.animation.core.tween
46
import androidx.compose.animation.scaleIn
57
import androidx.compose.animation.scaleOut
68
import androidx.compose.foundation.LocalOverscrollFactory
79
import androidx.compose.foundation.horizontalScroll
810
import androidx.compose.foundation.layout.Arrangement
911
import androidx.compose.foundation.layout.PaddingValues
1012
import androidx.compose.foundation.layout.Row
11-
import androidx.compose.foundation.layout.fillMaxHeight
1213
import androidx.compose.foundation.layout.fillMaxSize
1314
import androidx.compose.foundation.layout.padding
14-
import androidx.compose.foundation.lazy.LazyColumn
15-
import androidx.compose.foundation.lazy.LazyListState
1615
import androidx.compose.foundation.lazy.grid.GridCells
1716
import androidx.compose.foundation.lazy.grid.GridItemSpan
1817
import androidx.compose.foundation.lazy.grid.LazyGridState
1918
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
2019
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
21-
import androidx.compose.foundation.lazy.rememberLazyListState
2220
import androidx.compose.foundation.rememberScrollState
2321
import androidx.compose.foundation.shape.CornerSize
2422
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -52,6 +50,7 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
5250
import androidx.compose.ui.res.stringResource
5351
import androidx.compose.ui.tooling.preview.Preview
5452
import androidx.compose.ui.tooling.preview.PreviewParameter
53+
import androidx.compose.ui.tooling.preview.PreviewWrapper
5554
import androidx.compose.ui.unit.dp
5655
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
5756
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -62,14 +61,13 @@ import dev.shorthouse.coinwatch.ui.component.CoinSortChip
6261
import dev.shorthouse.coinwatch.ui.component.LoadingIndicator
6362
import dev.shorthouse.coinwatch.ui.component.ScrollToTopFab
6463
import dev.shorthouse.coinwatch.ui.insets.AppWindowInsets
64+
import dev.shorthouse.coinwatch.ui.preview.AppPreviewWrapper
6565
import dev.shorthouse.coinwatch.ui.preview.FavouritesUiStatePreviewProvider
6666
import dev.shorthouse.coinwatch.ui.screen.favourites.component.FavouriteCondensedItem
6767
import dev.shorthouse.coinwatch.ui.screen.favourites.component.FavouriteItem
6868
import dev.shorthouse.coinwatch.ui.screen.favourites.component.FavouritesEmptyState
6969
import kotlinx.collections.immutable.ImmutableList
7070
import kotlinx.coroutines.launch
71-
import androidx.compose.ui.tooling.preview.PreviewWrapper
72-
import dev.shorthouse.coinwatch.ui.preview.AppPreviewWrapper
7371

7472
@Composable
7573
fun FavouritesScreen(
@@ -111,21 +109,12 @@ fun FavouriteScreen(
111109
) {
112110
val scope = rememberCoroutineScope()
113111
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
114-
val listState = rememberLazyListState()
115112
val gridState = rememberLazyGridState()
116113
val snackbarHostState = remember { SnackbarHostState() }
117114
val pullRefreshState = rememberPullToRefreshState()
118115
val showScrollToTopFab by remember {
119116
derivedStateOf {
120-
gridState.firstVisibleItemIndex > 0 || listState.firstVisibleItemIndex > 0
121-
}
122-
}
123-
124-
LaunchedEffect(uiState.isFavouritesCondensed) {
125-
if (uiState.isFavouritesCondensed) {
126-
gridState.scrollToItem(0)
127-
} else {
128-
listState.scrollToItem(0)
117+
gridState.firstVisibleItemIndex > 0
129118
}
130119
}
131120

@@ -149,11 +138,7 @@ fun FavouriteScreen(
149138
ScrollToTopFab(
150139
onClick = {
151140
scope.launch {
152-
if (uiState.isFavouritesCondensed) {
153-
listState.animateScrollToItem(0)
154-
} else {
155-
gridState.animateScrollToItem(0)
156-
}
141+
gridState.animateScrollToItem(0)
157142
}
158143
}
159144
)
@@ -192,8 +177,7 @@ fun FavouriteScreen(
192177
isFavouritesCondensed = uiState.isFavouritesCondensed,
193178
coinSort = uiState.coinSort,
194179
onUpdateCoinSort = onUpdateCoinSort,
195-
gridState = gridState,
196-
listState = listState
180+
gridState = gridState
197181
)
198182
}
199183
}
@@ -263,7 +247,6 @@ fun FavouritesContent(
263247
coinSort: CoinSort,
264248
onUpdateCoinSort: (CoinSort) -> Unit,
265249
gridState: LazyGridState,
266-
listState: LazyListState,
267250
modifier: Modifier = Modifier,
268251
) {
269252
CompositionLocalProvider(LocalOverscrollFactory provides null) {
@@ -272,21 +255,11 @@ fun FavouritesContent(
272255
FavouritesEmptyState()
273256
}
274257

275-
isFavouritesCondensed -> {
276-
FavouritesList(
277-
favouriteCoins = favouriteCoins,
278-
onCoinClick = onCoinClick,
279-
coinSort = coinSort,
280-
onUpdateCoinSort = onUpdateCoinSort,
281-
listState = listState,
282-
modifier = modifier
283-
)
284-
}
285-
286258
else -> {
287259
FavouritesGrid(
288260
favouriteCoins = favouriteCoins,
289261
onCoinClick = onCoinClick,
262+
isFavouritesCondensed = isFavouritesCondensed,
290263
coinSort = coinSort,
291264
onUpdateCoinSort = onUpdateCoinSort,
292265
gridState = gridState,
@@ -301,70 +274,42 @@ fun FavouritesContent(
301274
fun FavouritesGrid(
302275
favouriteCoins: ImmutableList<FavouriteCoin>,
303276
onCoinClick: (FavouriteCoin) -> Unit,
277+
isFavouritesCondensed: Boolean,
304278
coinSort: CoinSort,
305279
onUpdateCoinSort: (CoinSort) -> Unit,
306280
gridState: LazyGridState,
307281
modifier: Modifier = Modifier,
308282
) {
309283
LazyVerticalGrid(
310284
state = gridState,
311-
columns = GridCells.Adaptive(minSize = 140.dp),
312-
horizontalArrangement = Arrangement.spacedBy(16.dp),
313-
verticalArrangement = Arrangement.spacedBy(16.dp),
285+
columns = if (isFavouritesCondensed) {
286+
GridCells.Fixed(1)
287+
} else {
288+
GridCells.Adaptive(minSize = 140.dp)
289+
},
290+
horizontalArrangement = Arrangement.spacedBy(
291+
if (isFavouritesCondensed) 0.dp else 16.dp
292+
),
293+
verticalArrangement = Arrangement.spacedBy(
294+
if (isFavouritesCondensed) 0.dp else 16.dp
295+
),
314296
contentPadding = PaddingValues(start = 12.dp, end = 12.dp, bottom = 80.dp),
315-
modifier = modifier.fillMaxHeight()
297+
modifier = modifier,
316298
) {
317299
item(
318300
span = { GridItemSpan(maxLineSpan) },
319301
) {
320-
Row(
321-
horizontalArrangement = Arrangement.spacedBy(8.dp),
322-
modifier = Modifier.horizontalScroll(rememberScrollState())
323-
) {
324-
CoinSort.entries.forEach { coinSortEntry ->
325-
CoinSortChip(
326-
coinSort = coinSortEntry,
327-
selected = coinSortEntry == coinSort,
328-
onClick = { onUpdateCoinSort(coinSortEntry) }
329-
)
330-
}
331-
}
332-
}
333-
items(
334-
count = favouriteCoins.size,
335-
key = { favouriteCoins[it].id },
336-
itemContent = { index ->
337-
val favouriteCoinItem = favouriteCoins[index]
338-
339-
FavouriteItem(
340-
favouriteCoin = favouriteCoinItem,
341-
onCoinClick = { onCoinClick(favouriteCoinItem) }
342-
)
343-
}
344-
)
345-
}
346-
}
347-
348-
@Composable
349-
fun FavouritesList(
350-
favouriteCoins: ImmutableList<FavouriteCoin>,
351-
onCoinClick: (FavouriteCoin) -> Unit,
352-
coinSort: CoinSort,
353-
onUpdateCoinSort: (CoinSort) -> Unit,
354-
listState: LazyListState,
355-
modifier: Modifier = Modifier,
356-
) {
357-
LazyColumn(
358-
state = listState,
359-
contentPadding = PaddingValues(start = 12.dp, end = 12.dp, bottom = 80.dp),
360-
modifier = modifier.fillMaxHeight()
361-
) {
362-
item {
363302
Row(
364303
horizontalArrangement = Arrangement.spacedBy(8.dp),
365304
modifier = Modifier
366305
.horizontalScroll(rememberScrollState())
367-
.padding(bottom = 8.dp)
306+
.padding(
307+
bottom = if (isFavouritesCondensed) {
308+
16.dp
309+
} else {
310+
0.dp
311+
}
312+
)
368313
) {
369314
CoinSort.entries.forEach { coinSortEntry ->
370315
CoinSortChip(
@@ -381,27 +326,46 @@ fun FavouritesList(
381326
itemContent = { index ->
382327
val favouriteCoinItem = favouriteCoins[index]
383328

384-
val cardShape = when {
385-
favouriteCoins.size == 1 -> MaterialTheme.shapes.medium
329+
if (isFavouritesCondensed) {
330+
val cardShape = when {
331+
favouriteCoins.size == 1 -> MaterialTheme.shapes.medium
386332

387-
index == 0 -> MaterialTheme.shapes.medium.copy(
388-
bottomStart = CornerSize(0.dp),
389-
bottomEnd = CornerSize(0.dp)
390-
)
333+
index == 0 -> MaterialTheme.shapes.medium.copy(
334+
bottomStart = CornerSize(0.dp),
335+
bottomEnd = CornerSize(0.dp)
336+
)
391337

392-
index == favouriteCoins.lastIndex -> MaterialTheme.shapes.medium.copy(
393-
topStart = CornerSize(0.dp),
394-
topEnd = CornerSize(0.dp)
395-
)
338+
index == favouriteCoins.lastIndex -> MaterialTheme.shapes.medium.copy(
339+
topStart = CornerSize(0.dp),
340+
topEnd = CornerSize(0.dp)
341+
)
396342

397-
else -> RoundedCornerShape(0.dp)
398-
}
343+
else -> RoundedCornerShape(0.dp)
344+
}
399345

400-
FavouriteCondensedItem(
401-
favouriteCoin = favouriteCoinItem,
402-
onCoinClick = { onCoinClick(favouriteCoinItem) },
403-
cardShape = cardShape
404-
)
346+
FavouriteCondensedItem(
347+
favouriteCoin = favouriteCoinItem,
348+
onCoinClick = { onCoinClick(favouriteCoinItem) },
349+
cardShape = cardShape,
350+
modifier = Modifier.animateItem(
351+
placementSpec = tween(
352+
durationMillis = 200,
353+
easing = FastOutSlowInEasing
354+
)
355+
)
356+
)
357+
} else {
358+
FavouriteItem(
359+
favouriteCoin = favouriteCoinItem,
360+
onCoinClick = { onCoinClick(favouriteCoinItem) },
361+
modifier = Modifier.animateItem(
362+
placementSpec = tween(
363+
durationMillis = 200,
364+
easing = FastOutSlowInEasing
365+
)
366+
)
367+
)
368+
}
405369
}
406370
)
407371
}
Loading

0 commit comments

Comments
 (0)