1
Fork 0
mirror of https://github.com/Steffo99/twom.git synced 2024-11-25 17:44:24 +00:00

Complete CreateActivityContent

This commit is contained in:
Steffo 2023-12-02 03:26:37 +01:00
parent 6804058474
commit 8d32d17d32
Signed by: steffo
GPG key ID: 2A24051445686895
3 changed files with 118 additions and 80 deletions

View file

@ -1,8 +1,5 @@
package eu.steffo.twom.create package eu.steffo.twom.create
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.net.Uri import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.PickVisualMediaRequest
@ -15,13 +12,13 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -34,7 +31,6 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.exifinterface.media.ExifInterface
import eu.steffo.twom.R import eu.steffo.twom.R
import eu.steffo.twom.matrix.avatar.AvatarFromBitmap import eu.steffo.twom.matrix.avatar.AvatarFromBitmap
import eu.steffo.twom.theme.TwoMPadding import eu.steffo.twom.theme.TwoMPadding
@ -43,91 +39,21 @@ import eu.steffo.twom.theme.TwoMPadding
@Preview @Preview
fun CreateActivityContent( fun CreateActivityContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onClickCreate: () -> Unit = {},
) { ) {
val context = LocalContext.current val context = LocalContext.current
var name by rememberSaveable { mutableStateOf("") } var name by rememberSaveable { mutableStateOf("") }
var description by rememberSaveable { mutableStateOf("") }
var avatarUri by rememberSaveable { mutableStateOf<Uri?>(null) } var avatarUri by rememberSaveable { mutableStateOf<Uri?>(null) }
var avatarBitmap by remember { mutableStateOf<ImageBitmap?>(null) } var avatarBitmap by rememberSaveable { mutableStateOf<ImageBitmap?>(null) }
// val avatarBitmap = if(avatarUri != null) BitmapFactory.decodeFile(avatarUri.toString()).asImageBitmap() else null // val avatarBitmap = if(avatarUri != null) BitmapFactory.decodeFile(avatarUri.toString()).asImageBitmap() else null
val avatarSelectLauncher = val avatarSelectLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) {
avatarUri = it avatarUri = it
if (it == null) { avatarBitmap = if (it != null) ImageHandler.uriToBitmap(context.contentResolver, it)
avatarBitmap = null ?.asImageBitmap() else null
} else {
// Open two streams...
// One to read the EXIF metadata from:
val exifStream = context.contentResolver.openInputStream(it)
// One to read the image data itself from:
val bitmapStream = context.contentResolver.openInputStream(it)
if (exifStream != null && bitmapStream != null) {
// Use the EXIF metadata to determine the orientation of the image
val exifInterface = ExifInterface(exifStream)
val orientation =
exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1)
exifStream.close()
// Parse the image data as-is
val originalBitmap = BitmapFactory.decodeStream(bitmapStream)
bitmapStream.close()
// Determine the starting points and the size to crop the image to a 1:1 square
val xStart: Int
val yStart: Int
val size: Int
if (originalBitmap.width > originalBitmap.height) {
yStart = 0
xStart = (originalBitmap.width - originalBitmap.height) / 2
size = originalBitmap.height
} else {
xStart = 0
yStart = (originalBitmap.height - originalBitmap.width) / 2
size = originalBitmap.width
}
// Create a transformation matrix to rotate the bitmap based on the orientation
val transformationMatrix: Matrix = Matrix()
// TODO: Make sure these transformations are valid
when (orientation) {
ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> transformationMatrix.postScale(
-1f,
1f
)
ExifInterface.ORIENTATION_ROTATE_180 -> transformationMatrix.postRotate(180f)
ExifInterface.ORIENTATION_FLIP_VERTICAL -> transformationMatrix.postScale(
1f,
-1f
)
ExifInterface.ORIENTATION_TRANSPOSE -> {/* TODO: Transpose the image Matrix */
}
ExifInterface.ORIENTATION_ROTATE_90 -> transformationMatrix.postRotate(90f)
ExifInterface.ORIENTATION_TRANSVERSE -> {/* TODO: Flip horizontally the image Matrix, then transpose it */
}
ExifInterface.ORIENTATION_ROTATE_270 -> transformationMatrix.postRotate(270f)
}
// Crop the bitmap
val croppedBitmap = Bitmap.createBitmap(
originalBitmap,
xStart,
yStart,
size,
size,
transformationMatrix,
true
)
avatarBitmap = croppedBitmap.asImageBitmap()
}
}
} }
Column(modifier) { Column(modifier) {
@ -161,5 +87,28 @@ fun CreateActivityContent(
onValueChange = { name = it } onValueChange = { name = it }
) )
} }
Row(TwoMPadding.base) {
TextField(
modifier = Modifier
.height(180.dp)
.fillMaxWidth(),
label = {
Text(stringResource(R.string.create_description_label))
},
value = description,
onValueChange = { description = it }
)
}
Row(TwoMPadding.base) {
Button(
modifier = Modifier
.fillMaxWidth(),
onClick = onClickCreate,
) {
Text(stringResource(R.string.create_complete_text))
}
}
} }
} }

