更新界面

This commit is contained in:
2024-07-20 16:06:37 +08:00
parent ba1d74f017
commit 82f58d4b9c
16 changed files with 375 additions and 214 deletions

View File

@@ -76,5 +76,8 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
implementation ("com.google.android.libraries.places:places:3.3.0")
implementation (libs.places)
implementation(libs.androidx.animation)
}

View File

@@ -13,12 +13,12 @@ import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -39,13 +39,18 @@ import androidx.compose.ui.unit.sp
@Preview
@Composable
fun CommentModalContent() {
fun CommentModalContent(onDismiss: () -> Unit = {}) {
val insets = WindowInsets
val imePadding = insets.ime.getBottom(density = LocalDensity.current)
var bottomPadding by remember { mutableStateOf(0.dp) }
LaunchedEffect(imePadding) {
bottomPadding = imePadding.dp
}
DisposableEffect(Unit) {
onDispose {
onDismiss()
}
}
Column(
modifier = Modifier.height(500.dp)
@@ -92,8 +97,6 @@ fun CommentModalContent() {
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.clip(RoundedCornerShape(20.dp))
.background(Color(0xffe5e5e5))

View File

@@ -3,24 +3,22 @@ package com.aiosman.riderpro
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.interaction.MutableInteractionSource
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
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.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
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.res.painterResource
import androidx.compose.ui.text.font.FontWeight
@@ -70,7 +68,10 @@ fun NoticeScreenHeader(
Image(
painter = painterResource(id = R.drawable.rider_pro_nav_back),
contentDescription = title,
modifier = Modifier.size(16.dp).clickable {
modifier = Modifier.size(16.dp).clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
nav.popBackStack()
}
)

View File

@@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@@ -30,16 +31,20 @@ import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@@ -47,11 +52,15 @@ import kotlinx.coroutines.launch
fun GalleryPage() {
val pagerState = rememberPagerState(pageCount = { 2 })
val scope = rememberCoroutineScope()
val systemUiController = rememberSystemUiController()
fun switchToPage(page: Int) {
scope.launch {
pagerState.animateScrollToPage(page)
}
}
LaunchedEffect(Unit) {
systemUiController.setNavigationBarColor(Color.Transparent)
}
Scaffold(
topBar = {
TopAppBar(
@@ -148,6 +157,26 @@ fun DashedVerticalLine(modifier: Modifier = Modifier) {
}
}
}
@Composable
fun DashedLine() {
Canvas(modifier = Modifier
.width(1.dp) // 控制线条的宽度
.fillMaxHeight()) { // 填满父容器的高度
val canvasWidth = size.width
val canvasHeight = size.height
// 创建一个PathEffect来定义如何绘制线段
val pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
drawLine(
color = Color.Gray, // 线条颜色
start = Offset(x = canvasWidth / 2, y = 0f), // 起始点
end = Offset(x = canvasWidth / 2, y = canvasHeight), // 终点
pathEffect = pathEffect // 应用虚线效果
)
}
}
@Preview
@Composable
fun TimelineItem() {
@@ -172,12 +201,13 @@ fun TimelineItem() {
Text("12", fontSize = 22.sp, fontWeight = androidx.compose.ui.text.font.FontWeight.Bold)
Text("7月", fontSize = 20.sp,fontWeight = androidx.compose.ui.text.font.FontWeight.Bold)
// add vertical dash line
Box(
modifier = Modifier
.height(120.dp)
.width(3.dp)
.background(Color.Gray)
)
// Box(
// modifier = Modifier
// .height(120.dp)
// .width(3.dp)
// .background(Color.Gray)
// )
DashedLine()
}
Column {
Row(

View File

@@ -0,0 +1,24 @@
package com.aiosman.riderpro
import androidx.lifecycle.ViewModel
private val DATA = (0..60).toList().mapIndexed { idx, _ ->
MomentItem(
id = idx,
avatar = R.drawable.default_avatar,
nickname = "Onyama Limba",
location = "Japan",
time = "2023.02.02 11:23",
followStatus = false,
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
momentPicture = R.drawable.default_moment_img,
likeCount = 21,
commentCount = 43,
shareCount = 33,
favoriteCount = 211
)
}
object HomeViewModel : ViewModel() {
val momentList = DATA
}

View File

@@ -5,16 +5,16 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.animation.SharedTransitionScope
import androidx.compose.animation.animateColorAsState
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
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
@@ -22,27 +22,17 @@ 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.LaunchedEffect
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
@@ -50,20 +40,19 @@ 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.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
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() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
@@ -81,38 +70,32 @@ val LocalNavController = compositionLocalOf<NavHostController> {
error("NavController not provided")
}
@OptIn(ExperimentalSharedTransitionApi::class)
val LocalSharedTransitionScope = compositionLocalOf<SharedTransitionScope> {
error("SharedTransitionScope not provided")
}
val LocalAnimatedContentScope = compositionLocalOf<AnimatedContentScope> {
error("AnimatedContentScope not provided")
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun NavigationController(navController: NavHostController) {
val navigationBarHeight = with(LocalDensity.current) {
WindowInsets.navigationBars.getBottom(this).toDp()
}
NavHost(
navController = navController,
startDestination = "Index",
) {
// 带底部导航栏的路由:
// listOf(
// NavigationItem.Home,
// NavigationItem.Street,
// NavigationItem.Add,
// NavigationItem.Message,
// NavigationItem.Profile
// ).forEach { item ->
// composable(route = item.route) {
// ScaffoldWithNavigationBar(navController) {
// when (item) {
// NavigationItem.Home -> Home()
// NavigationItem.Street -> Street()
// NavigationItem.Add -> Add()
// NavigationItem.Message -> Video()
// NavigationItem.Profile -> Profile()
// else -> {} // 由于过滤,这里不会发生
// }
// }
// }
// }
composable(route = "Index") {
ScaffoldWithNavigationBar2()
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
ScaffoldWithNavigationBar2()
}
}
composable(route = "ProfileTimeline") {
GalleryPage()
@@ -130,26 +113,30 @@ fun NavigationController(navController: NavHostController) {
composable(route = "OfficialPhotographer") {
OfficialPhotographer()
}
composable(route = "Post") {
PostPage()
composable(
route = "Post/{id}",
arguments = listOf(navArgument("id") { type = NavType.StringType })
) { backStackEntry ->
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
val id = backStackEntry.arguments?.getString("id")
PostPage(
id!!
)
}
}
composable(route = "ModificationList") {
ModificationListScreen()
}
composable(route = "MyMessage") {
NotificationsScreen()
}
composable(route = "Comments") {
CommentsScreen()
}
composable(route = "Likes") {
LikePage()
}
composable(route = "Followers") {
FollowerPage()
@@ -165,14 +152,22 @@ fun NavigationController(navController: NavHostController) {
}
}
}
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun Navigation() {
val navController = rememberNavController()
CompositionLocalProvider(LocalNavController provides navController) {
Box {
NavigationController(navController = navController)
SharedTransitionLayout {
CompositionLocalProvider(
LocalNavController provides navController,
LocalSharedTransitionScope provides this@SharedTransitionLayout,
) {
Box {
NavigationController(navController = navController)
}
}
}
}
@@ -271,9 +266,9 @@ fun ScaffoldWithNavigationBar(
}
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun ScaffoldWithNavigationBar2(
) {
fun ScaffoldWithNavigationBar2() {
val model = IndexViewModel
val navigationBarHeight = with(LocalDensity.current) {
WindowInsets.navigationBars.getBottom(this).toDp()
@@ -344,7 +339,10 @@ fun ScaffoldWithNavigationBar2(
when (model.tabIndex) {
0 -> Box(
modifier = Modifier.padding(innerPadding)
) { Home() }
) {
Home()
}
1 -> Street()
2 -> Box(
modifier = Modifier.padding(innerPadding)

View File

@@ -22,6 +22,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -32,12 +33,17 @@ 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.google.accompanist.systemuicontroller.rememberSystemUiController
@Preview(showBackground = true)
@Composable
fun NotificationsScreen() {
val navController = LocalNavController.current
val systemUiController = rememberSystemUiController()
LaunchedEffect(Unit) {
systemUiController.setNavigationBarColor(Color.Transparent)
}
StatusBarMaskLayout(darkIcons = true) {
Column(
modifier = Modifier.fillMaxWidth().weight(1f)

View File

@@ -1,8 +1,6 @@
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
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -10,32 +8,27 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
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
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@Preview
@Composable
fun ModificationListScreen() {
val navController = LocalNavController.current
val systemUiController = rememberSystemUiController()
LaunchedEffect(Unit) {
systemUiController.setNavigationBarColor(Color.Transparent)
}
val modifications = getModifications()
StatusBarMaskLayout {
Column(

View File

@@ -46,7 +46,7 @@ val profileMomentItems = listOf(
shareCount = 33,
favoriteCount = 211),
MomentItem(
id = 1,
id = 2,
avatar = R.drawable.default_avatar,
nickname = "Onyama Limba",
location = "Japan",
@@ -59,7 +59,7 @@ val profileMomentItems = listOf(
shareCount = 33,
favoriteCount = 211),
MomentItem(
id = 1,
id = 3,
avatar = R.drawable.default_avatar,
nickname = "Onyama Limba",
location = "Japan",

View File

@@ -7,6 +7,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -37,7 +38,6 @@ import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
@@ -86,7 +86,10 @@ fun NewPostTopBar() {
Image(
painter = painterResource(id = R.drawable.rider_pro_close),
contentDescription = "Back",
modifier = Modifier.size(24.dp).clickable {
modifier = Modifier.size(24.dp).clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
navController.popBackStack()
}
)
@@ -172,7 +175,10 @@ fun AddImageGrid() {
.drawBehind {
drawRoundRect(color = Color(0xFF999999), style = stroke)
}
.clickable {
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
Intent(Intent.ACTION_PICK).apply {
type = "image/*"
pickImageLauncher.launch(this)
@@ -228,7 +234,10 @@ fun AdditionalPostItem() {
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp, horizontal = 24.dp)
.clickable {
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
onSelectLocationClick()
}
) {
@@ -258,7 +267,10 @@ fun AdditionalPostItem() {
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp, horizontal = 24.dp)
.clickable {
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
navController.navigate("EditModification")
}
) {
@@ -311,7 +323,10 @@ fun SelectedLocation(
contentDescription = "Next",
modifier = Modifier
.size(24.dp)
.clickable {
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
onRemoveLocation()
}
)

View File

@@ -1,11 +1,11 @@
package com.aiosman.riderpro
import androidx.annotation.DrawableRes
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.fillMaxHeight
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
@@ -26,7 +25,6 @@ import androidx.compose.material.icons.filled.Build
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
@@ -39,67 +37,89 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.paging.LoadState
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.compose.collectAsLazyPagingItems
import com.google.accompanist.systemuicontroller.rememberSystemUiController
private val DATA = (0..60).toList().map { momentTestItem }
private val DATA = (0..60).toList().mapIndexed { idx, _ ->
MomentItem(
id = idx,
avatar = R.drawable.default_avatar,
nickname = "Onyama Limba",
location = "Japan",
time = "2023.02.02 11:23",
followStatus = false,
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
momentPicture = R.drawable.default_moment_img,
likeCount = 21,
commentCount = 43,
shareCount = 33,
favoriteCount = 211
)
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun PagingBackendSample() {
val myBackend = remember { TestBackend(DATA) }
val pager = remember {
Pager(
PagingConfig(
pageSize = myBackend.DataBatchSize,
enablePlaceholders = true,
maxSize = 200
)
) {
myBackend.getAllData()
}
}
val lazyPagingItems = pager.flow.collectAsLazyPagingItems()
// val myBackend = remember { TestBackend(DATA) }
// val pager = remember {
// Pager(
// PagingConfig(
// pageSize = myBackend.DataBatchSize,
// enablePlaceholders = true,
// maxSize = 200
// )
// ) {
// myBackend.getAllData()
// }
// }
val model = HomeViewModel
// val lazyPagingItems = model.pager.collectAsLazyPagingItems()
LazyColumn {
if (lazyPagingItems.loadState.refresh == LoadState.Loading) {
item {
MomentListLoading()
}
}
items(count = lazyPagingItems.itemCount) { index ->
val item = lazyPagingItems[index]
// if (lazyPagingItems.loadState.refresh == LoadState.Loading) {
// item {
// MomentListLoading()
// }
// }
items(count = model.momentList.size) { index ->
val item = model.momentList.getOrNull(index)
if (item != null) {
MomentCard(item)
}
}
if (lazyPagingItems.loadState.append == LoadState.Loading) {
item {
MomentListLoading()
}
}
// if (lazyPagingItems.loadState.append == LoadState.Loading) {
// item {
// MomentListLoading()
// }
// }
}
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun MomentCard(momentItem: MomentItem) {
fun MomentCard(
momentItem: MomentItem,
) {
val navController = LocalNavController.current
Column(
modifier = Modifier.fillMaxWidth()
) {
MomentTopRowGroup(momentItem = momentItem)
MomentContentGroup(momentItem = momentItem)
Column(
modifier = Modifier
.fillMaxWidth()
.clickable {
navController.navigate("Post/${momentItem.id}")
}
) {
MomentContentGroup(momentItem = momentItem)
}
val momentOperateBtnBoxModifier = Modifier
.fillMaxHeight()
.weight(1f)
@@ -121,7 +141,10 @@ fun ModificationListHeader() {
.fillMaxWidth()
.background(Color(0xFFF8F8F8))
.padding(4.dp)
.clickable {
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
navController.navigate("ModificationList")
}
) {
@@ -239,21 +262,37 @@ fun MomentTopRowGroup(momentItem: MomentItem) {
}
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun MomentContentGroup(momentItem: MomentItem) {
Text(
text = momentItem.momentTextContent,
modifier = Modifier
.fillMaxWidth()
.padding(top = 22.dp, bottom = 16.dp, start = 24.dp, end = 24.dp),
fontSize = 16.sp
)
Image(
modifier = Modifier
.fillMaxWidth(),
painter = painterResource(id = momentItem.momentPicture),
contentDescription = ""
)
fun MomentContentGroup(
momentItem: MomentItem,
) {
val sharedTransitionScope = LocalSharedTransitionScope.current
val animatedContentScope = LocalAnimatedContentScope.current
with(sharedTransitionScope) {
Text(
text = momentItem.momentTextContent,
modifier = Modifier
.sharedElement(
sharedTransitionScope.rememberSharedContentState(key = "text-${momentItem.id}"),
animatedVisibilityScope = animatedContentScope
)
.fillMaxWidth()
.padding(top = 22.dp, bottom = 16.dp, start = 24.dp, end = 24.dp),
fontSize = 16.sp
)
Image(
modifier = Modifier
.sharedElement(
sharedTransitionScope.rememberSharedContentState(key = "image-${momentItem.id}"),
animatedVisibilityScope = animatedContentScope
)
.fillMaxWidth(),
painter = painterResource(id = momentItem.momentPicture),
contentDescription = ""
)
}
}
@Composable
@@ -276,6 +315,7 @@ fun MomentOperateBtn(@DrawableRes icon: Int, count: String) {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MomentBottomOperateRowGroup(modifier: Modifier) {
var systemUiController = rememberSystemUiController()
var showCommentModal by remember { mutableStateOf(false) }
if (showCommentModal) {
ModalBottomSheet(
@@ -285,7 +325,10 @@ fun MomentBottomOperateRowGroup(modifier: Modifier) {
skipPartiallyExpanded = true
)
) {
CommentModalContent()
systemUiController.setNavigationBarColor(Color(0xfff7f7f7))
CommentModalContent() {
systemUiController.setNavigationBarColor(Color.Black)
}
}
}
Row(
@@ -300,7 +343,10 @@ fun MomentBottomOperateRowGroup(modifier: Modifier) {
MomentOperateBtn(icon = R.drawable.rider_pro_like, count = "21")
}
Box(
modifier = modifier.clickable {
modifier = modifier.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
showCommentModal = true
},
contentAlignment = Alignment.Center

View File

@@ -1,6 +1,7 @@
package com.aiosman.riderpro
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
@@ -39,7 +40,6 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -54,7 +54,6 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
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 kotlinx.coroutines.launch
@@ -67,12 +66,14 @@ fun makeMockImages(): List<PostImage> {
)
}
@Preview
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun PostPage() {
fun PostPage(
id: String,
) {
var showCollapseContent by remember { mutableStateOf(true) }
val scrollState = rememberLazyListState()
StatusBarMaskLayout {
Scaffold(
modifier = Modifier.fillMaxSize(),
@@ -91,9 +92,15 @@ fun PostPage() {
.aspectRatio(1f)
) {
PostImageView(makeMockImages())
PostImageView(
id,
makeMockImages(),
)
}
PostDetails()
PostDetails(
id,
)
}
}
}
@@ -109,6 +116,7 @@ fun PostPage() {
}
}
}
}
@Composable
@@ -163,62 +171,85 @@ data class PostImage(
val description: String
)
@OptIn(ExperimentalFoundationApi::class)
@OptIn(ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class)
@Composable
fun PostImageView(images: List<PostImage>) {
fun PostImageView(
postId: String,
images: List<PostImage>,
) {
val sharedTransitionScope = LocalSharedTransitionScope.current
val animatedContentScope = LocalAnimatedContentScope.current
val pagerState = rememberPagerState(pageCount = { images.size })
Column {
HorizontalPager(
state = pagerState,
modifier = Modifier
.weight(1f)
.fillMaxWidth()
) { page ->
Image(
painter = painterResource(id = images[page].imgRes),
contentDescription = images[page].description,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
}
// Indicator container
Row(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
images.forEachIndexed { index, _ ->
Box(
modifier = Modifier
.size(8.dp)
.clip(CircleShape)
.background(
if (pagerState.currentPage == index) Color.Red else Color.Gray.copy(
alpha = 0.5f
)
with(sharedTransitionScope) {
Column {
HorizontalPager(
state = pagerState,
modifier = Modifier
.weight(1f)
.fillMaxWidth()
) { page ->
Image(
painter = painterResource(id = images[page].imgRes),
contentDescription = images[page].description,
contentScale = ContentScale.Crop,
modifier = Modifier.Companion
.sharedElement(
sharedTransitionScope.rememberSharedContentState(key = "image-$postId"),
animatedVisibilityScope = animatedContentScope
)
.padding(4.dp)
.fillMaxSize()
)
Spacer(modifier = Modifier.width(8.dp))
}
// Indicator container
Row(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
images.forEachIndexed { index, _ ->
Box(
modifier = Modifier
.size(8.dp)
.clip(CircleShape)
.background(
if (pagerState.currentPage == index) Color.Red else Color.Gray.copy(
alpha = 0.5f
)
)
.padding(4.dp)
)
Spacer(modifier = Modifier.width(8.dp))
}
}
}
}
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun PostDetails() {
fun PostDetails(
postId: String,
) {
val sharedTransitionScope = LocalSharedTransitionScope.current
val animatedContentScope = LocalAnimatedContentScope.current
with(sharedTransitionScope) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = "这里太适合骑行了", fontSize = 16.sp, fontWeight = FontWeight.Bold)
Text(text = "By strongarming Ducati into giving him the factory seat.Marquez effectively …", fontSize = 16.sp, fontWeight = FontWeight.Bold, modifier = Modifier.Companion.sharedElement(
sharedTransitionScope.rememberSharedContentState(key = "text-$postId"),
animatedVisibilityScope = animatedContentScope
))
Text(text = "12-11 发布")
Spacer(modifier = Modifier.height(8.dp))
Text(text = "共231条评论")
}
}
}
fun MakeMockComments(): List<Comment> {
return listOf(
@@ -374,7 +405,10 @@ fun MakeMockComments(): List<Comment> {
}
@Composable
fun CommentsSection(scrollState: LazyListState = rememberLazyListState(), onWillCollapse: (Boolean) -> Unit) {
fun CommentsSection(
scrollState: LazyListState = rememberLazyListState(),
onWillCollapse: (Boolean) -> Unit
) {
val items = MakeMockComments()
LazyColumn(
state = scrollState, modifier = Modifier

View File

@@ -1,6 +1,5 @@
package com.aiosman.riderpro
import android.app.Activity
import android.net.Uri
import android.view.Gravity
import android.view.ViewGroup
@@ -15,24 +14,28 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
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.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
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.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
@@ -53,7 +56,6 @@ import androidx.media3.common.util.Util
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultDataSourceFactory
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.SimpleExoPlayer
import androidx.media3.exoplayer.source.ProgressiveMediaSource
import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.PlayerView
@@ -174,7 +176,7 @@ fun VideoPlayer(
hideController()
useController = false
player = exoPlayer
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL // 或 RESIZE_MODE_ZOOM
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT // 或 RESIZE_MODE_ZOOM
layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,

View File

@@ -2,10 +2,10 @@ package com.aiosman.riderpro
import androidx.paging.PagingSource
import androidx.paging.PagingState
import kotlin.math.ceil
import kotlinx.coroutines.delay
import kotlin.math.ceil
internal class TestBackend(
class TestBackend(
private val backendDataList: List<MomentItem>,
private val loadDelay: Long = 500,
) {
@@ -24,7 +24,7 @@ internal class TestBackend(
}
fun getAllData() = TestPagingSource(this, loadDelay)
}
internal class TestPagingSource(
class TestPagingSource(
private val backend: TestBackend,
private val loadDelay: Long,
) : PagingSource<Int, MomentItem>() {

View File

@@ -6,6 +6,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -19,7 +20,6 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -142,7 +142,10 @@ fun StreetPage() {
contentDescription = "",
modifier = Modifier
.align(Alignment.BottomStart)
.padding(start = 16.dp, bottom = 16.dp + navigationBarHeight) .clickable {
.padding(start = 16.dp, bottom = 16.dp + navigationBarHeight) .clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
currentLocation?.let {
cameraPositionState.position = CameraPosition.fromLatLngZoom(it, cameraPositionState.position.zoom)
}

View File

@@ -1,6 +1,7 @@
[versions]
accompanistSystemuicontroller = "0.27.0"
agp = "8.4.0"
animation = "1.7.0-beta05"
kotlin = "1.9.0"
coreKtx = "1.10.1"
junit = "4.13.2"
@@ -8,7 +9,7 @@ junitVersion = "1.1.5"
espressoCore = "3.5.1"
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
composeBom = "2023.08.00"
composeBom = "2024.06.00"
mapsCompose = "4.3.3"
material3Android = "1.2.1"
media3Exoplayer = "1.3.1"
@@ -16,9 +17,11 @@ navigationCompose = "2.7.7"
pagingRuntime = "3.3.0"
activityKtx = "1.9.0"
lifecycleCommonJvm = "2.8.2"
places = "3.3.0"
[libraries]
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanistSystemuicontroller" }
androidx-animation = { module = "androidx.compose.animation:animation", version.ref = "animation" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3Exoplayer" }
androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "media3Exoplayer" }
@@ -43,7 +46,7 @@ androidx-material3-android = { group = "androidx.compose.material3", name = "mat
maps-compose = { module = "com.google.maps.android:maps-compose", version.ref = "mapsCompose" }
androidx-activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref = "activityKtx" }
androidx-lifecycle-common-jvm = { group = "androidx.lifecycle", name = "lifecycle-common-jvm", version.ref = "lifecycleCommonJvm" }
places = { module = "com.google.android.libraries.places:places", version.ref = "places" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }