Android Kotlin Jetpack Compose:特定设备图库图片旋转异常求助
解决Jetpack Compose中Android 9设备图片旋转异常问题
在Android 9(API 28)及以下版本,MediaStore.Images.Media.getBitmap不会自动读取并应用图片的Exif旋转元数据,这就是富士通901FJ设备上部分图库图片显示旋转/倒置的原因。以下是针对Kotlin代码的修复方案:
1. 添加Exif旋转角度读取函数
这个函数从图片的Exif信息中提取正确的旋转角度:
import android.media.ExifInterface import android.content.ContentResolver import android.net.Uri fun Uri.getImageRotationAngle(contentResolver: ContentResolver): Int { return kotlin.runCatching { contentResolver.openInputStream(this)?.use { inputStream -> val exif = ExifInterface(inputStream) when (exif.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL )) { ExifInterface.ORIENTATION_ROTATE_90 -> 90 ExifInterface.ORIENTATION_ROTATE_180 -> 180 ExifInterface.ORIENTATION_ROTATE_270 -> 270 else -> 0 } } }.getOrDefault(0) }
2. 添加Bitmap旋转工具函数
根据读取到的角度修正Bitmap方向:
import android.graphics.Bitmap import android.graphics.Matrix fun Bitmap.rotate(degrees: Int): Bitmap { if (degrees == 0) return this val matrix = Matrix().apply { postRotate(degrees.toFloat()) } return Bitmap.createBitmap(this, 0, 0, width, height, matrix, true) }
3. 修改图片加载逻辑
更新图库选择后的处理代码,先修正旋转再缩放:
val galleryLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> uri?.let { val originalBitmap = it.getBitmapOrNull(context.contentResolver) originalBitmap?.let { bitmap -> val rotationAngle = it.getImageRotationAngle(context.contentResolver) val rotatedBitmap = bitmap.rotate(rotationAngle) // 缩放并更新状态 imageBitmap = Bitmap.createScaledBitmap(rotatedBitmap, 120, 120, true) // 回收临时Bitmap避免内存泄漏 if (bitmap !== rotatedBitmap) { bitmap.recycle() } rotatedBitmap.recycle() } } }
额外注意事项
- 针对Android 9设备,确保已在Manifest中添加
READ_EXTERNAL_STORAGE权限,并在运行时请求该权限(如果图片来自外部存储)。 - 若将旋转逻辑整合到
getBitmapOrNull函数中,需注意在API 29+版本中,ImageDecoder已经自动处理了Exif旋转,无需重复操作,所以可以在函数内做版本判断:
fun Uri.getBitmapOrNull(contentResolver: ContentResolver): Bitmap? { return kotlin.runCatching { val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val source = ImageDecoder.createSource(contentResolver, this) ImageDecoder.decodeBitmap(source) } else { MediaStore.Images.Media.getBitmap(contentResolver, this) } // 仅在Android 9及以下处理旋转 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { val rotationAngle = getImageRotationAngle(contentResolver) bitmap.rotate(rotationAngle) } else { bitmap } }.getOrNull() }
内容的提问来源于stack exchange,提问作者Yuki
相关产品推荐
相关产品推荐

