For a complete example check MainActivity.kt in the app module
First create the model list by instantiating objects from the different implementations of BaseSpotlight:
- FadingSpotlight
- ScalingSpotlight
- SlidingSpotlight
- StaticSpotlight
Most attributes have default values, you will only need the position (epresented with a Rect object) and the composable to show on top.
Example:
private fun firstSpotlight(rect: Rect) = ScalingSpotlight(
rectangle = rect,
isCircular = false,
) {
ConstraintLayout(Modifier.fillMaxSize()) {
val text = createRef()
val topGuideline = createGuidelineFromTop(with(LocalDensity.current) {
rect.top.toInt().toDp()
})
val startGuideline = createGuidelineFromStart(with(LocalDensity.current) {
rect.left.toInt().toDp()
})
Text("Here you can see the weather", color = Color.White,
modifier = Modifier.constrainAs(text) {
bottom.linkTo(topGuideline)
start.linkTo(startGuideline)
}
)
}
}
Finally, add a SpotlightContainer() passing the list and a callback for when the last one is closed.
@Composable
fun Content() {
var hintList by remember { mutableStateOf<List<Rect>?>(null) }
var showOnBoarding by remember { mutableStateOf(true) }
Box(
Modifier
.fillMaxSize()
) {
Home { hintList = it }
hintList?.let {
if (showOnBoarding) {
SpotlightContainer(spotlights = it.mapIndexed { index, rect ->
when (index) {
0 -> firstSpotlight(rect)
1 -> secondSpotlight(rect)
2 -> thirdSpotlight(rect)
else -> fourthSpotlight(rect)
}
}) {
showOnBoarding = false
}
}
}
}
}
In the example the Home composable has a callback to load the list and the onboarding is showed when the list is ready.
In compose you can use the modifier onGloballyPositioned to get the position.
FloatingActionButton(onClick = onClick, modifier = Modifier.onGloballyPositioned {
it.boundsInRoot // type:Rect
})
In traditional activities and fragments you can add the container in a composeView and create the rectangle like this:
private fun firstSpotlight() = FadingSpotlight(
rectangle = Rect(
binding.text.left.toFloat(),
binding.text.top.toFloat(),
binding.text.right.toFloat(),
binding.text.bottom.toFloat()
),
isCircular = false,
) {
...
}