I'm new to the jetpack compose area, and I'm trying to implement a function inside a button but it gives the following error: @Composable invocations can only happen from the context of a @Composable function in mContext.startActivity(Intent(mContext, MainScreen()::class.java))
If anyone can help me I'm new and I'm killing myself trying to complete a project for my college
@Composable
fun AdminAuth() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
var password by rememberSaveable { mutableStateOf("") }
var passawordVisibility by remember { mutableStateOf(false) }
val icon = if (passawordVisibility)
painterResource(id = R.drawable.ic_visibility)
else
painterResource(id = R.drawable.ic_visibility_off)
Text(text = "Insira a senha do usuário Master:", fontSize = 15.sp)
OutlinedTextField(
value = password,
onValueChange = {
password = it
},
placeholder = { Text(text = "Senha") },
label = { Text(text = "Senha") },
trailingIcon = {
IconButton(onClick = {
passawordVisibility = !passawordVisibility
}) {
Icon(
painter = icon,
contentDescription = "Ícone de visibilidade"
)
}
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password
),
visualTransformation = if (passawordVisibility)
VisualTransformation.None
else PasswordVisualTransformation()
)
val mContext = LocalContext.current
OutlinedButton(
onClick = {
if (password.equals("Abac@xi123")) {
mContext.startActivity(Intent(mContext, MainScreen()::class.java))
}
},
modifier = Modifier
.fillMaxWidth()
.padding(35.dp),
) {
Text(text = "Entrar")
}
}
}
@Composable
@Preview
fun AdminAuthPreview() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
AdminAuth()
}
}
CodePudding user response:
There's nothing wrong calling startActivity
inside onClick
, but you should NOT call the MainScreen's
constructor (assuming it's an Activity
), you can simply remove the parenthesis and it will be fine.
onClick = {
if (password.equals("Abac@xi123")) {
mContext.startActivity(Intent(mContext, MainScreen::class.java))
}
}
But I suspect MainScreen
is just another @Composable
screen and not an Activity
that you want to navigate to and your'e having that error because
you cannot call a composable inside non-composable functions
like the compile error you are seeing.
I would suggest further reading and especially watching the live coding, you will see first hand how to navigate from a composable screen to another.
CodePudding user response:
mContext.startActivity(Intent(mContext, MainScreen()::class.java))
This is not correct way to change Compose. Not even for changing Activity either even if MainScreen is an Activity because of MainScreen() it should be MainScreen
Composable functions are like suspending functions that require you to call them as a lambda, function parameter, insider param or as getter.
What are differents between Composable function and normal function in Android?
@Target(
// function declarations
// @Composable fun Foo() { ... }
// lambda expressions
// val foo = @Composable { ... }
AnnotationTarget.FUNCTION,
// type declarations
// var foo: @Composable () -> Unit = { ... }
// parameter types
// foo: @Composable () -> Unit
AnnotationTarget.TYPE,
// composable types inside of type signatures
// foo: (@Composable () -> Unit) -> Unit
AnnotationTarget.TYPE_PARAMETER,
// composable property getters and setters
// val foo: Int @Composable get() { ... }
// var bar: Int
// @Composable get() { ... }
AnnotationTarget.PROPERTY_GETTER
)
annotation class Composable
If you wish to change UI using Compose you can use
conditional Composition or Compose navigation to navigate to next UI or screen.
Conditional change is generally by a State or a flag
var screenState by remember{mutableStateOf(Idle)}
OutlinedButton(
onClick = {
if (password.equals("Abac@xi123")) {
screenState = Success
}
},
modifier = Modifier
.fillMaxWidth()
.padding(35.dp),
) {
Text(text = "Entrar")
}
when(screenState) {
Idle -> // Show Composable for this state
Success -> // Show Composable when user enters valid password
else -> // Implement other states of UI
}
or using navigation using a callback instead of passing navigationController
and in root navigating using this callback
OutlinedButton(
onClick = {
if (password.equals("Abac@xi123")) {
navigateToSuccessScreen()
}
},
modifier = Modifier
.fillMaxWidth()
.padding(35.dp),
) {
Text(text = "Entrar")
}