From 5b530f3ef6e60cbffb32a6e9413500af2136f3ad Mon Sep 17 00:00:00 2001 From: AllenTom Date: Wed, 17 Jul 2024 14:35:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/aiosman/riderpro/LikePage.kt | 48 ++- .../com/aiosman/riderpro/LikePageViewModel.kt | 65 ++++ .../com/aiosman/riderpro/LocationDetail.kt | 9 +- .../java/com/aiosman/riderpro/MainActivity.kt | 57 +-- .../com/aiosman/riderpro/MockDataSource.kt | 31 ++ .../com/aiosman/riderpro/ModificationList.kt | 49 +-- .../com/aiosman/riderpro/OfficialGallery.kt | 23 +- .../aiosman/riderpro/OfficialPhotographer.kt | 364 +++++++++--------- 8 files changed, 393 insertions(+), 253 deletions(-) create mode 100644 app/src/main/java/com/aiosman/riderpro/LikePageViewModel.kt create mode 100644 app/src/main/java/com/aiosman/riderpro/MockDataSource.kt diff --git a/app/src/main/java/com/aiosman/riderpro/LikePage.kt b/app/src/main/java/com/aiosman/riderpro/LikePage.kt index b5decf9..0edf57e 100644 --- a/app/src/main/java/com/aiosman/riderpro/LikePage.kt +++ b/app/src/main/java/com/aiosman/riderpro/LikePage.kt @@ -6,18 +6,21 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.asPaddingValues -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -30,6 +33,23 @@ import androidx.compose.ui.unit.sp @Preview @Composable fun LikePage() { + val model = LikePageViewModel + val coroutineScope = rememberCoroutineScope() + val listState = rememberLazyListState() + + // observe list scrolling + val reachedBottom: Boolean by remember { + derivedStateOf { + val lastVisibleItem = listState.layoutInfo.visibleItemsInfo.lastOrNull() + lastVisibleItem?.index != 0 && lastVisibleItem?.index == listState.layoutInfo.totalItemsCount - 3 + } + } + LaunchedEffect(Unit) { + model.loader.loadData() + } + LaunchedEffect(reachedBottom) { + if (reachedBottom) model.loader.loadMore() + } StatusBarMaskLayout( darkIcons = true, maskBoxBackgroundColor = Color(0xFFFFFFFF) @@ -43,26 +63,28 @@ fun LikePage() { NoticeScreenHeader("LIKES") Spacer(modifier = Modifier.height(28.dp)) LazyColumn( - modifier = Modifier.weight(1f) - ) { - item { - repeat(20) { - LikeItem() + modifier = Modifier.weight(1f), + state = listState, - } + ) { + items(model.loader.list, key = { it.id }) { + LikeItem(it) + } + item { BottomNavigationPlaceholder() } - } + } } + } @Composable -fun LikeItem() { +fun LikeItem(itemData: LikeItemData) { Box( modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp) ) { @@ -79,7 +101,7 @@ fun LikeItem() { Column( modifier = Modifier.weight(1f) ) { - Text("Username", fontWeight = FontWeight.Bold, fontSize = 16.sp) + Text(itemData.name, fontWeight = FontWeight.Bold, fontSize = 16.sp) Spacer(modifier = Modifier.height(5.dp)) Text("Username", fontSize = 12.sp, color = Color(0x99000000)) } diff --git a/app/src/main/java/com/aiosman/riderpro/LikePageViewModel.kt b/app/src/main/java/com/aiosman/riderpro/LikePageViewModel.kt new file mode 100644 index 0000000..8976afa --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/LikePageViewModel.kt @@ -0,0 +1,65 @@ +package com.aiosman.riderpro + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel + +class LikeDataSource : MockDataSource() { + init { + var newList = mutableListOf() + for (i in 0..999) { + newList.add(LikeItemData(i, "Like $i")) + } + list = newList + } +} +abstract class DataLoader { + var list = mutableListOf() + var page by mutableStateOf(1) + var pageSize by mutableStateOf(20) + var total by mutableStateOf(0) + var noMoreData by mutableStateOf(false) + + suspend fun loadData() { + val resp = fetchData(page, pageSize) + if (resp.success) { + resp.data?.let { + total = it.total + list = it.list.toMutableList() + if (it.list.size < pageSize) { + noMoreData = true + } + } + } + } + suspend fun loadMore(){ + if (list.size >= total) return + page++ + val resp = fetchData(page, pageSize) + if (resp.success) { + resp.data?.let { + total = it.total + list.addAll(it.list) + if (it.list.size < pageSize) { + noMoreData = true + } + } + } + } + abstract suspend fun fetchData(page: Int, pageSize: Int): MockDataContainer> +} +class LikeListLoader : DataLoader() { + var mockDataSource = LikeDataSource() + override suspend fun fetchData(page: Int, pageSize: Int): MockDataContainer> { + return mockDataSource.fetchData(page, pageSize) + } +} +object LikePageViewModel : ViewModel() { + val loader = LikeListLoader() +} + +data class LikeItemData( + val id: Int, + val name: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/LocationDetail.kt b/app/src/main/java/com/aiosman/riderpro/LocationDetail.kt index ab931ae..48b4aa3 100644 --- a/app/src/main/java/com/aiosman/riderpro/LocationDetail.kt +++ b/app/src/main/java/com/aiosman/riderpro/LocationDetail.kt @@ -17,7 +17,6 @@ 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.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -34,7 +33,6 @@ import androidx.compose.material3.BottomSheetScaffold import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SheetState import androidx.compose.material3.SheetValue @@ -43,7 +41,6 @@ import androidx.compose.material3.rememberBottomSheetScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -54,8 +51,6 @@ 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.layout.onGloballyPositioned -import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource @@ -64,7 +59,6 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import kotlinx.coroutines.launch data class OfficialGalleryItem( val id: Int, @@ -153,6 +147,7 @@ fun LocationDetail() { // Assuming index 0 corresponds to the top of the feed showGalleryAndInfo = index == 0 } + } Box( modifier = Modifier.fillMaxSize() @@ -200,6 +195,7 @@ fun LocationDetail() { ) } + Spacer(modifier = Modifier.height(16.dp)) GalleryAndInfo(showGalleryAndInfo) // feed @@ -234,6 +230,7 @@ fun LocationDetail() { contentPadding = PaddingValues(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp), flingBehavior = ScrollableDefaults.flingBehavior(), + ) { items(feedItems) { item -> Column( diff --git a/app/src/main/java/com/aiosman/riderpro/MainActivity.kt b/app/src/main/java/com/aiosman/riderpro/MainActivity.kt index 6b784a5..52388ec 100644 --- a/app/src/main/java/com/aiosman/riderpro/MainActivity.kt +++ b/app/src/main/java/com/aiosman/riderpro/MainActivity.kt @@ -8,6 +8,7 @@ import androidx.activity.enableEdgeToEdge import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -20,16 +21,26 @@ import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItemColors import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRow +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -37,6 +48,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.view.WindowCompat +import androidx.navigation.NavGraph import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -45,6 +57,7 @@ import androidx.navigation.compose.rememberNavController import com.aiosman.riderpro.ui.theme.RiderProTheme import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.android.libraries.places.api.Places +import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { @@ -73,12 +86,7 @@ fun NavigationController(navController: NavHostController) { NavHost( navController = navController, startDestination = NavigationItem.Home.route, - enterTransition = { - fadeIn(animationSpec = tween(0)) - }, - exitTransition = { - fadeOut(animationSpec = tween(0)) - }) { + ) { // 带底部导航栏的路由: listOf( NavigationItem.Home, @@ -111,11 +119,7 @@ fun NavigationController(navController: NavHostController) { } } composable(route = "OfficialPhoto") { - Box( - modifier = Modifier.padding(bottom = navigationBarHeight) - ) { - OfficialGalleryPage() - } + OfficialGalleryPage() } composable(route = "OfficialPhotographer") { OfficialPhotographer() @@ -128,11 +132,7 @@ fun NavigationController(navController: NavHostController) { } } composable(route = "ModificationList") { - Box( - modifier = Modifier.padding(bottom = navigationBarHeight) - ) { - ModificationListScreen() - } + ModificationListScreen() } composable(route = "MyMessage") { @@ -205,26 +205,31 @@ fun ScaffoldWithNavigationBar( NavigationBarItem( selected = currentRoute == it.route, onClick = { + // Check if the current route is not the same as the tab's route to avoid unnecessary navigation if (currentRoute != it.route) { - navController.navigate(it.route) + navController.navigate(it.route) { + // Avoid creating a new layer on top of the navigation stack + launchSingleTop = true + // Attempt to pop up to the existing instance of the destination, if present + popUpTo(navController.graph.startDestinationId) { + saveState = true + } + // Restore state when navigating back to the composable + restoreState = true + } } + // Additional logic for system UI color changes when (it.route) { NavigationItem.Add.route -> { - systemUiController.setSystemBarsColor( - color = Color.Black - ) + systemUiController.setSystemBarsColor(color = Color.Black) } NavigationItem.Message.route -> { - systemUiController.setSystemBarsColor( - color = Color.Black - ) + systemUiController.setSystemBarsColor(color = Color.Black) } else -> { - systemUiController.setSystemBarsColor( - color = Color.Transparent - ) + systemUiController.setSystemBarsColor(color = Color.Transparent) } } }, diff --git a/app/src/main/java/com/aiosman/riderpro/MockDataSource.kt b/app/src/main/java/com/aiosman/riderpro/MockDataSource.kt new file mode 100644 index 0000000..18c9313 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/MockDataSource.kt @@ -0,0 +1,31 @@ +package com.aiosman.riderpro + +import kotlin.math.min + +class MockDataContainer( + val success: Boolean, + val data: T? +) { + +} + +class MockListContainer( + val total: Int, + val page: Int, + val pageSize: Int, + val list: List +) { + +} + +abstract class MockDataSource { + var list = mutableListOf() + suspend fun fetchData(page: Int, pageSize: Int): MockDataContainer> { + // over page return empty + if (page * pageSize > list.size) { + return MockDataContainer(false, MockListContainer(0, page, pageSize, emptyList())) + } + val backData = list.subList((page - 1) * pageSize, min(page * pageSize, list.size)) + return MockDataContainer(true, MockListContainer(list.size, page, pageSize, backData)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/ModificationList.kt b/app/src/main/java/com/aiosman/riderpro/ModificationList.kt index f13909a..3da4f7f 100644 --- a/app/src/main/java/com/aiosman/riderpro/ModificationList.kt +++ b/app/src/main/java/com/aiosman/riderpro/ModificationList.kt @@ -1,4 +1,5 @@ import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -23,44 +24,45 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.aiosman.riderpro.BottomNavigationPlaceholder import com.aiosman.riderpro.LocalNavController +import com.aiosman.riderpro.NoticeScreenHeader import com.aiosman.riderpro.R +import com.aiosman.riderpro.StatusBarMask +import com.aiosman.riderpro.StatusBarMaskLayout -@OptIn(ExperimentalMaterial3Api::class) @Preview @Composable fun ModificationListScreen() { val navController = LocalNavController.current val modifications = getModifications() - Column(modifier = Modifier.fillMaxSize().background(Color(0xFFF8F8F8))) { - TopAppBar( - title = { Text("Modification List") }, - navigationIcon = { - IconButton(onClick = { - navController.popBackStack() - }) { - Icon( - painter = painterResource(id = R.drawable.rider_pro_nav_back), // Replace with your back icon - contentDescription = "Back" - ) + StatusBarMaskLayout { + Column( + modifier = Modifier + .weight(1f) + .padding(horizontal = 16.dp) + .background(Color(0xFFF8F8F8)) + + ) { + NoticeScreenHeader("Modification List") + Spacer(modifier = Modifier.height(8.dp)) + LazyColumn(modifier = Modifier.padding(16.dp)) { + items(modifications.size) { index -> + val modification = modifications[index] + ModificationItem(name = modification.name, price = modification.price) + Spacer(modifier = Modifier.height(8.dp)) + } + item { + BottomNavigationPlaceholder() } - }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = Color(0xFFF8F8F8), - ) - ) - Spacer(modifier = Modifier.height(8.dp)) - LazyColumn(modifier = Modifier.padding(16.dp)) { - items(modifications.size) { index -> - val modification = modifications[index] - ModificationItem(name = modification.name, price = modification.price) - Spacer(modifier = Modifier.height(8.dp)) } } } } + data class Modification(val name: String, val price: String) + fun getModifications(): List { return listOf( Modification("Modification name", "$74.00"), @@ -85,6 +87,7 @@ fun getModifications(): List { Modification("Modification name", "$74.00"), ) } + @Composable fun ModificationItem(name: String, price: String) { Card( diff --git a/app/src/main/java/com/aiosman/riderpro/OfficialGallery.kt b/app/src/main/java/com/aiosman/riderpro/OfficialGallery.kt index d82b282..fff1963 100644 --- a/app/src/main/java/com/aiosman/riderpro/OfficialGallery.kt +++ b/app/src/main/java/com/aiosman/riderpro/OfficialGallery.kt @@ -36,16 +36,18 @@ import androidx.compose.ui.unit.sp @Preview @Composable fun OfficialGalleryPage() { - Column( - modifier = Modifier - .fillMaxSize() - .padding(top = 16.dp, start = 16.dp, end = 16.dp) - ) { - OfficialGalleryPageHeader() -// CertificationSection() - Spacer(modifier = Modifier.height(16.dp)) - ImageGrid() + StatusBarMaskLayout { + Column( + modifier = Modifier + .fillMaxSize() + .padding(start = 16.dp, end = 16.dp) + ) { + OfficialGalleryPageHeader() + Spacer(modifier = Modifier.height(16.dp)) + ImageGrid() + } } + } @Composable @@ -141,6 +143,9 @@ fun ImageGrid() { items(photographers.size) { index -> PhotographerCard(photographers[index].first, photographers[index].second) } + item{ + BottomNavigationPlaceholder() + } } } diff --git a/app/src/main/java/com/aiosman/riderpro/OfficialPhotographer.kt b/app/src/main/java/com/aiosman/riderpro/OfficialPhotographer.kt index fc1cb95..31c5124 100644 --- a/app/src/main/java/com/aiosman/riderpro/OfficialPhotographer.kt +++ b/app/src/main/java/com/aiosman/riderpro/OfficialPhotographer.kt @@ -84,196 +84,208 @@ fun OfficialPhotographer() { alp } } - Scaffold { paddingValues -> - - Box( - modifier = Modifier - .background(Color.Black) - .padding(paddingValues) - - ) { - LazyColumn( - modifier = Modifier.fillMaxSize(), - state = lazyListState - ) { - item { - Box( - modifier = Modifier - .height(400.dp) - .fillMaxWidth() - ) { - Image( - painter = painterResource(id = R.drawable.default_moment_img), - contentDescription = "Logo", - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize() - ) - // top bar - - // on bottom of box - Box( - modifier = Modifier - .fillMaxWidth() - .height(120.dp) - .background( - brush = Brush.verticalGradient( - colors = listOf( - Color.Black.copy(alpha = 1f), - Color.Black.copy(alpha = 1f), - Color.Black.copy(alpha = 0f), - ), - startY = Float.POSITIVE_INFINITY, - endY = 0f - ) - ) - .padding(16.dp) - .align(alignment = androidx.compose.ui.Alignment.BottomCenter) - - ) { - Column( - modifier = Modifier.fillMaxSize(), - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .weight(1f), - verticalAlignment = Alignment.CenterVertically - ) { - Image( - painter = painterResource(id = R.drawable.default_avatar), - contentDescription = "", - modifier = Modifier - .size(32.dp) - .clip(CircleShape) // Clip the image to a circle - ) - Spacer(modifier = Modifier.width(8.dp)) - // name - Text("Onyama Limba", color = Color.White, fontSize = 14.sp) - Spacer(modifier = Modifier.width(8.dp)) - // round box - Box( - modifier = Modifier - .background(Color.Red, CircleShape) - .padding(horizontal = 8.dp, vertical = 4.dp) - ) { - // certification - Text("摄影师", color = Color.White, fontSize = 12.sp) - } - Spacer(modifier = Modifier.weight(1f)) - IconButton( - onClick = { /*TODO*/ }, - modifier = Modifier.size(32.dp) - ) { - Icon( - imageVector = Icons.Filled.Favorite, - contentDescription = null, - tint = Color.White - ) - } - Spacer(modifier = Modifier.width(4.dp)) - Text("123", color = Color.White) - Spacer(modifier = Modifier.width(8.dp)) - IconButton( - onClick = {}, - modifier = Modifier.size(32.dp) - ) { - Image( - painter = painterResource(id = R.drawable.rider_pro_eye), - contentDescription = "", - modifier = Modifier - .size(24.dp) - ) - } - Spacer(modifier = Modifier.width(4.dp)) - Text("123", color = Color.White) - - } - Box( - modifier = Modifier - .fillMaxWidth() - .weight(1f) - ) { - // description - Text( - "摄影师 Diego Morata 的作品", - color = Color.White, - modifier = Modifier.align(Alignment.Center) - ) - } - } - - // circle avatar - - } - - } - val screenWidth = LocalConfiguration.current.screenWidthDp.dp - val imageSize = - (screenWidth - (4.dp * 4)) / 3 // Subtracting total padding and divi - val itemWidth = screenWidth / 3 - 4.dp * 2 - FlowRow( - modifier = Modifier.padding(4.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalArrangement = Arrangement.spacedBy(4.dp), - maxItemsInEachRow = 3 - ) { - for (artWork in artWorks) { - Box( - modifier = Modifier - .width(itemWidth) - .aspectRatio(1f) - .background(Color.Gray) - ) { - Image( - painter = painterResource(id = artWork.resId), - contentDescription = "", - contentScale = ContentScale.Crop, - modifier = Modifier - .width(imageSize) - .aspectRatio(1f) - ) - } - } - - } - } - } + StatusBarMaskLayout( + maskBoxBackgroundColor = Color.Black, + darkIcons = false + ) { + Column { Box( modifier = Modifier - .fillMaxWidth() - .height(64.dp) - .background(Color.Black.copy(alpha = alpha)) - .padding(horizontal = 16.dp) + .background(Color.Black) + + ) { - Row( + LazyColumn( modifier = Modifier.fillMaxSize(), - verticalAlignment = androidx.compose.ui.Alignment.CenterVertically, + state = lazyListState ) { - Image( - painter = painterResource(id = R.drawable.rider_pro_nav_back), - colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(Color.White), - contentDescription = "", - modifier = Modifier - .size(32.dp) - .clip(CircleShape) // Clip the image to a circle - ) - if (alpha == 1f) { - Spacer(modifier = Modifier.width(8.dp)) + item { + Box( + modifier = Modifier + .height(400.dp) + .fillMaxWidth() + ) { + Image( + painter = painterResource(id = R.drawable.default_moment_img), + contentDescription = "Logo", + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize() + ) + // dark alpha overlay + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = alpha)) + ) + + // on bottom of box + Box( + modifier = Modifier + .fillMaxWidth() + .height(120.dp) + .background( + brush = Brush.verticalGradient( + colors = listOf( + Color.Black.copy(alpha = 1f), + Color.Black.copy(alpha = 1f), + Color.Black.copy(alpha = 0f), + ), + startY = Float.POSITIVE_INFINITY, + endY = 0f + ) + ) + .padding(16.dp) + .align(alignment = androidx.compose.ui.Alignment.BottomCenter) + + ) { + Column( + modifier = Modifier.fillMaxSize(), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .weight(1f), + verticalAlignment = Alignment.CenterVertically + ) { + Image( + painter = painterResource(id = R.drawable.default_avatar), + contentDescription = "", + modifier = Modifier + .size(32.dp) + .clip(CircleShape) // Clip the image to a circle + ) + Spacer(modifier = Modifier.width(8.dp)) + // name + Text("Onyama Limba", color = Color.White, fontSize = 14.sp) + Spacer(modifier = Modifier.width(8.dp)) + // round box + Box( + modifier = Modifier + .background(Color.Red, CircleShape) + .padding(horizontal = 8.dp, vertical = 4.dp) + ) { + // certification + Text("摄影师", color = Color.White, fontSize = 12.sp) + } + Spacer(modifier = Modifier.weight(1f)) + IconButton( + onClick = { /*TODO*/ }, + modifier = Modifier.size(32.dp) + ) { + Icon( + imageVector = Icons.Filled.Favorite, + contentDescription = null, + tint = Color.White + ) + } + Spacer(modifier = Modifier.width(4.dp)) + Text("123", color = Color.White) + Spacer(modifier = Modifier.width(8.dp)) + IconButton( + onClick = {}, + modifier = Modifier.size(32.dp) + ) { + Image( + painter = painterResource(id = R.drawable.rider_pro_eye), + contentDescription = "", + modifier = Modifier + .size(24.dp) + ) + } + Spacer(modifier = Modifier.width(4.dp)) + Text("123", color = Color.White) + + } + Box( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + ) { + // description + Text( + "摄影师 Diego Morata 的作品", + color = Color.White, + modifier = Modifier.align(Alignment.Center) + ) + } + } + + // circle avatar + + } + + + } + val screenWidth = LocalConfiguration.current.screenWidthDp.dp + val imageSize = + (screenWidth - (4.dp * 4)) / 3 // Subtracting total padding and divi + val itemWidth = screenWidth / 3 - 4.dp * 2 + FlowRow( + modifier = Modifier.padding(4.dp), + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalArrangement = Arrangement.spacedBy(4.dp), + maxItemsInEachRow = 3 + ) { + for (artWork in artWorks) { + Box( + modifier = Modifier + .width(itemWidth) + .aspectRatio(1f) + .background(Color.Gray) + ) { + Image( + painter = painterResource(id = artWork.resId), + contentDescription = "", + contentScale = ContentScale.Crop, + modifier = Modifier + .width(imageSize) + .aspectRatio(1f) + ) + } + } + BottomNavigationPlaceholder() + + } + } + } + Box( + modifier = Modifier + .fillMaxWidth() + .height(64.dp) + .background(Color.Black.copy(alpha = alpha)) + .padding(horizontal = 16.dp) + ) { + Row( + modifier = Modifier.fillMaxSize(), + verticalAlignment = androidx.compose.ui.Alignment.CenterVertically, + ) { Image( - painter = painterResource(id = R.drawable.default_avatar), + painter = painterResource(id = R.drawable.rider_pro_nav_back), + colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(Color.White), contentDescription = "", modifier = Modifier .size(32.dp) .clip(CircleShape) // Clip the image to a circle - ) - Spacer(modifier = Modifier.width(8.dp)) - Text("Onyama Limba", color = Color.White) + if (alpha == 1f) { + Spacer(modifier = Modifier.width(8.dp)) + Image( + painter = painterResource(id = R.drawable.default_avatar), + contentDescription = "", + modifier = Modifier + .size(32.dp) + .clip(CircleShape) // Clip the image to a circle + + ) + Spacer(modifier = Modifier.width(8.dp)) + Text("Onyama Limba", color = Color.White) + } } + } - } - } + } } + } \ No newline at end of file