Accessing rememberLauncherForActivityResult from Util / Jetpack Composee

Viewed 675

I have a photo composable that allows the user to pickup the photo from the their mobile gallery.

I want to have this function/service from Util class/Function because i have other composable that needs the same service and i don't want to keep copy/pasting the same code. also this allows me to use it to pick up documents by changing the Mime type from launch { } but this looks tricky for me. if i use a @Composable function, i can't use the .launch also if i kept it as a class with a value the rememberLauncherForActivityResult needs Composable.

any help?

@OptIn(ExperimentalCoilApi::class)
@Composable
fun ContactPagePhoto() {
    val imageUriState = remember {
        mutableStateOf<Uri?>(null)
    }
    val pickingUp = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
        imageUriState.value = it
    }
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .layoutId("userPhoto")
            .fillMaxHeight(0.4f)
            .fillMaxWidth(1f)
    ) {
        imageUriState.value?.let {
            Image(
                modifier = Modifier
                    .align(Alignment.TopCenter)
                    .fillMaxSize(1f),
                contentDescription = "UserImage",
                contentScale = ContentScale.Crop,
                painter = rememberImagePainter(data = it)
            )
        }
    }
    TextButton(
        onClick = { pickingUp.launch("image/*") },
        modifier = Modifier.layoutId("changePhoto")
    ) {
        Text(
            text = "Change Photo",
        color = Color.Black)
    }
}

how i expect to use it... inside ``util``` package i want to create a new kotlin file that has the service i need

I may use a @Composable function that allow me to use rememberLauncherForActivityResult or make a class and extend it to MainActivity to gain access to ComponentActivity() and use registerForActivityResult to get the Uri

like

class PickUp(){
val launcher = registerForActivityResult...
}

or

@Composable
fun pickup():MutableState<Uri>{
rememberLauncherForActivityResult ...
}

just suggesting...

1 Answers

You can do it like this:

class GetContentActivityResult(
    private val launcher: ManagedActivityResultLauncher<String, Uri>,
    val uri: Uri?
) {
    fun launch(mimeType: String) {
        launcher.launch(mimeType)
    }
}

@Composable
fun rememberGetContentActivityResult(): GetContentActivityResult {
    var uri by rememberSaveable { mutableStateOf<Uri?>(null) }
    val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent(), onResult = {
        uri = it
    })
    return remember(launcher, uri) {
        GetContentActivityResult(launcher, uri)
    }
}

Usage:

@Composable
fun ContactPagePhoto() {
    val getContent = rememberGetContentActivityResult()
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .layoutId("userPhoto")
            .fillMaxHeight(0.4f)
            .fillMaxWidth(1f)
    ) {
        getContent.uri?.let {
            Image(
                modifier = Modifier
                    .align(Alignment.TopCenter)
                    .fillMaxSize(1f),
                contentDescription = "UserImage",
                contentScale = ContentScale.Crop,
                painter = rememberImagePainter(data = it)
            )
        }
    }
    TextButton(
        onClick = { getContent.launch("image/*") },
        modifier = Modifier.layoutId("changePhoto")
    ) {
        Text(
            text = "Change Photo",
            color = Color.Black
        )
    }
}
Related