Last active
April 11, 2024 05:03
-
-
Save andrew-levy/a200152de34bd3382c536b8dc4ec6669 to your computer and use it in GitHub Desktop.
JetpackComposeViewModule
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package expo.modules.jetpackcomposeview | |
import android.content.Context | |
import androidx.compose.animation.animateColorAsState | |
import androidx.compose.animation.core.animateFloatAsState | |
import androidx.compose.foundation.layout.Arrangement | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.fillMaxSize | |
import androidx.compose.foundation.layout.padding | |
import androidx.compose.material3.* | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.mutableStateOf | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.setValue | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.graphics.graphicsLayer | |
import androidx.compose.ui.platform.ComposeView | |
import androidx.compose.ui.unit.dp | |
import expo.modules.kotlin.AppContext | |
import expo.modules.kotlin.views.ExpoView | |
class JetpackComposeView(context: Context, appContext: AppContext) : ExpoView(context, appContext) { | |
internal val composeView = ComposeView(context).also { | |
// add the compose view as a child | |
addView(it) | |
it.layoutParams = LayoutParams( | |
android.view.ViewGroup.LayoutParams.MATCH_PARENT, | |
android.view.ViewGroup.LayoutParams.MATCH_PARENT, | |
) | |
it.setContent { | |
Greeting("Compose") | |
} | |
} | |
// update the text | |
fun updateText(newValue: String) { | |
composeText.setContent { | |
Greeting(newValue) | |
} | |
} | |
} | |
// Composable here | |
@Composable | |
fun Greeting(name: String) { | |
var isChecked by remember { mutableStateOf(false) } | |
var isDialogOpen by remember { mutableStateOf(false) } | |
var sliderPosition by remember { mutableStateOf(0f) } | |
var animateText by remember { mutableStateOf(false) } | |
val scaleText by animateFloatAsState(targetValue = if (animateText) 1.5f else 1f, label = "") | |
val textColor by animateColorAsState(targetValue = if (animateText) Color.Blue else Color.Black, label = "") | |
Column( | |
modifier = Modifier.fillMaxSize(), | |
verticalArrangement = Arrangement.Center, | |
horizontalAlignment = Alignment.CenterHorizontally | |
) { | |
Text( | |
text = "Expo + $name!", | |
style = MaterialTheme.typography.titleLarge, | |
color = textColor, | |
modifier = Modifier.graphicsLayer(scaleX = scaleText, scaleY = scaleText) | |
) | |
Button( | |
onClick = { | |
animateText = !animateText | |
}, | |
modifier = Modifier.padding(16.dp) | |
) { Text(text = "Animate") } | |
Switch( | |
checked = isChecked, | |
onCheckedChange = { isChecked = it }, | |
modifier = Modifier.padding(16.dp) | |
) | |
Slider( | |
value = sliderPosition, | |
onValueChange = { sliderPosition = it }, | |
modifier = Modifier.padding(16.dp) | |
) | |
Button( | |
onClick = { | |
isDialogOpen = true | |
}, | |
modifier = Modifier.padding(16.dp) | |
) { | |
Text(text = "Click Me") | |
} | |
if (isDialogOpen) { | |
AlertDialogExample( | |
onDismissRequest = { | |
isDialogOpen = false | |
}, | |
onConfirmation = { | |
isDialogOpen = false | |
}, | |
dialogTitle = "Dialog Title", | |
dialogText = "Dialog Text" | |
) | |
} | |
} | |
} | |
@OptIn(ExperimentalMaterial3Api::class) | |
@Composable | |
fun AlertDialogExample( | |
onDismissRequest: () -> Unit, | |
onConfirmation: () -> Unit, | |
dialogTitle: String, | |
dialogText: String, | |
) { | |
AlertDialog( | |
title = { | |
Text(text = dialogTitle) | |
}, | |
text = { | |
Text(text = dialogText) | |
}, | |
onDismissRequest = { | |
onDismissRequest() | |
}, | |
confirmButton = { | |
TextButton( | |
onClick = { | |
onConfirmation() | |
} | |
) { | |
Text("Confirm") | |
} | |
}, | |
dismissButton = { | |
TextButton( | |
onClick = { | |
onDismissRequest() | |
} | |
) { | |
Text("Dismiss") | |
} | |
} | |
) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package expo.modules.jetpackcomposeview | |
import expo.modules.kotlin.modules.Module | |
import expo.modules.kotlin.modules.ModuleDefinition | |
class JetpackComposeViewModule : Module() { | |
override fun definition() = ModuleDefinition { | |
Name("JetpackComposeView") | |
View(JetpackComposeView::class) { | |
Prop("name") { view: JetpackComposeView, prop: String -> | |
view.updateText(prop) | |
println(prop) | |
} | |
} | |
} | |
} |
@corysimmons Thanks! You’ll need to add a bit of setup in your module’s build.gradle file. You can follow this: https://developer.android.com/jetpack/compose/setup
@corysimmons Thanks! You’ll need to add a bit of setup in your module’s build.gradle file. You can follow this: https://developer.android.com/jetpack/compose/setup
Hello @andrew-levy , can you please share with me the build.gradle file that you use to make jetpackCompose work with expo modules.
Module build.gradle example with compose:
https://github.com/andrew-levy/sweet-sheet/blob/main/android/build.gradle
(check the dependencies near the bottom)
Project build.gradle example:
https://github.com/andrew-levy/sweet-sheet/blob/main/example/android/build.gradle
(check line 22)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Very cool @andrew-levy ! 👏
I get errors about not being able to resolve Compose. Do you have instructions on adding those dependencies in an Expo project?