Skip to content

Instantly share code, notes, and snippets.

@rock3r
Created August 25, 2021 18:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rock3r/a9f53217ed3663729108604870df2e4a to your computer and use it in GitHub Desktop.
Save rock3r/a9f53217ed3663729108604870df2e4a to your computer and use it in GitHub Desktop.
Bubble shape — the hard way, because why not.
internal class SpeechBubbleShape(
private val cornerRadius: Dp,
@Px private val stemPosition: Float,
private val stemSize: Dp
) : Shape {
private val bubblePath = Path()
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline = with(density) {
Outline.Generic(createSpeechBubblePath(size, cornerRadius.toPx(), stemPosition, stemSize.toPx()))
}
private fun createSpeechBubblePath(
size: Size,
@Px cornerRadius: Float,
@Px stemPosition: Float,
@Px stemSize: Float
): Path {
// /\
// / \
// _____/ \__________________
// / \
// | |
// | |
// | |
// \_____________________________/
bubblePath.apply {
reset()
val cornerDiameter = cornerRadius * 2
// Top left rounded corner
arcTo(
rect = Rect(left = 0f, top = stemSize, right = cornerDiameter, bottom = stemSize + cornerDiameter),
startAngleDegrees = 180f,
sweepAngleDegrees = 90f,
forceMoveTo = false
)
// Left-hand part of the top edge of the rounded rect
lineTo(x = stemPosition - (stemSize / 2), y = stemSize)
// Stem
lineTo(x = stemPosition, y = 0f)
lineTo(x = stemPosition + (stemSize / 2), y = stemSize)
// Right-hand part of the top edge of the rounded rect
lineTo(x = size.width - cornerRadius, y = stemSize)
// Top right rounded corner
arcTo(
rect = Rect(left = size.width - cornerDiameter, top = stemSize, right = size.width, bottom = stemSize + cornerDiameter),
startAngleDegrees = 270f,
sweepAngleDegrees = 90f,
forceMoveTo = false
)
// Right edge
lineTo(x = size.width, y = size.height - cornerRadius)
// Bottom right rounded corner
arcTo(
rect = Rect(left = size.width - cornerDiameter, top = size.height - cornerDiameter, right = size.width, bottom = size.height),
startAngleDegrees = 0f,
sweepAngleDegrees = 90f,
forceMoveTo = false
)
// Bottom edge
lineTo(x = cornerRadius, y = size.height)
// Bottom left rounded corner
arcTo(
rect = Rect(left = 0f, top = size.height - cornerDiameter, right = cornerDiameter, bottom = size.height),
startAngleDegrees = 90f,
sweepAngleDegrees = 90f,
forceMoveTo = false
)
// Left edge (by cheating)
close()
}
return bubblePath
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment