概要
svg画像からJetpack ComposeのIcons.Default.PersonのようなImageVector画像をプラグインを用いて生成する方法です。
解決したいこと
- SVG画像をJetpack Composeのandroidx.compose.material.iconsのIconsのような感じで使えるようにしたい
- drawableにvectorを追加したくない
- painterResourceを使用することなくsvgをIconとして使えるようにしたい
なぜSVG画像をJetpack ComposeのIconsのような感じで使えるようにしたいのか
Iconsのような感じで使えるようにしたい理由としては下記の理由があります。
- painterResourceを使う方法はAndroidに依存してしまうので、Compose Desktopなどでこの方法を用いることができない
- 宣言的UIなのでxmlなどのリソースに依存するのではなく、コードベースで管理したいというお気持ちがある
なぜdrawableにvector(xml)を追加したくないのか
drawableにvector(xml)を追加する問題点として下記のものがあります。
- リソースが使われなくなった時削除されないまま放置される可能性がある
- ディレクトリに分けてリソースを整理することができない
Iconsの仕組み
IconsはImageVectorを返すような仕組みになっており、初期化されていない状態の時は、
ImageVector.Builderを用いてImageVectorを構築するような仕組みになっています。
今回は下記のようなコードをSVGを元にプラグインを使って生成します。
package androidx.compose.material.icons.filled
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.materialIcon
import androidx.compose.material.icons.materialPath
import androidx.compose.ui.graphics.vector.ImageVector
public val Icons.Filled.Favorite: ImageVector
get() {
if (_favorite != null) {
return _favorite!!
}
_favorite = materialIcon(name = "Filled.Favorite") {
materialPath {
moveTo(12.0f, 21.35f)
lineToRelative(-1.45f, -1.32f)
curveTo(5.4f, 15.36f, 2.0f, 12.28f, 2.0f, 8.5f)
curveTo(2.0f, 5.42f, 4.42f, 3.0f, 7.5f, 3.0f)
curveToRelative(1.74f, 0.0f, 3.41f, 0.81f, 4.5f, 2.09f)
curveTo(13.09f, 3.81f, 14.76f, 3.0f, 16.5f, 3.0f)
curveTo(19.58f, 3.0f, 22.0f, 5.42f, 22.0f, 8.5f)
curveToRelative(0.0f, 3.78f, -3.4f, 6.86f, -8.55f, 11.54f)
lineTo(12.0f, 21.35f)
close()
}
}
return _favorite!!
}
private var _favorite: ImageVector? = null
解決策
解決策としてはSVGをComposeのImageVectorを生成するコードを生成するプラグインがあるのでそれを用いてコードの生成を行います。
プラグインを導入する
SVG画像をComposeに変換してくれるプラグイン「Svg to Compose」というものがあるので
JetBrainsのMarcketspaceからインストールします。
※ Android StudioのPluginsからインストールすることもできます。
https://plugins.jetbrains.com/plugin/18619-svg-to-compose
Accessorを作成する
Accessorとはandroidx.compose.material.iconsでいうところのIconsのようなもので、
このAccessorを経由してImageVectorを取得します。
今回はMyIconsという名前のAccessorを作成しました。
またこのAccessorは後述するSVGをImageVectorに変換する時に必要になります。
object MyIcons {
}
SVGをImageVectorに変換する
ImageVectorを生成したいパッケージを右クリックして、
New → Jetpack Compose ImageVectorを選択します。
画像を選択してImageVectorを生成する
New → Jetpack Compose ImageVectorを選択すると下記のようなダイアログが表示されるので、
Accessor nameにあらかじめ作成しておいたAccessorの名称であるMyIconsを入力し、
Vector images directoryにSVG画像のファイルがあるパスを指定します。
Createを選択すると下記のようなコードが生成されます。
package net.pantasystem.milktea.setting.activities.myicons
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.ImageVector.Builder
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.unit.dp
import net.pantasystem.milktea.setting.activities.MyIcons
public val MyIcons.SettingsFill0Wght400Grad0Opsz48: ImageVector
get() {
if (_settingsFill0Wght400Grad0Opsz48 != null) {
return _settingsFill0Wght400Grad0Opsz48!!
}
_settingsFill0Wght400Grad0Opsz48 = Builder(name = "SettingsFill0Wght400Grad0Opsz48",
defaultWidth = 48.0.dp, defaultHeight = 48.0.dp, viewportWidth = 48.0f,
viewportHeight = 48.0f).apply {
path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f,
strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f,
pathFillType = NonZero) {
moveToRelative(19.4f, 44.0f)
lineToRelative(-1.0f, -6.3f)
quadToRelative(-0.95f, -0.35f, -2.0f, -0.95f)
reflectiveQuadToRelative(-1.85f, -1.25f)
lineToRelative(-5.9f, 2.7f)
lineTo(4.0f, 30.0f)
lineToRelative(5.4f, -3.95f)
quadToRelative(-0.1f, -0.45f, -0.125f, -1.025f)
quadTo(9.25f, 24.45f, 9.25f, 24.0f)
quadToRelative(0.0f, -0.45f, 0.025f, -1.025f)
reflectiveQuadTo(9.4f, 21.95f)
lineTo(4.0f, 18.0f)
lineToRelative(4.65f, -8.2f)
lineToRelative(5.9f, 2.7f)
quadToRelative(0.8f, -0.65f, 1.85f, -1.25f)
reflectiveQuadToRelative(2.0f, -0.9f)
lineToRelative(1.0f, -6.35f)
horizontalLineToRelative(9.2f)
lineToRelative(1.0f, 6.3f)
quadToRelative(0.95f, 0.35f, 2.025f, 0.925f)
quadTo(32.7f, 11.8f, 33.45f, 12.5f)
lineToRelative(5.9f, -2.7f)
lineTo(44.0f, 18.0f)
lineToRelative(-5.4f, 3.85f)
quadToRelative(0.1f, 0.5f, 0.125f, 1.075f)
quadToRelative(0.025f, 0.575f, 0.025f, 1.075f)
reflectiveQuadToRelative(-0.025f, 1.05f)
quadToRelative(-0.025f, 0.55f, -0.125f, 1.05f)
lineTo(44.0f, 30.0f)
lineToRelative(-4.65f, 8.2f)
lineToRelative(-5.9f, -2.7f)
quadToRelative(-0.8f, 0.65f, -1.825f, 1.275f)
quadToRelative(-1.025f, 0.625f, -2.025f, 0.925f)
lineToRelative(-1.0f, 6.3f)
close()
moveTo(24.0f, 30.5f)
quadToRelative(2.7f, 0.0f, 4.6f, -1.9f)
quadToRelative(1.9f, -1.9f, 1.9f, -4.6f)
quadToRelative(0.0f, -2.7f, -1.9f, -4.6f)
quadToRelative(-1.9f, -1.9f, -4.6f, -1.9f)
quadToRelative(-2.7f, 0.0f, -4.6f, 1.9f)
quadToRelative(-1.9f, 1.9f, -1.9f, 4.6f)
quadToRelative(0.0f, 2.7f, 1.9f, 4.6f)
quadToRelative(1.9f, 1.9f, 4.6f, 1.9f)
close()
moveTo(24.0f, 27.5f)
quadToRelative(-1.45f, 0.0f, -2.475f, -1.025f)
quadTo(20.5f, 25.45f, 20.5f, 24.0f)
quadToRelative(0.0f, -1.45f, 1.025f, -2.475f)
quadTo(22.55f, 20.5f, 24.0f, 20.5f)
quadToRelative(1.45f, 0.0f, 2.475f, 1.025f)
quadTo(27.5f, 22.55f, 27.5f, 24.0f)
quadToRelative(0.0f, 1.45f, -1.025f, 2.475f)
quadTo(25.45f, 27.5f, 24.0f, 27.5f)
close()
moveTo(24.0f, 24.0f)
close()
moveTo(21.8f, 41.0f)
horizontalLineToRelative(4.4f)
lineToRelative(0.7f, -5.6f)
quadToRelative(1.65f, -0.4f, 3.125f, -1.25f)
reflectiveQuadTo(32.7f, 32.1f)
lineToRelative(5.3f, 2.3f)
lineToRelative(2.0f, -3.6f)
lineToRelative(-4.7f, -3.45f)
quadToRelative(0.2f, -0.85f, 0.325f, -1.675f)
quadToRelative(0.125f, -0.825f, 0.125f, -1.675f)
quadToRelative(0.0f, -0.85f, -0.1f, -1.675f)
quadToRelative(-0.1f, -0.825f, -0.35f, -1.675f)
lineTo(40.0f, 17.2f)
lineToRelative(-2.0f, -3.6f)
lineToRelative(-5.3f, 2.3f)
quadToRelative(-1.15f, -1.3f, -2.6f, -2.175f)
quadToRelative(-1.45f, -0.875f, -3.2f, -1.125f)
lineTo(26.2f, 7.0f)
horizontalLineToRelative(-4.4f)
lineToRelative(-0.7f, 5.6f)
quadToRelative(-1.7f, 0.35f, -3.175f, 1.2f)
quadToRelative(-1.475f, 0.85f, -2.625f, 2.1f)
lineTo(10.0f, 13.6f)
lineToRelative(-2.0f, 3.6f)
lineToRelative(4.7f, 3.45f)
quadToRelative(-0.2f, 0.85f, -0.325f, 1.675f)
quadToRelative(-0.125f, 0.825f, -0.125f, 1.675f)
quadToRelative(0.0f, 0.85f, 0.125f, 1.675f)
quadToRelative(0.125f, 0.825f, 0.325f, 1.675f)
lineTo(8.0f, 30.8f)
lineToRelative(2.0f, 3.6f)
lineToRelative(5.3f, -2.3f)
quadToRelative(1.2f, 1.2f, 2.675f, 2.05f)
quadTo(19.45f, 35.0f, 21.1f, 35.4f)
close()
}
}
.build()
return _settingsFill0Wght400Grad0Opsz48!!
}
private var _settingsFill0Wght400Grad0Opsz48: ImageVector? = null
名称などを調節する
元々のSVGの名称から名称が決定されてしまい、場合によっては扱いづらいこともあるので適切な名前にリネームしてください。
実際に使用する
うまくいくと下記のように扱うことができると思います。
@Composable
fun SettingIconComponent() {
Icon(MyIcons.SettingsFill0Wght400Grad0Opsz48, contentDescription = "testtest")
}
まとめ
- Svg to ComposeというプラグインでSVGをImageVectorを生成するコードを生成することができる
- この方法を用いることによって、独自のリソースをandroidx.compose.material.iconsのIconsのような感じで扱えるようにできる
- Androidに依存していないため、Comopse Desktopなどでもこの方法を用いて独自のSVGアイコンを使用することができるようになる。