[Android] SHAPEタグを使って出来ること〜画像ファイルを使わずにボタンや背景をカスタマイズする〜

2016.03.15

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

最近の端末は1昔前と違い性能が向上したのであまり画像のサイズを気にする必要はないかもしれませんが、ボタンやviewの背景に画像を使わないことでアプリサイズを軽くすることができます。selectorタグと併用して状態変化に対応に応じて表示を変えたりといったこともできます。

公式ドキュメント

以下はGoogle公式ページの引用になります。

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape=["rectangle" | "oval" | "line" | "ring"] >
    <corners
        android:radius="integer"
        android:topLeftRadius="integer"
        android:topRightRadius="integer"
        android:bottomLeftRadius="integer"
        android:bottomRightRadius="integer" />
    <gradient
        android:angle="integer"
        android:centerX="integer"
        android:centerY="integer"
        android:centerColor="integer"
        android:endColor="color"
        android:gradientRadius="integer"
        android:startColor="color"
        android:type=["linear" | "radial" | "sweep"]
        android:useLevel=["true" | "false"] />
    <padding
        android:left="integer"
        android:top="integer"
        android:right="integer"
        android:bottom="integer" />
    <size
        android:width="integer"
        android:height="integer" />
    <solid
        android:color="color" />
    <stroke
        android:width="integer"
        android:color="color"
        android:dashWidth="integer"
        android:dashGap="integer" />
</shape>

使い方

shapeの種類は以下の4種類が用意されています。

  • rectangle : 四角形
  • oval : 楕円
  • line : 直線
  • ring : 円形

shapeがringの時のみ以下の4種類のパラメータは使用できます。

  • innerRadius : 円の中心から内側の円までの幅(単位 dp)
  • thickness : 内側の円と外側の円の幅 (単位 dp)
  • thicknessRatio : thicknessRatio/width の結果がthicknessとなる (例えばwidthが200dpでthicknessRatio="5"の場合 thicknessは40dpとなる
  • useLevel level-listを使用する際にtrueを指定する。

corners

角丸を表現するためにはcornersのパラメータをdpで入力します。入力する値が角丸の半径になります。

gradient

グラデーションを表現します。
android:angle 0で左から右、90で下から上、180で右から左、270で上から下へのグラデーションを表現します。(0-360)
android:centerX 横軸の中心の位置を指定します(0-1.0)
android:centerY 縦軸の中心の位置を指定します(0-1.0)
android:gradientRadius 「android:type="radial"」の時のみ使用可能。グラデーションの半径を指定します。(単位 dp)

stroke

dashWidthとdashGapで点線を表現します。dashWidthで1つの点の幅、dashGapで点と点の間の幅を指定します。(単位 dp)

実例

スクリーンショット 2016-03-15 0.25.35

rectangle.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="false" android:state_pressed="false">
        <shape android:shape="rectangle">
            <corners android:radius="10dp" />
            <size android:width="100dp" android:height="100dp" />
            <stroke android:width="4dp" android:color="#666666" />
            <gradient android:angle="270" android:centerColor="@color/navy" android:centerX="0.2" android:centerY="0.2" android:gradientRadius="100dp" android:type="radial" />
        </shape>
    </item>
</selector>

line.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="false" android:state_pressed="false">
        <shape android:shape="line">
            <stroke android:width="10dp" android:color="#666666" android:dashGap="3dp" android:dashWidth="5dp" />
            <padding android:bottom="15dp" android:top="30dp" />
        </shape>
    </item>
</selector>

oval.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="false" android:state_pressed="false">
        <shape android:shape="oval">
            <solid android:color="#666666" />
            <size android:width="200dp" android:height="100dp" />
            <stroke android:width="4dp" android:color="#666666" />
            <gradient android:angle="90" android:centerColor="@color/navy" android:centerX="0" android:centerY="0" android:gradientRadius="90" android:type="linear" />
        </shape>
    </item>
</selector>

ring.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="false" android:state_pressed="false">
        <shape android:innerRadius="40dp" android:shape="ring" android:thicknessRatio="5" android:useLevel="false">
            <size android:width="150dp" android:height="150dp" />
            <stroke android:width="4dp" android:color="#666666" />
            <gradient android:angle="180" android:startColor="@color/navy" />
        </shape>
    </item>
</selector>

最後に

selecterタグとitemタグについては別の機会にご紹介します。