界面调整、以及修复bug等
-收藏界面和动态界面添加了多图角标和视频角标 -短视频新增双击点赞和双击取消点赞功能 -修复帖子详情页的多图内容不能左右滑动图片,去掉帖子详情页多图下通过Next和Previous按钮来切换图片 -评论框界面调整
This commit is contained in:
@@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.ime
|
import androidx.compose.foundation.layout.ime
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
@@ -31,6 +32,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
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.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
@@ -79,8 +81,9 @@ class CommentModalViewModel(
|
|||||||
fun CommentModalContent(
|
fun CommentModalContent(
|
||||||
postId: Int? = null,
|
postId: Int? = null,
|
||||||
commentCount: Int = 0,
|
commentCount: Int = 0,
|
||||||
onCommentAdded: () -> Unit = {},
|
onDismiss: () -> Unit = {},
|
||||||
onDismiss: () -> Unit = {}
|
showTitle: Boolean = true,
|
||||||
|
onCommentAdded: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val model = viewModel<CommentModalViewModel>(
|
val model = viewModel<CommentModalViewModel>(
|
||||||
key = "CommentModalViewModel_$postId",
|
key = "CommentModalViewModel_$postId",
|
||||||
@@ -161,28 +164,42 @@ fun CommentModalContent(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
|
// 拖动手柄
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 16.dp, bottom = 16.dp, end = 16.dp)
|
.padding(top = 8.dp, bottom = 12.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
Box(
|
||||||
stringResource(R.string.comment),
|
modifier = Modifier
|
||||||
fontSize = 18.sp,
|
.width(40.dp)
|
||||||
fontWeight = FontWeight.Bold,
|
.height(4.dp)
|
||||||
color = AppColors.text,
|
.clip(RoundedCornerShape(50))
|
||||||
modifier = Modifier.align(Alignment.Center)
|
.background(AppColors.divider)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizontalDivider(
|
if (showTitle) {
|
||||||
color = AppColors.divider
|
Box(
|
||||||
)
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 16.dp, bottom = 16.dp, end = 16.dp)
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.comment),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = AppColors.text,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 24.dp, vertical = 16.dp),
|
.padding(horizontal = 20.dp, vertical = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -17,15 +17,19 @@ import androidx.compose.foundation.rememberScrollState
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.PlayArrow
|
||||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
import androidx.compose.material.pullrefresh.pullRefresh
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
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.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -155,7 +159,10 @@ fun FavouriteListPage() {
|
|||||||
.clip(RoundedCornerShape(8.dp)),
|
.clip(RoundedCornerShape(8.dp)),
|
||||||
context = context
|
context = context
|
||||||
)
|
)
|
||||||
if (momentItem.images.size > 1) {
|
|
||||||
|
val isVideoMoment = momentItem.images.isEmpty() && !momentItem.videos.isNullOrEmpty()
|
||||||
|
|
||||||
|
if (momentItem.images.size > 1 || (momentItem.videos?.size ?: 0) > 1) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(top = 8.dp, end = 8.dp)
|
.padding(top = 8.dp, end = 8.dp)
|
||||||
@@ -168,6 +175,31 @@ fun FavouriteListPage() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isVideoMoment) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 8.dp, end = 8.dp)
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(24.dp)
|
||||||
|
.background(
|
||||||
|
color = Color.Black.copy(alpha = 0.4f),
|
||||||
|
shape = RoundedCornerShape(12.dp)
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.PlayArrow,
|
||||||
|
contentDescription = "",
|
||||||
|
tint = Color.White,
|
||||||
|
modifier = Modifier.size(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ import androidx.compose.runtime.setValue
|
|||||||
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.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
@@ -97,6 +99,9 @@ fun VideoRecommendationItem(
|
|||||||
skipPartiallyExpanded = true
|
skipPartiallyExpanded = true
|
||||||
)
|
)
|
||||||
var pauseIconVisibleState by remember { mutableStateOf(false) }
|
var pauseIconVisibleState by remember { mutableStateOf(false) }
|
||||||
|
// 防抖:记录上次双击时间,防止快速重复双击
|
||||||
|
val lastDoubleTapTime = remember { mutableStateOf(0L) }
|
||||||
|
val doubleTapDebounceTime = 500L // 500ms 防抖时间
|
||||||
|
|
||||||
val exoPlayer = remember(videoUrl) {
|
val exoPlayer = remember(videoUrl) {
|
||||||
ExoPlayer.Builder(context)
|
ExoPlayer.Builder(context)
|
||||||
@@ -167,18 +172,32 @@ fun VideoRecommendationItem(
|
|||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.noRippleClickable {
|
.pointerInput(videoUrl, moment.liked) {
|
||||||
pauseIconVisibleState = true
|
detectTapGestures(
|
||||||
exoPlayer.pause()
|
onDoubleTap = { offset ->
|
||||||
scope.launch {
|
// 双击点赞/取消点赞
|
||||||
delay(100)
|
val currentTime = System.currentTimeMillis()
|
||||||
if (exoPlayer.isPlaying) {
|
if (currentTime - lastDoubleTapTime.value > doubleTapDebounceTime) {
|
||||||
|
lastDoubleTapTime.value = currentTime
|
||||||
|
// 检查当前点赞状态,如果已点赞则取消点赞,如果未点赞则点赞
|
||||||
|
onLikeClick?.invoke(moment)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onTap = {
|
||||||
|
// 单击播放/暂停
|
||||||
|
pauseIconVisibleState = true
|
||||||
exoPlayer.pause()
|
exoPlayer.pause()
|
||||||
} else {
|
scope.launch {
|
||||||
pauseIconVisibleState = false
|
delay(100)
|
||||||
exoPlayer.play()
|
if (exoPlayer.isPlaying) {
|
||||||
|
exoPlayer.pause()
|
||||||
|
} else {
|
||||||
|
pauseIconVisibleState = false
|
||||||
|
exoPlayer.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -300,7 +319,9 @@ fun VideoRecommendationItem(
|
|||||||
ModalBottomSheet(
|
ModalBottomSheet(
|
||||||
onDismissRequest = { showCommentModal = false },
|
onDismissRequest = { showCommentModal = false },
|
||||||
containerColor = Color.White,
|
containerColor = Color.White,
|
||||||
sheetState = sheetState
|
sheetState = sheetState,
|
||||||
|
dragHandle = {},
|
||||||
|
shape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)
|
||||||
) {
|
) {
|
||||||
CommentModalContent(postId = moment.id) {
|
CommentModalContent(postId = moment.id) {
|
||||||
// 评论添加后的回调
|
// 评论添加后的回调
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ import androidx.compose.foundation.lazy.grid.itemsIndexed
|
|||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
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.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -273,6 +276,45 @@ fun GalleryGrid(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (momentItem.images.size > 1 || (momentItem.videos?.size ?: 0) > 1) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 8.dp, end = 8.dp)
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
painter = painterResource(R.drawable.rider_pro_picture_more),
|
||||||
|
contentDescription = "",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVideoMoment) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 8.dp, end = 8.dp)
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(24.dp)
|
||||||
|
.background(
|
||||||
|
color = Color.Black.copy(alpha = 0.4f),
|
||||||
|
shape = RoundedCornerShape(12.dp)
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.PlayArrow,
|
||||||
|
contentDescription = "",
|
||||||
|
tint = Color.White,
|
||||||
|
modifier = Modifier.size(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.gestures.Orientation
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -56,6 +57,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleEventObserver
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
@@ -467,6 +469,9 @@ fun VideoPlayer(
|
|||||||
.clip(RectangleShape)
|
.clip(RectangleShape)
|
||||||
) {
|
) {
|
||||||
var playerView by remember { mutableStateOf<PlayerView?>(null) }
|
var playerView by remember { mutableStateOf<PlayerView?>(null) }
|
||||||
|
// 防抖:记录上次双击时间,防止快速重复双击
|
||||||
|
val lastDoubleTapTime = remember { mutableStateOf(0L) }
|
||||||
|
val doubleTapDebounceTime = 500L // 500ms 防抖时间
|
||||||
|
|
||||||
// 使用 key 强制每个视频的 PlayerView 完全独立,避免布局状态残留
|
// 使用 key 强制每个视频的 PlayerView 完全独立,避免布局状态残留
|
||||||
androidx.compose.runtime.key(videoUrl) {
|
androidx.compose.runtime.key(videoUrl) {
|
||||||
@@ -479,8 +484,24 @@ fun VideoPlayer(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.clip(RectangleShape)
|
.clip(RectangleShape)
|
||||||
.noRippleClickable {
|
.pointerInput(videoUrl, moment?.liked) {
|
||||||
handleVideoClick(pauseIconVisibleState, exoPlayer, scope)
|
detectTapGestures(
|
||||||
|
onDoubleTap = { offset ->
|
||||||
|
// 双击点赞/取消点赞
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
if (currentTime - lastDoubleTapTime.value > doubleTapDebounceTime) {
|
||||||
|
lastDoubleTapTime.value = currentTime
|
||||||
|
moment?.let {
|
||||||
|
// 检查当前点赞状态,如果已点赞则取消点赞,如果未点赞则点赞
|
||||||
|
onLikeClick?.invoke(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onTap = {
|
||||||
|
// 单击播放/暂停
|
||||||
|
handleVideoClick(pauseIconVisibleState, exoPlayer, scope)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -660,7 +681,8 @@ fun VideoPlayer(
|
|||||||
},
|
},
|
||||||
containerColor = AppColors.background,
|
containerColor = AppColors.background,
|
||||||
sheetState = sheetState,
|
sheetState = sheetState,
|
||||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
|
dragHandle = {},
|
||||||
|
shape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -670,6 +692,7 @@ fun VideoPlayer(
|
|||||||
CommentModalContent(
|
CommentModalContent(
|
||||||
postId = moment.id,
|
postId = moment.id,
|
||||||
commentCount = moment.commentCount,
|
commentCount = moment.commentCount,
|
||||||
|
showTitle = false,
|
||||||
onCommentAdded = {
|
onCommentAdded = {
|
||||||
onCommentAdded?.invoke(moment)
|
onCommentAdded?.invoke(moment)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import androidx.compose.animation.slideInVertically
|
|||||||
import androidx.compose.animation.slideOutVertically
|
import androidx.compose.animation.slideOutVertically
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
@@ -1159,14 +1161,26 @@ fun ImageViewerDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun PostImageView(
|
fun PostImageView(
|
||||||
images: List<MomentImageEntity>,
|
images: List<MomentImageEntity>,
|
||||||
initialPage: Int? = 0
|
initialPage: Int? = 0
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
var isImageViewerDialog by remember { mutableStateOf(false) }
|
var isImageViewerDialog by remember { mutableStateOf(false) }
|
||||||
var currentImageIndex by remember { mutableStateOf(initialPage ?: 0) }
|
val initialPageIndex = initialPage ?: 0
|
||||||
|
val pagerState = rememberPagerState(
|
||||||
|
pageCount = { images.size },
|
||||||
|
initialPage = initialPageIndex.coerceIn(0, maxOf(0, images.size - 1))
|
||||||
|
)
|
||||||
|
var currentImageIndex by remember { mutableStateOf(pagerState.currentPage) }
|
||||||
|
|
||||||
|
// 同步 pagerState 的当前页面到 currentImageIndex
|
||||||
|
LaunchedEffect(pagerState.currentPage) {
|
||||||
|
currentImageIndex = pagerState.currentPage
|
||||||
|
}
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
onDispose {
|
onDispose {
|
||||||
@@ -1187,23 +1201,31 @@ fun PostImageView(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
) {
|
) {
|
||||||
if (images.isNotEmpty()) {
|
if (images.isNotEmpty()) {
|
||||||
CustomAsyncImage(
|
HorizontalPager(
|
||||||
context,
|
state = pagerState,
|
||||||
images[currentImageIndex].thumbnail,
|
|
||||||
contentDescription = "Image",
|
|
||||||
contentScale = ContentScale.Crop,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.pointerInput(Unit) {
|
) { page ->
|
||||||
detectTapGestures(
|
val image = images[page]
|
||||||
onTap = {
|
CustomAsyncImage(
|
||||||
isImageViewerDialog = true
|
context,
|
||||||
}
|
image.thumbnail,
|
||||||
)
|
contentDescription = "Image",
|
||||||
}
|
blurHash = image.blurHash,
|
||||||
.background(Color.Gray.copy(alpha = 0.1f))
|
contentScale = ContentScale.Crop,
|
||||||
)
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.pointerInput(Unit) {
|
||||||
|
detectTapGestures(
|
||||||
|
onTap = {
|
||||||
|
isImageViewerDialog = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.background(Color.Gray.copy(alpha = 0.1f))
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图片导航控件
|
// 图片导航控件
|
||||||
@@ -1212,56 +1234,26 @@ fun PostImageView(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.Center,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
// Previous button
|
|
||||||
Text(
|
|
||||||
text = "Previous",
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(8.dp)
|
|
||||||
.noRippleClickable {
|
|
||||||
if (currentImageIndex > 0) {
|
|
||||||
currentImageIndex--
|
|
||||||
}
|
|
||||||
},
|
|
||||||
color = if (currentImageIndex > 0) Color.Blue else Color.Gray
|
|
||||||
)
|
|
||||||
|
|
||||||
// Indicators
|
// Indicators
|
||||||
Row(
|
images.forEachIndexed { index, _ ->
|
||||||
horizontalArrangement = Arrangement.Center
|
Box(
|
||||||
) {
|
modifier = Modifier
|
||||||
images.forEachIndexed { index, _ ->
|
.size(4.dp)
|
||||||
Box(
|
.clip(CircleShape)
|
||||||
modifier = Modifier
|
.background(
|
||||||
.size(4.dp)
|
if (pagerState.currentPage == index) Color.Red else Color.Gray.copy(
|
||||||
.clip(CircleShape)
|
alpha = 0.5f
|
||||||
.background(
|
|
||||||
if (currentImageIndex == index) Color.Red else Color.Gray.copy(
|
|
||||||
alpha = 0.5f
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
.padding(4.dp)
|
)
|
||||||
)
|
.padding(4.dp)
|
||||||
if (index < images.size - 1) {
|
)
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
if (index < images.size - 1) {
|
||||||
}
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next button
|
|
||||||
Text(
|
|
||||||
text = "Next",
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(8.dp)
|
|
||||||
.noRippleClickable {
|
|
||||||
if (currentImageIndex < images.size - 1) {
|
|
||||||
currentImageIndex++
|
|
||||||
}
|
|
||||||
},
|
|
||||||
color = if (currentImageIndex < images.size - 1) Color.Blue else Color.Gray
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user