Yo, Yo, 俺らVector xml手書き部
この記事はAndroid 初心者向け Advent Calendar 2019の15日目の記事として登録させていただいています。寝なければまだ今日なのでセーフです。
プロローグ
さて、みなさんはAndroidアプリのリソースになにを使用していますか?pngですか?pngですよね。そうですよねpngですよね。
(webp?知らない子ですね…)
いやまあpngじゃなくてもいいんですけど、Androidでは、画像リソースとしてpngなどのラスタ形式以外にも、ベクター形式の画像を使用することができます。
Androidでのベクターがなんぞや的なアレはアレです、拡大しても画像が荒くなんなくてxmlで表現できるやつです。
詳しくは以下のあたりをば。
このベクター画像、使うとなにが嬉しいかと言うと、 画像サイズの違うだけの同じ画像を複数用意する必要がないのです。
これによってapkサイズも小さくなりハッピー!だったのですが、でかい画像をベクターでやると初回描画に時間がかかる特性に加えて、今はaab使っちゃえばpngとかでも必要なサイズの画像だけよしなにやってくれるのでもうそこまで嬉しいことはなさそう……(要検証)
そこで「Vector xmlを救いたい」と言う思いの元結成されたのが、我々Vector xml手書き部です。
Vector xmlを手書きする
先ほど、ベクター画像を使う利点は同じ画像を複数用意する必要がないこととそこからのapkファイルの縮小と説明しましたが、もう一つ大きな大きな利点が存在します。
このベクター画像、Android Studio上でxmlファイルを編集することで変更を加えることができるのです。
つまり、画像の色を変えたい、縦横比を変更したいなどの場合に、リソースファイルを新たに用意することなくxmlファイルを編集するだけでこれを済ますことができます。
いやまあすごいことっぽく書いてもxmlファイルって時点で当たり前体操なんですが…
Vector画像のxmlファイルの概要
さて、それでは実際にxmlの画像ファイルを見ていきます。
今回のお題は車両通行止めです。
<!-- ちゃんと全部今回のために手書きしたよ!! --> <vector android:height="25dp" android:viewportHeight="1000" android:width="25dp" android:viewportWidth="1000" xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 背景の白 --> <path android:fillColor="@android:color/white" android:pathData="M0,0 L1000,0 1000,1000 0,1000"/> <!-- 赤い円 --> <path android:fillColor="@color/hyousikiRed" android:pathData="M0,500 A500,500 0,1,0 500,0 A500,500 0,0,0 0,500"/> <!--白い線--> <path android:strokeColor="@android:color/white" android:strokeWidth="24" android:pathData="M48,500 A452,452 0,1,0 500,48 A452,452 0,0,0 48,500"/> <!--中の白い円--> <path android:fillColor="@android:color/white" android:pathData="M192,500 A308,308 0,1,0 500,192 A308,308 0,0,0 192,500"/> <!--赤い斜線--> <path android:strokeColor="@color/hyousikiRed" android:strokeWidth="192" android:pathData="M0,0 L1000,1000" android:trimPathStart="0.2" android:trimPathEnd="0.8"/> </vector>
意外と読めますね。
<path />
のタグが一本の線とそれに囲まれた図形を表しており、それらを重ねることでパス図形を表現しています。
<path />
内の要素はここに使われてる以外にもいろいろあり、それぞれ以下の感じです。
要素 | 意味 |
---|---|
strokeColor | 線の色 |
strokeWidth | 線の太さ(px指定) |
strokeAlpha | 線の透明度 |
strokeLineCap | 線端の形状。enum値で指定。ここでも見てくれ |
strokeLineJoin | 線結合部の形状。enum値で指定。ここでも見てくれ |
strokeMiterLimit | 説明が難しいのでここでも見てくれ |
fillColor | 囲まれた範囲の色 |
fillAlpha | 囲まれた範囲の透明度 |
fillType | 説明が難しいのでここを見てくれ |
trimPathStart | 始点をパスの途中の位置に設定できる。0~1で指定 |
trimPathEnd | 終点をパスの途中の位置に設定できる。0~1で指定 |
trimPathOffset | トリムする位置をずらせる。0~1で指定 |
※trim系は特に0.5超えた時の挙動が死ぬほど言葉で説明しづらいので試してみることを推奨します。(正直よくわかってない)
世界一便利な表を作ってしまいましたね。ただのリンク集だけど
勘の良い読者ならもう気づいているでしょうが(言ってみたかった)、これはxmlの皮を被ったsvgです。(名探偵コナン)(筆者はsvgが全くわからない)(野生の馬)
上の表で唯一説明していないpathData
こそがこのパスの本体となっています。
svgの記法で書かれてるのでその記法について詳しくはここを見てくれ!
pathDataの説明
リンク集やってても仕方ないし読んでる人的にもなにが言いたいんじゃだと思うので上の止まれ標識を挙げて実際に説明していきましょう。
まず、簡単な説明として、ここのpathData
、または元となったSVGのd
はいくつかのコマンドにより線(パス)を表し、そこで囲まれた図形(パス図形)とパス自身によってグラフィックを表現します。
とりあえずそれだけ頭に入れてヒャウィゴ!
親要素
まず親要素のコイツについてはなんかまあ見たまんまです。
<vector android:height="25dp" android:viewportHeight="1000" android:width="25dp" android:viewportWidth="1000" xmlns:android="http://schemas.android.com/apk/res/android">
唯一ちょっと見慣れないviewPortなんとか
はpxで表現された画像サイズを表します。
背景の四角
<!-- 背景の白 --> <path android:fillColor="@android:color/white" android:pathData="M0,0 L1000,0 1000,1000 0,1000"/>
pathData
で示された範囲内に白を塗ってます。
pathData
内では、M0,0
で(0,0)の座標に始点を設定、L1000,0 1000,1000 0,1000
で始点から(1000,0), (1000,1000), (0,1000)の順に直線を引いて四角形を表現しています。
ここで使われたコマンドをまとめると、始点を指定するM
コマンドと、現在の点から与えられた点へと直線を描くL
コマンドです。L
コマンドに複数の座標を与えることで、その順に直線を描いています。
そうあと激アツポイントなんですけど@color
とかが参照できます。
円
円については今回3つの要素で描かれています。
赤い円、白い線、中の白い円の3つですね。
これらに使われているコマンドは先ほどの始点を指定するM
以外ではA
だけです。
一番大きな赤い円で見てみましょう。
<!-- 赤い円 --> <path android:fillColor="@color/hyousikiRed" android:pathData="M0,500 A500,500 0,1,0 500,0 A500,500 0,0,0 0,500"/>
まず、M
コマンドで(0, 500)に始点を指定しています。
その後にはA500,500 0,1,0 500,0
が続きます。
A
は弧を描画するコマンドであり、
これは、A(X方向の半径)(Y方向の半径) (円をどれだけ回転させるか),(描く弧が長弧なら1、短弧なら0のフラグ),(弧の向きの0,1フラグ) (終点座標)
で表されます。
このままだと円の一部が切り取られており、綺麗な円になっていないので、この終点から、最初に指定した座標までもう一つA
を使って弧を描いています。
赤い斜線
<!--赤い斜線--> <path android:strokeColor="@color/hyousikiRed" android:strokeWidth="192" android:pathData="M0,0 L1000,1000" android:trimPathStart="0.2" android:trimPathEnd="0.8"/>
この子はそれほど難しくありませんね!
左上から右下までM
とL
を使って線を引き、二つのtrimPathほげほげ
で線の始点と終点を調整しています。
まとめ
どうです?意外と書けそうってなりません!?
まとめとか書いときながら特にまとめることもないのですが、まあxmlで画像やると手書きできるメリットがあるよって話でした。
Android Studioのxml画像のプレビューが変更から一瞬で反映されるので体験としても悪くはないかと思います。
Android 初心者向け Advent Calendar 2019、明日(今日)は@aosa4054さん、よろしくお願いします。僕なんですけどね。 それではまた明日もお会いしましょう。
参考
ここに限らず、調べながら手書きするならSVGで検索することを強くおすすめします。