Home > OS >  @Composable invocations can only happen from the context of a @Composable function in android
@Composable invocations can only happen from the context of a @Composable function in android

Time:10-19

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.

Official Docs

Some Related Posts

Philipp Lackner's Note App

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")
        }
  • Related