完善需求功能:使用用户配置的水印样式和图片质量,添加标题/内容文字样式配置
This commit is contained in:
@@ -62,6 +62,7 @@ import androidx.lifecycle.LifecycleOwner
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
||||
import com.inspection.camera.data.PreferencesManager
|
||||
import com.inspection.camera.data.models.ImageQuality
|
||||
import com.inspection.camera.data.models.WatermarkStyle
|
||||
import com.inspection.camera.util.ImageProcessor
|
||||
import com.inspection.camera.util.LocationHelper
|
||||
@@ -90,6 +91,7 @@ fun CameraScreen(
|
||||
var locationText by remember { mutableStateOf("") }
|
||||
var manualAddress by remember { mutableStateOf("") }
|
||||
var currentWatermarkStyle by remember { mutableStateOf(WatermarkStyle.Default) }
|
||||
var currentImageQuality by remember { mutableStateOf(ImageQuality.Standard) }
|
||||
var showPermissionDeniedDialog by remember { mutableStateOf(false) }
|
||||
|
||||
val capturedImages = remember { mutableStateListOf<Uri>() }
|
||||
@@ -120,6 +122,9 @@ fun CameraScreen(
|
||||
preferencesManager.manualAddress.collect { address ->
|
||||
manualAddress = address
|
||||
}
|
||||
preferencesManager.imageQuality.collect { quality ->
|
||||
currentImageQuality = quality
|
||||
}
|
||||
}
|
||||
|
||||
// 获取位置
|
||||
@@ -148,6 +153,7 @@ fun CameraScreen(
|
||||
context = context,
|
||||
flashMode = flashMode,
|
||||
watermarkStyle = currentWatermarkStyle,
|
||||
imageQuality = currentImageQuality,
|
||||
locationText = if (locationText.isNotBlank()) locationText else "未知地点",
|
||||
onComplete = { uri ->
|
||||
capturedImages.add(uri)
|
||||
@@ -398,6 +404,7 @@ private fun capturePhoto(
|
||||
context: Context,
|
||||
flashMode: Int,
|
||||
watermarkStyle: WatermarkStyle,
|
||||
imageQuality: ImageQuality,
|
||||
locationText: String,
|
||||
onComplete: (Uri) -> Unit
|
||||
) {
|
||||
@@ -431,7 +438,7 @@ private fun capturePhoto(
|
||||
|
||||
// 保存到相册
|
||||
val fileName = ImageProcessor.generateFileName("")
|
||||
val uri = ImageProcessor.saveToGallery(context, watermarkedBitmap, fileName)
|
||||
val uri = ImageProcessor.saveToGallery(context, watermarkedBitmap, fileName, imageQuality.quality)
|
||||
|
||||
bitmap.recycle()
|
||||
watermarkedBitmap.recycle()
|
||||
|
||||
@@ -56,7 +56,9 @@ import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.inspection.camera.data.PreferencesManager
|
||||
import com.inspection.camera.data.models.ImageQuality
|
||||
import com.inspection.camera.data.models.MergeLayoutType
|
||||
import com.inspection.camera.data.models.WatermarkStyle
|
||||
import com.inspection.camera.ui.theme.Primary
|
||||
import com.inspection.camera.util.ImageProcessor
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -76,12 +78,29 @@ fun MergeScreen(
|
||||
|
||||
val images = remember { mutableStateListOf<Uri>().apply { addAll(imageUris) } }
|
||||
var layoutType by remember { mutableStateOf(MergeLayoutType.Grid2x2) }
|
||||
var imageQuality by remember { mutableStateOf(ImageQuality.Standard) }
|
||||
var titleStyle by remember { mutableStateOf(WatermarkStyle.Default) }
|
||||
var contentStyle by remember { mutableStateOf(WatermarkStyle.Default) }
|
||||
var showPreview by remember { mutableStateOf(false) }
|
||||
var previewBitmap by remember { mutableStateOf<Bitmap?>(null) }
|
||||
var title by remember { mutableStateOf("") }
|
||||
var content by remember { mutableStateOf("") }
|
||||
var showSaveDialog by remember { mutableStateOf(false) }
|
||||
|
||||
// 加载用户配置
|
||||
LaunchedEffect(Unit) {
|
||||
preferencesManager.mergeLayout.collect { layoutType = it }
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
preferencesManager.imageQuality.collect { imageQuality = it }
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
preferencesManager.titleStyle.collect { titleStyle = it }
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
preferencesManager.contentStyle.collect { contentStyle = it }
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
@@ -206,15 +225,15 @@ fun MergeScreen(
|
||||
ImageProcessor.mergeImages(
|
||||
images.toList(),
|
||||
layoutType,
|
||||
com.inspection.camera.data.models.ImageQuality.Standard
|
||||
imageQuality
|
||||
).let { bitmap ->
|
||||
if (title.isNotBlank() || content.isNotBlank()) {
|
||||
ImageProcessor.addTextToBitmap(
|
||||
bitmap,
|
||||
title,
|
||||
content,
|
||||
com.inspection.camera.data.models.WatermarkStyle.Default,
|
||||
com.inspection.camera.data.models.WatermarkStyle.Default
|
||||
titleStyle,
|
||||
contentStyle
|
||||
)
|
||||
} else {
|
||||
bitmap
|
||||
@@ -273,15 +292,15 @@ fun MergeScreen(
|
||||
ImageProcessor.mergeImages(
|
||||
images.toList(),
|
||||
layoutType,
|
||||
com.inspection.camera.data.models.ImageQuality.Standard
|
||||
imageQuality
|
||||
).let { mergedBitmap ->
|
||||
if (title.isNotBlank() || content.isNotBlank()) {
|
||||
ImageProcessor.addTextToBitmap(
|
||||
mergedBitmap,
|
||||
title,
|
||||
content,
|
||||
com.inspection.camera.data.models.WatermarkStyle.Default,
|
||||
com.inspection.camera.data.models.WatermarkStyle.Default
|
||||
titleStyle,
|
||||
contentStyle
|
||||
)
|
||||
} else {
|
||||
mergedBitmap
|
||||
|
||||
@@ -56,6 +56,8 @@ fun SettingsScreen(
|
||||
var locationMode by remember { mutableStateOf(LocationMode.Network) }
|
||||
var mergeLayout by remember { mutableStateOf(MergeLayoutType.Grid2x2) }
|
||||
var imageQuality by remember { mutableStateOf(ImageQuality.Standard) }
|
||||
var titleStyle by remember { mutableStateOf(WatermarkStyle.Default) }
|
||||
var contentStyle by remember { mutableStateOf(WatermarkStyle.Default) }
|
||||
var defaultTheme by remember { mutableStateOf("") }
|
||||
var inspectorName by remember { mutableStateOf("") }
|
||||
var manualAddress by remember { mutableStateOf("") }
|
||||
@@ -73,6 +75,12 @@ fun SettingsScreen(
|
||||
scope.launch {
|
||||
preferencesManager.imageQuality.collect { imageQuality = it }
|
||||
}
|
||||
scope.launch {
|
||||
preferencesManager.titleStyle.collect { titleStyle = it }
|
||||
}
|
||||
scope.launch {
|
||||
preferencesManager.contentStyle.collect { contentStyle = it }
|
||||
}
|
||||
scope.launch {
|
||||
preferencesManager.defaultTheme.collect { defaultTheme = it }
|
||||
}
|
||||
@@ -210,6 +218,48 @@ fun SettingsScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
SettingsItem(title = "默认标题样式") {
|
||||
WatermarkStyle.entries.forEach { style ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { scope.launch { preferencesManager.setTitleStyle(style) } }
|
||||
.padding(vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
RadioButton(
|
||||
selected = titleStyle.name == style.name,
|
||||
onClick = { scope.launch { preferencesManager.setTitleStyle(style) } }
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(style.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
SettingsItem(title = "默认内容样式") {
|
||||
WatermarkStyle.entries.forEach { style ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { scope.launch { preferencesManager.setContentStyle(style) } }
|
||||
.padding(vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
RadioButton(
|
||||
selected = contentStyle.name == style.name,
|
||||
onClick = { scope.launch { preferencesManager.setContentStyle(style) } }
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(style.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
@@ -79,9 +79,11 @@ object ImageProcessor {
|
||||
val y = result.height - padding
|
||||
|
||||
// 绘制背景
|
||||
if (style.backgroundColor != android.graphics.Color.TRANSPARENT) {
|
||||
// 通过ARGB判断来决定是否绘制背景,避免混用 Android Color 与 Compose Color 的类型问题
|
||||
val bgColorInt = style.backgroundColor.toArgb()
|
||||
if (bgColorInt != 0) {
|
||||
val bgPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
color = style.backgroundColor.toArgb()
|
||||
color = bgColorInt
|
||||
}
|
||||
val bgRect = RectF(
|
||||
x - 10,
|
||||
|
||||
Reference in New Issue
Block a user