View file

@ -0,0 +1,87 @@
package eu.steffo.twom.create
import android.content.ContentResolver
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.net.Uri
import androidx.exifinterface.media.ExifInterface
class ImageHandler {
companion object {
fun uriToBitmap(contentResolver: ContentResolver, uri: Uri): Bitmap? {
// Open two streams...
// One to read the EXIF metadata from:
val exifStream = contentResolver.openInputStream(uri)
// One to read the image data itself from:
val bitmapStream = contentResolver.openInputStream(uri)
if (exifStream == null || bitmapStream == null) {
return null
}
// Use the EXIF metadata to determine the orientation of the image
val exifInterface = ExifInterface(exifStream)
val orientation =
exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1)
exifStream.close()
// Parse the image data as-is
val originalBitmap = BitmapFactory.decodeStream(bitmapStream)
bitmapStream.close()
// Determine the starting points and the size to crop the image to a 1:1 square
val xStart: Int
val yStart: Int
val size: Int
if (originalBitmap.width > originalBitmap.height) {
yStart = 0
xStart = (originalBitmap.width - originalBitmap.height) / 2
size = originalBitmap.height
} else {
xStart = 0
yStart = (originalBitmap.height - originalBitmap.width) / 2
size = originalBitmap.width
}
// Create a transformation matrix to rotate the bitmap based on the orientation
val transformationMatrix = Matrix()
// TODO: Make sure these transformations are valid
when (orientation) {
ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> transformationMatrix.postScale(
-1f,
1f
)
ExifInterface.ORIENTATION_ROTATE_180 -> transformationMatrix.postRotate(180f)
ExifInterface.ORIENTATION_FLIP_VERTICAL -> transformationMatrix.postScale(
1f,
-1f
)
ExifInterface.ORIENTATION_TRANSPOSE -> {/* TODO: Transpose the image Matrix */
}
ExifInterface.ORIENTATION_ROTATE_90 -> transformationMatrix.postRotate(90f)
ExifInterface.ORIENTATION_TRANSVERSE -> {/* TODO: Flip horizontally the image Matrix, then transpose it */
}
ExifInterface.ORIENTATION_ROTATE_270 -> transformationMatrix.postRotate(270f)
}
// Crop the bitmap
val croppedBitmap = Bitmap.createBitmap(
originalBitmap,
xStart,
yStart,
size,
size,
transformationMatrix,
true
)
return croppedBitmap
}
}
}

View file

@ -30,4 +30,6 @@
<string name="create_title">Create a new happening</string> <string name="create_title">Create a new happening</string>
<string name="create_name_label">Name</string> <string name="create_name_label">Name</string>
<string name="create_avatar_label">Select happening avatar</string> <string name="create_avatar_label">Select happening avatar</string>
<string name="create_description_label">Description</string>
<string name="create_complete_text">Create</string>
</resources> </resources>