我正在使用 Jetpack Compose 在 Android Studio 中创建一个应用程序。在主屏幕中,我有一个按钮,当它被点击时,它会通过
registerForActivityResult(ActivityResultContracts.PickVisualMedia())
打开图库,然后当图像被选中时,它会导航到显示图像的另一个屏幕,然后用 MlKit vision 进行分析。这是主要活动
private val selectMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()){ uri ->
if (uri != null){
val encodedUri = Uri.encode(
uri
.toString()
.replace('%', '|')
)
}
}
@ExperimentalPermissionsApi
@ExperimentalCoroutinesApi
@ExperimentalCoilApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
AppNavigation(navController = navController, selectMedia, encodedUri)
}
这是主屏幕,当单击按钮时,画廊将启动,并使用 LaunchedEffect 导航到另一个屏幕
ox(
Modifier
.weight(1f)
.clickable {
selectMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))
}, contentAlignment = Alignment.Center) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
val gallery =
painterResource(id = R.drawable.icons8_im_genes_de_carpetas_32__1_)
Image(
painter = gallery,
contentDescription = null,
modifier = Modifier.size(36.dp, 36.dp)
)
Text(text = "Imágenes", fontFamily = Inter, fontSize = 12.sp)
}
}
LaunchedEffect(key1 = selectMedia){
navController.popBackStack()
navController.navigate(AppScreens.SecondScreenImage.route + "/{$encodedUri}")
}
这是接收uri的文件
val imageUri = textUri?.toUri()
val textChanged = mutableStateOf("")
val recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)
val image = InputImage.fromFilePath(context, imageUri!!)
recognizer.process(image)
.addOnSuccessListener {
textChanged.value = it.text
}
.addOnFailureListener {
Log.e("TEXT_REC", it.message.toString())
}
我需要对 Uri 进行编码以便通过 navController 发送它,但我认为我遇到的问题是 encodedUri 常量为空或至少为空字符串,当它到达最终屏幕时,它是转向 Uri,它没有要转换的内容,因为我得到的错误出现在图像常量的最后一个屏幕中。 我能做什么?当 encodedUri 常量在 MainActivity 中并且在常量中它没有范围时,我如何访问它?
这里的主要问题是你的
LaunchedEffect
。您正在使用 selectMedia
作为键 - 这是错误的。启动效果会在第一次合成时运行,然后在其键更改时运行。在您的情况下,密钥永远不会改变。您需要做的是将您的 LaunchedEffect 基于 uri:
LaunchedEffect(encodedUri) {
if (encodedUri != null) {
// navigate
}
}
在你的活动中,
encodedUri
必须是State
,或者其他一些可观察的对象:
var encodedUri by mutableStateOf<String?>(null)
如果您不需要在 Activity 中定义启动器,最好将其完全移动到组合中:
@Composable
fun Screen() {
val selectMedia = rememberLauncherForActivityResult(
contract = ActivityResultContracts.PickVisualMedia(),
){ uri ->
// parse uri and navigate from here
val encodedUri = ...
navController.navigate(...)
}
Button(onClick = { selectMedia.launch(...) }) {}
}
那是因为您没有更新值并且没有将其传递给 App Navigation 可组合项,您应该使编码的 uri 可变状态,以修复将以下内容添加到您的主要 Activity 也通过提升状态(提升在 MainActivity 中启动状态):
val encodedUri = remember { mutableStateOf<String?>(null) }
更新 slecetMedia 值:
private val selectMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
if (uri != null) {
encodedUri.value = Uri.encode(
uri
.toString()
.replace('%', '|')
)
}
}
然后将 encodedUri 的状态传递给 AppNavigation 可组合项:
AppNavigation(navController = navController, selectMedia, encodedUri)
更新 launchedEffect 以处理空值,如果编码状态值不为空,它将导航,如果为空,则不会导航:
LaunchedEffect(key1 = selectMedia) {
if (encodedUri != null) {
navController.popBackStack()
navController.navigate(AppScreens.SecondScreenImage.route + "/{$encodedUri}")
}
}