以前に書いた Kotlin による簡易SVG parser の実装実験 を使って自前のAndroidアプリのアイコン描画などを行っていたのだが、 そんなの標準に提供されているライブラリで対処できるだろう、と思って調べたところ対処できたのでメモしておきます。
やりたいことは、SVGコマンドを android.graphics.Path に変換して、たとえば、 android.graphics.Canvas に drawPath() して、カスタムViewなどで表示させることです。 結論だけを先に書くと androidx.core.graphics.PathParser.createPathFromPathData() を使えばよい。
https://developer.mozilla.org/ja/docs/Web/SVG/Tutorial/Paths を参考に自分でコマンドを書いてもよいのですが、ここでは既存のSVGコマンドを利用してみます。 さまざまなSVGアイコンが用意されているマテリアルデザインのサイト: https://material.io/resources/icons/ から zoom_in-24px.svg をダウンロードします。
中身を見てみると:
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/><path d="M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z"/></svg>
縦横 24ピクセル の正方形のアイコンです。
SVGコマンドは path d="(SVGコマンド...)" の部分に記述されています。
androidx.core.graphics.PathParser.createPathFromPathData("SVGコマンド") を使えば Path に変換できる。
具体的には以下のようにカスタム View を書く( kotlin ):
class SvgView: View {
constructor(ctx: Context) : super(ctx) {}
constructor(ctx: Context, attributeSet: AttributeSet) : super(ctx, attributeSet) {}
private companion object {
const val svgCmd =
"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
val svgPath: Path = PathParser.createPathFromPathData(svgCmd)
}
private val paint = Paint()
init {
paint.isAntiAlias = true
paint.style = Paint.Style.FILL
paint.color = Color.BLUE
}
override fun draw(canvas: Canvas?) {
super.draw(canvas)
canvas?.drawPath(svgPath, paint)
}
}
結果:
ちっさ。
実行するデバイスにもよりますが、24px サイズでは小さすぎます。 これを例えば 5倍に拡大してみます。 path.transform(matrix) を使って変形(拡大)します。
init に 5倍にパスを拡大するコードを追加:
init {
paint.isAntiAlias = true
paint.style = Paint.Style.FILL
paint.color = Color.BLUE
//
// svgPath を 5倍に拡大
//
val matrix = Matrix()
matrix.setValues(floatArrayOf(
5f, 0f, 0f,
0f, 5f, 0f,
0f, 0f, 1f
))
svgPath.transform(matrix)
}
結果:
Androidでは、XML定義経由でSVGコマンドをアイコン等で利用するだけでなく、 プログラム的にSVGコマンドをPathに変換するのも簡単にできる。