0
1

More than 1 year has passed since last update.

プラグインを使ってSVGからJetpack ComposeのImageVectorを生成する

Last updated at Posted at 2023-02-06

概要

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
スクリーンショット 2023-02-06 15.53.41.png

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画像のファイルがあるパスを指定します。
スクリーンショット 2023-02-06 15.59.43.png

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アイコンを使用することができるようになる。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1