feat:发帖时增加 emoji 表情功能
This commit is contained in:
@@ -524,22 +524,33 @@ private fun ZoomableImage(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.pointerInput(scale) {
|
||||
detectTransformGestures { _, pan, zoom, _ ->
|
||||
val newScale = (scale * zoom).coerceIn(1f, 4f)
|
||||
// 只有在缩放或已经放大时才处理手势
|
||||
if (zoom != 1f || scale > 1f) {
|
||||
scale = newScale
|
||||
if (scale > 1f) {
|
||||
offsetX += pan.x
|
||||
offsetY += pan.y
|
||||
} else {
|
||||
offsetX = 0f
|
||||
offsetY = 0f
|
||||
.then(
|
||||
// 只有在放大状态下才启用手势检测,否则让 HorizontalPager 处理滑动
|
||||
if (scale > 1f) {
|
||||
Modifier.pointerInput(Unit) {
|
||||
detectTransformGestures { _, pan, zoom, _ ->
|
||||
val newScale = (scale * zoom).coerceIn(1f, 4f)
|
||||
scale = newScale
|
||||
if (scale > 1f) {
|
||||
offsetX += pan.x
|
||||
offsetY += pan.y
|
||||
} else {
|
||||
offsetX = 0f
|
||||
offsetY = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Modifier.pointerInput(Unit) {
|
||||
detectTransformGestures { _, _, zoom, _ ->
|
||||
// 未放大时只处理缩放手势(双指捏合)
|
||||
if (zoom != 1f) {
|
||||
scale = (scale * zoom).coerceIn(1f, 4f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.clickable {
|
||||
if (scale == 1f) {
|
||||
onTap()
|
||||
|
||||
@@ -37,6 +37,7 @@ fun CreatePostScreen(
|
||||
) {
|
||||
var content by remember { mutableStateOf("") }
|
||||
var selectedImages by remember { mutableStateOf<List<Uri>>(emptyList()) }
|
||||
var showEmojiPicker by remember { mutableStateOf(false) }
|
||||
|
||||
val imagePicker = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.GetMultipleContents()
|
||||
@@ -232,7 +233,7 @@ fun CreatePostScreen(
|
||||
|
||||
// Emoji Button
|
||||
IconButton(
|
||||
onClick = { },
|
||||
onClick = { showEmojiPicker = true },
|
||||
modifier = Modifier.size(40.dp)
|
||||
) {
|
||||
Icon(
|
||||
@@ -264,4 +265,113 @@ fun CreatePostScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emoji Picker
|
||||
if (showEmojiPicker) {
|
||||
CreatePostEmojiPicker(
|
||||
onDismiss = { showEmojiPicker = false },
|
||||
onEmojiSelected = { emoji ->
|
||||
content = content + emoji
|
||||
showEmojiPicker = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CreatePostEmojiPicker(
|
||||
onDismiss: () -> Unit,
|
||||
onEmojiSelected: (String) -> Unit
|
||||
) {
|
||||
val emojis = listOf(
|
||||
"😀", "😃", "😄", "😁", "😆", "😅", "🤣", "😂", "🙂", "😊",
|
||||
"😇", "🥰", "😍", "🤩", "😘", "😗", "😚", "😋", "😛", "😜",
|
||||
"🤪", "😝", "🤑", "🤗", "🤭", "🤫", "🤔", "🤐", "🤨", "😐",
|
||||
"😑", "😶", "😏", "😒", "🙄", "😬", "🤥", "😌", "😔", "😪",
|
||||
"🤤", "😴", "😷", "🤒", "🤕", "🤢", "🤮", "🥴", "😵", "🤯",
|
||||
"👍", "👎", "👏", "🙌", "🤝", "👊", "✊", "🤛", "🤜", "🤞",
|
||||
"✌️", "🤟", "🤘", "👌", "🤌", "👈", "👉", "👆", "👇", "☝️",
|
||||
"💪", "🦾", "🙏", "✍️", "🤳", "💅", "🖐️", "✋", "👋", "🤚",
|
||||
"❤️", "🧡", "💛", "💚", "💙", "💜", "🖤", "🤍", "🤎", "💔",
|
||||
"❣️", "💕", "💞", "💓", "💗", "💖", "💘", "💝", "💟", "♥️",
|
||||
"🎉", "🎊", "🎈", "🎁", "🏆", "🥇", "🔥", "⭐", "🌟", "✨",
|
||||
"💯", "💢", "💥", "💫", "💦", "💨", "🕳️", "💣", "💬", "👀"
|
||||
)
|
||||
|
||||
androidx.compose.ui.window.Dialog(
|
||||
onDismissRequest = onDismiss,
|
||||
properties = androidx.compose.ui.window.DialogProperties(usePlatformDefaultWidth = false)
|
||||
) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(28.dp),
|
||||
color = Color.White,
|
||||
shadowElevation = 16.dp,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(24.dp)) {
|
||||
// 标题栏
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(4.dp, 24.dp)
|
||||
.clip(RoundedCornerShape(2.dp))
|
||||
.background(Brand500)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
text = "选择表情",
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 20.sp,
|
||||
color = Slate900
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
IconButton(
|
||||
onClick = onDismiss,
|
||||
modifier = Modifier.size(32.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Close,
|
||||
contentDescription = "关闭",
|
||||
tint = Slate400,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 表情网格
|
||||
androidx.compose.foundation.lazy.grid.LazyVerticalGrid(
|
||||
columns = androidx.compose.foundation.lazy.grid.GridCells.Fixed(6),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(max = 400.dp),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
contentPadding = PaddingValues(vertical = 8.dp)
|
||||
) {
|
||||
items(emojis.size) { index ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(1f)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.clickable { onEmojiSelected(emojis[index]) },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = emojis[index],
|
||||
fontSize = 32.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.outlined.Image
|
||||
import androidx.compose.material.icons.outlined.Mood
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -37,6 +38,7 @@ fun EditPostScreen(
|
||||
var content by remember { mutableStateOf(post.content) }
|
||||
var existingImages by remember { mutableStateOf(post.media.map { it.mediaUrl }) }
|
||||
var newImages by remember { mutableStateOf<List<Uri>>(emptyList()) }
|
||||
var showEmojiPicker by remember { mutableStateOf(false) }
|
||||
|
||||
val totalImages = existingImages.size + newImages.size
|
||||
|
||||
@@ -227,7 +229,8 @@ fun EditPostScreen(
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||
.navigationBarsPadding(),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
IconButton(
|
||||
onClick = { imagePicker.launch("image/*") },
|
||||
@@ -241,6 +244,124 @@ fun EditPostScreen(
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
IconButton(
|
||||
onClick = { showEmojiPicker = true },
|
||||
modifier = Modifier.size(40.dp)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Outlined.Mood,
|
||||
contentDescription = "添加表情",
|
||||
tint = Brand500,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emoji Picker
|
||||
if (showEmojiPicker) {
|
||||
EditPostEmojiPicker(
|
||||
onDismiss = { showEmojiPicker = false },
|
||||
onEmojiSelected = { emoji ->
|
||||
content = content + emoji
|
||||
showEmojiPicker = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EditPostEmojiPicker(
|
||||
onDismiss: () -> Unit,
|
||||
onEmojiSelected: (String) -> Unit
|
||||
) {
|
||||
val emojis = listOf(
|
||||
"😀", "😃", "😄", "😁", "😆", "😅", "🤣", "😂", "🙂", "😊",
|
||||
"😇", "🥰", "😍", "🤩", "😘", "😗", "😚", "😋", "😛", "😜",
|
||||
"🤪", "😝", "🤑", "🤗", "🤭", "🤫", "🤔", "🤐", "🤨", "😐",
|
||||
"😑", "😶", "😏", "😒", "🙄", "😬", "🤥", "😌", "😔", "😪",
|
||||
"🤤", "😴", "😷", "🤒", "🤕", "🤢", "🤮", "🥴", "😵", "🤯",
|
||||
"👍", "👎", "👏", "🙌", "🤝", "👊", "✊", "🤛", "🤜", "🤞",
|
||||
"✌️", "🤟", "🤘", "👌", "🤌", "👈", "👉", "👆", "👇", "☝️",
|
||||
"💪", "🦾", "🙏", "✍️", "🤳", "💅", "🖐️", "✋", "👋", "🤚",
|
||||
"❤️", "🧡", "💛", "💚", "💙", "💜", "🖤", "🤍", "🤎", "💔",
|
||||
"❣️", "💕", "💞", "💓", "💗", "💖", "💘", "💝", "💟", "♥️",
|
||||
"🎉", "🎊", "🎈", "🎁", "🏆", "🥇", "🔥", "⭐", "🌟", "✨",
|
||||
"💯", "💢", "💥", "💫", "💦", "💨", "🕳️", "💣", "💬", "👀"
|
||||
)
|
||||
|
||||
androidx.compose.ui.window.Dialog(
|
||||
onDismissRequest = onDismiss,
|
||||
properties = androidx.compose.ui.window.DialogProperties(usePlatformDefaultWidth = false)
|
||||
) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(28.dp),
|
||||
color = Color.White,
|
||||
shadowElevation = 16.dp,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(24.dp)) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(4.dp, 24.dp)
|
||||
.clip(RoundedCornerShape(2.dp))
|
||||
.background(Brand500)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
text = "选择表情",
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 20.sp,
|
||||
color = Slate900
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
IconButton(
|
||||
onClick = onDismiss,
|
||||
modifier = Modifier.size(32.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = "关闭",
|
||||
tint = Slate400,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
androidx.compose.foundation.lazy.grid.LazyVerticalGrid(
|
||||
columns = androidx.compose.foundation.lazy.grid.GridCells.Fixed(6),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(max = 400.dp),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
contentPadding = PaddingValues(vertical = 8.dp)
|
||||
) {
|
||||
items(emojis.size) { index ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(1f)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.clickable { onEmojiSelected(emojis[index]) },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = emojis[index],
|
||||
fontSize = 32.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,11 +167,11 @@ fun PostDetailScreen(
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// Content Text
|
||||
// Content Text - 与首页保持一致
|
||||
Text(
|
||||
text = post.content,
|
||||
fontSize = 20.sp,
|
||||
lineHeight = 28.sp,
|
||||
fontSize = 15.sp,
|
||||
lineHeight = 22.sp,
|
||||
color = Slate800
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user