问题修正

This commit is contained in:
2024-10-23 20:32:32 +08:00
parent 6cb19eb6cf
commit dad032e233
5 changed files with 128 additions and 31 deletions

View File

@@ -0,0 +1,9 @@
package com.aiosman.riderpro.exp
import android.graphics.Bitmap
fun Bitmap.rotate(degree: Int): Bitmap {
val matrix = android.graphics.Matrix()
matrix.postRotate(degree.toFloat())
return Bitmap.createBitmap(this, 0, 0, this.width, this.height, matrix, true)
}

View File

@@ -7,7 +7,6 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
@@ -45,7 +44,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.ContentScale
@@ -232,16 +230,18 @@ fun AddImageGrid() {
val navController = LocalNavController.current
val context = LocalContext.current
val model = NewPostViewModel
val scope = model.viewModelScope
val pickImagesLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.GetMultipleContents()
) { uris ->
if (uris.isNotEmpty()) {
model.imageList += uris.map {
ImageItem(
uri = it.toString(),
id = java.util.UUID.randomUUID().toString()
)
scope.launch {
for (uri in uris) {
ImageItem.fromUri(context, uri.toString())?.let {
model.imageList += it
}
}
}
}
}
@@ -250,10 +250,12 @@ fun AddImageGrid() {
contract = ActivityResultContracts.TakePicture()
) { success ->
if (success) {
model.imageList += ImageItem(
uri = model.currentPhotoUri.toString(),
id = java.util.UUID.randomUUID().toString()
)
scope.launch {
ImageItem.fromUri(context, model.currentPhotoUri.toString())?.let {
model.imageList += it
}
}
}
}
@@ -283,7 +285,7 @@ fun AddImageGrid() {
) {
CustomAsyncImage(
LocalContext.current,
item.uri,
item.bitmap,
contentDescription = "Image",
modifier = Modifier
.fillMaxWidth()
@@ -320,7 +322,8 @@ fun AddImageGrid() {
val strokeWidth = 1.dp.toPx()
val dashLength = 10f
val dashGap = 10f
val pathEffect = PathEffect.dashPathEffect(floatArrayOf(dashLength, dashGap))
val pathEffect =
PathEffect.dashPathEffect(floatArrayOf(dashLength, dashGap))
drawRoundRect(
color = Color(0xFFD6D6D6),
style = Stroke(strokeWidth, pathEffect = pathEffect),
@@ -351,7 +354,8 @@ fun AddImageGrid() {
val strokeWidth = 1.dp.toPx()
val dashLength = 10f
val dashGap = 10f
val pathEffect = PathEffect.dashPathEffect(floatArrayOf(dashLength, dashGap))
val pathEffect =
PathEffect.dashPathEffect(floatArrayOf(dashLength, dashGap))
drawRoundRect(
color = Color(0xFFD6D6D6),
style = Stroke(strokeWidth, pathEffect = pathEffect),

View File

@@ -103,7 +103,7 @@ fun NewPostImageGridScreen() {
) { page ->
val imageUrl = imageList[page]
Image(
painter = rememberAsyncImagePainter(model = imageUrl),
painter = rememberAsyncImagePainter(model = imageUrl.bitmap),
contentDescription = "Image $page",
modifier = Modifier.fillMaxSize()
)

View File

@@ -1,6 +1,9 @@
package com.aiosman.riderpro.ui.post
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.ExifInterface
import android.net.Uri
import android.util.Log
import androidx.compose.runtime.getValue
@@ -11,20 +14,70 @@ import com.aiosman.riderpro.data.MomentService
import com.aiosman.riderpro.entity.MomentServiceImpl
import com.aiosman.riderpro.data.UploadImage
import com.aiosman.riderpro.entity.MomentEntity
import com.aiosman.riderpro.exp.rotate
import com.aiosman.riderpro.ui.index.tabs.moment.MomentViewModel
import com.aiosman.riderpro.ui.index.tabs.profile.MyProfileViewModel
import com.aiosman.riderpro.ui.modification.Modification
import com.aiosman.riderpro.utils.FileUtil
import com.aiosman.riderpro.utils.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.util.UUID
data class ImageItem(
val uri: String,
val id: String
val id: String,
val bitmap: Bitmap,
val file: File
) {
companion object {
suspend fun fromUri(context: Context,uri: String): ImageItem? {
// 保存图片文件到临时文件夹
context.contentResolver.openInputStream(Uri.parse(uri))?.use { inputStream ->
val tempFileName = UUID.randomUUID().toString()
val tempFile = File.createTempFile(tempFileName, null, context.cacheDir)
FileOutputStream(tempFile).use { outputStream ->
inputStream.copyTo(outputStream)
}
// 读取图片文件为 Bitmap
var bitmap = BitmapFactory.decodeFile(tempFile.absolutePath)
// 读取文件exif修正旋转
val exif = ExifInterface(tempFile.absolutePath)
bitmap = when (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)) {
ExifInterface.ORIENTATION_ROTATE_90 -> bitmap.rotate(90)
ExifInterface.ORIENTATION_ROTATE_180 -> bitmap.rotate(180)
ExifInterface.ORIENTATION_ROTATE_270 -> bitmap.rotate(270)
else -> bitmap
}
// 保存 bitmap 到临时文件夹
try {
val savedBitmapFilename = UUID.randomUUID().toString()
val bitmapFile = File.createTempFile(savedBitmapFilename, ".jpg", context.cacheDir)
FileOutputStream(bitmapFile).use { os ->
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os)
}
// 清理临时文件
tempFile.delete()
return ImageItem(
Uri.fromFile(bitmapFile).toString(),
savedBitmapFilename,
bitmap,
bitmapFile
)
} catch (e: IOException) {
Log.e("NewPost", "Failed to save bitmap to file", e)
null
}
}
return null
}
}
}
object NewPostViewModel : ViewModel() {
var momentService: MomentService = MomentServiceImpl()
@@ -42,13 +95,14 @@ object NewPostViewModel : ViewModel() {
imageList = listOf()
relPostId = null
}
fun asNewPostWithImageUris(imageUris: List<String>) {
textContent = ""
searchPlaceAddressResult = null
modificationList = listOf()
imageList = imageUris.map {
ImageItem(it, UUID.randomUUID().toString())
}
// imageList = imageUris.map {
// ImageItem(it, UUID.randomUUID().toString())
// }
relPostId = null
}
@@ -71,20 +125,32 @@ object NewPostViewModel : ViewModel() {
}
return null
}
suspend fun createMoment(context: Context, onUploadProgress: (Float) -> Unit) {
val uploadImageList = emptyList<UploadImage>().toMutableList()
var index = 0
for (item in imageList) {
val cursor = context.contentResolver.query(Uri.parse(item.uri), null, null, null, null)
cursor?.use {
if (it.moveToFirst()) {
val displayName = it.getString(it.getColumnIndex("_display_name"))
val extension = displayName.substringAfterLast(".")
Log.d("NewPost", "File name: $displayName, extension: $extension")
// read as file
val file = uriToFile(context, Uri.parse(item.uri))
Log.d("NewPost", "File size: ${file.length()}")
uploadImageList += UploadImage(file, displayName, item.uri, extension)
// cursor?.use {
// if (it.moveToFirst()) {
// val columnIndex = it.getColumnIndex("_display_name")
// if (columnIndex != -1) {
// val displayName = it.getString(columnIndex)
// val extension = displayName.substringAfterLast(".")
// Log.d("NewPost", "File name: $displayName, extension: $extension")
// // read as file
// val file = uriToFile(context, Uri.parse(item.uri))
// Log.d("NewPost", "File size: ${file.length()}")
// uploadImageList += UploadImage(file, displayName, item.uri, extension)
// }
// }
// }
// 保存图片到本地
FileUtil.bitmapToJPG(context, item.bitmap, UUID.randomUUID().toString())
?.let { savedImageUri ->
// 读取保存的图片文件
uriToFile(context, savedImageUri).let { file ->
uploadImageList += UploadImage(file, file.name, item.uri, "jpg")
}
}
// 在上传过程中调用 onUploadProgress 更新进度
@@ -95,6 +161,7 @@ object NewPostViewModel : ViewModel() {
// 刷新个人动态
MyProfileViewModel.loadProfile(pullRefresh = true)
MomentViewModel.refreshPager()
}
suspend fun init() {
@@ -103,6 +170,7 @@ object NewPostViewModel : ViewModel() {
relMoment = moment
}
}
fun deleteImage(index: Int) {
imageList = imageList.toMutableList().apply {
removeAt(index)

View File

@@ -15,7 +15,10 @@ import coil.request.SuccessResult
import com.aiosman.riderpro.utils.Utils.getImageLoader
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStream
object FileUtil {
@@ -102,4 +105,17 @@ object FileUtil {
return realPath
}
suspend fun bitmapToJPG(context: Context, bitmap: Bitmap, displayName: String): Uri? {
return withContext(Dispatchers.IO) {
try {
val tempFile = File.createTempFile(displayName, ".jpg", context.cacheDir)
FileOutputStream(tempFile).use { os ->
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os)
}
Uri.fromFile(tempFile)
} catch (e: IOException) {
null
}
}
}
}