There is a similar question Another similar question.
But it doesn't solve my problem.
I get this error "#Composable invocations can only happen from the context of a #composable function" after building my project, even though the preview is working fine.
This is my code:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp {
SplashUI()
}
}
}
#Composable
fun SplashUI() {
Image(painterResource(R.drawable.logo_voodlee),"content description")
}
#Composable
fun MyApp(content: #Composable () -> Unit) {
MaterialTheme {
Surface(color = Color.Yellow) {
content()
}
}
}
#Preview("MyScreen preview")
#Composable
fun DefaultPreview() {
MyApp {
SplashUI()
}
}
Been stuck at this for hours.
Please help me fix this!!!
Found the solution. I had imported the wrong setContent, and had missed adding the dependency "androidx.activity:activity-compose:1.3.0-alpha05"
Added it, and then imported the right setContent, i.e androidx.activity.compose.setContent - this solved the issue.
Related
I want to change the text that's appearing on the button each time I click it, so I have written the following code, but it's not working. Where am I going wrong?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var i=0;
Button(onClick = {i++ }) {
Text("Clicked $i times") //!!not updating here
}
}
}
}
Check how compose works with states and recomposition.
Use something like:
var i by remember { mutableStateOf(0) }
Button(onClick = {i++ }) {
Text("Clicked $i times")
}
I'm having issues whit the onClick on Jetpack compose, it performs the click as soon as I run the app and after returning to this activity the button stops working. Any insights?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val context = LocalContext.current
linkButton("Go to text views", goTo(context, TextViewActivity::class.java))
}
}
}
#Composable
fun linkButton(msg: String, link: Unit) {
Button(onClick = {
link
}) {
Text(msg)
}
}
#Preview
#Composable
fun PreviewMessageCard() {
val context = LocalContext.current
linkButton(
msg = "Sample",
link = goTo(context, TextViewActivity::class.java)
)
}
private fun goTo(context: Context, clazz: Class<*>) {
context.startActivity(Intent(context, clazz))
}
You are actually calling the method at the moment you are composing the linkButton, not passing it as a callback to be called on click. And on click, it is just returning a Unit which causes the unexpected behavior.
To fix that, you should change the parameter type in your composable function to () -> Unit, which represents a function type.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val context = LocalContext.current
linkButton("Go to text views") {
goTo(context, TextViewActivity::class.java)
}
}
}
}
#Composable
fun LinkButton(msg: String, link: () -> Unit) {
Button(onClick = {
link()
}) {
Text(msg)
}
}
I wanted to build a very simple demo. A button which you can click, and it counts the clicks.
Code looks like this:
class MainActivity : ComponentActivity() {
private var clicks = mutableStateOf(0)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Surface(color = MaterialTheme.colors.background) {
NewsStory(clicks.value) { onClick() }
}
}
}
private fun onClick() {
clicks.value++
}
}
#Composable
fun NewsStory(clicks: Int, onClick: () -> Unit) {
Column(modifier = Modifier.padding(8.dp)) {
Button(onClick = onClick) {
Text("Clicked: $clicks")
}
}
}
From my understanding this should be recomposed everytime the button is clicked, as clicks is changed.
But it does not work, any ideas what I'm doing wrong here?
I'm on androidx.activity:activity-compose:1.3.0-beta01, kotlin 1.5.10 and compose version 1.0.0-beta08
You need to use the "remember" keyword for the recomposition to happen each time, as explained here: https://foso.github.io/Jetpack-Compose-Playground/general/state/
In short, your composable would look like this:
#Composable
fun NewsStory (){
val clickState = remember { mutableStateOf(0) }
Column (modifier = Modifier.padding(8.dp)) {
Button(
onClick = { clickState.value++ }) {
}
Text("Clicked: $clickState.value.toString()")
}
}
I have tried to basic composable codelab exercise. In Android Studio BasicCodelabThemes shows as an error. Please help me to find the error
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp {
Greeting("Android")
}
}
}
}
#Composable
fun MyApp(content:#Composable () -> Unit) {
BasicsCodelabTheme {
Surface(color = Color.Yellow) {
content()
}
}
}
#Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
Yeah from my research on the BasicCodelabTheme, it is a custom-built composable function, it isn't a predefined one, so you need to create it yourself in your Kotlin file as a composable function for your theme.BasicCodelabTheme function definition
Let's consider the following #Composable functions:
#Composable
fun WelcomeScreen() {
...
ButtonTheme {
Button(...) {...}
}
}
#Composable
#Preview
fun MockWelcome() {
AppTheme {
WelcomeScreen { }
}
}
#Composable
#Preview
fun MockDarkWelcome() {
AppTheme(darkTheme = true) {
WelcomeScreen { }
}
}
And theme (note: AppTheme follows the same logic):
#Composable
fun ButtonTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: #Composable () -> Unit) {
MaterialTheme(
...
colors = if (darkTheme) darkButtonColorPalette else lightButtonColorPalette,
)
}
The preview window will show both WelcomeScreen versions correctly but the dark version will not show the button in the dark theme.
Running the app everything is OK, this it's only a preview "problem".
So, my question is: is this intended behaviour, a bug, or a misconfiguration?
Full code here: https://github.com/GuilhE/JetpackChallenge
If you join together the previews and screen together you effectively have something like this:
AppTheme(darkTheme = true) {
ButtonTheme {
Button(...) {...}
}
}
So the ButtonTheme will always be used no matter what theme you use in preview - the preview theme is overridden always.
To make the previews work as you want you'd need to abstract ButtonTheme outside of WelcomeScreen so something like this:
#Composable
fun MyApp() {
...
MyTheme {
WelcomeScreen()
}
}
#Composable
fun WelcomeScreen() {
...
Button(...) {...}
}
#Composable
#Preview
fun MockWelcome() {
AppTheme {
WelcomeScreen { }
}
}
#Composable
#Preview
fun MockDarkWelcome() {
AppTheme(darkTheme = true) {
WelcomeScreen { }
}
}