mirror of
https://github.com/Steffo99/twom.git
synced 2024-11-25 17:44:24 +00:00
Complete CreateActivityContent
This commit is contained in:
parent
6804058474
commit
8d32d17d32
3 changed files with 118 additions and 80 deletions
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
87
app/src/main/java/eu/steffo/twom/create/ImageHandler.kt
Normal file
87
app/src/main/java/eu/steffo/twom/create/ImageHandler.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
Loading…
Reference in a new issue