I'm storing a material icon in a data class like so:
import androidx.compose.ui.graphics.vector.ImageVector
data class Item(
val icon: ImageVector
)
val item = Item(Icons.Filled.Send)
The item is later passed to a composable where it's drawn using a VectorPainter
.
How do I rotate the ImageVector
by 90 degrees? Ideally this would result in an ImageVector
that I can still store in the data class.
You can build a rotated ImageVector
copying all the groups and paths from the source ImageVector
, and applying required rotation parameter (combined with correct values of pivotX
/pivotY
that determines the center point of rotation).
fun ImageVector.Companion.copyFrom(
src: ImageVector,
rotation: Float = src.root.rotation,
pivotX: Float = src.root.pivotX,
pivotY: Float = src.root.pivotY,
) = ImageVector.Builder(
name = src.name,
defaultWidth = src.defaultWidth,
defaultHeight = src.defaultHeight,
viewportWidth = src.viewportWidth,
viewportHeight = src.viewportHeight,
tintColor = src.tintColor,
tintBlendMode = src.tintBlendMode,
autoMirror = src.autoMirror,
).addGroup(
src = src.root,
rotation = rotation,
pivotX = pivotX,
pivotY = pivotY,
).build()
private fun ImageVector.Builder.addNode(node: VectorNode) {
when (node) {
is VectorGroup -> addGroup(node)
is VectorPath -> addPath(node)
}
}
private fun ImageVector.Builder.addGroup(
src: VectorGroup,
rotation: Float = src.rotation,
pivotX: Float = src.pivotX,
pivotY: Float = src.pivotY,
) = apply {
group(
name = src.name,
rotate = rotation,
pivotX = pivotX,
pivotY = pivotY,
scaleX = src.scaleX,
scaleY = src.scaleY,
translationX = src.translationX,
translationY = src.translationY,
clipPathData = src.clipPathData,
) {
src.forEach { addNode(it) }
}
}
private fun ImageVector.Builder.addPath(src: VectorPath) = apply {
addPath(
pathData = src.pathData,
pathFillType = src.pathFillType,
name = src.name,
fill = src.fill,
fillAlpha = src.fillAlpha,
stroke = src.stroke,
strokeAlpha = src.strokeAlpha,
strokeLineWidth = src.strokeLineWidth,
strokeLineCap = src.strokeLineCap,
strokeLineJoin = src.strokeLineJoin,
strokeLineMiter = src.strokeLineMiter,
)
}
The usage can look like this:
val icon = ImageVector.vectorResource(R.drawable.ic_smile)
val rotatedIcon = ImageVector.copyFrom(
src = icon,
rotation = 90f,
pivotX = icon.defaultWidth.value / 2,
pivotY = icon.defaultHeight.value / 2,
)