ActionBarのメニューにCheckBoxを表示する

前置き

ActionBarでは、メニューをすべて表示することができなかったり"showAsAction="never"を設定したメニューがある場合、一部のメニューをActionBar右端のドロップダウンに格納することがあります。 Andorid Developersではこの機能をAction Overflowと呼んでいます。 Action Overflowに関する細かい機能名称などが見つけられなかったため、この記事ではオーバーフローに格納されているメニューを「オーバーフローメニュー」と呼ぶことにします。 http://developer.android.com/design/patterns/actionbar.html

オーバーフローメニューの活用

ActionBarのオーバーフローメニューにはチェックボックスラジオボタンを表示することができます。 メニューと違って常時表示されないデメリットはありますが、タイトルが表示されるのでどのような機能かわかりやすく、アイコンを用意しなくても良いというメリットもあります。

下の画像はPlayストアアプリでの例です。 Playストアでの例

以下、チェックボックスラジオボタン、それぞれの実装について説明します。 サンプルではappcompat-v7版のActionBarを使用しています。

チェックボックスの実装

チェックボックスを利用する際、オーバーフローメニュー以外ではチェックボックスが表示されない事に気をつけてください。 <item>要素にshowAsAction="never"を設定しておくことで確実にオーバーフローメニューにすることができますが、 showAsAction="always"showAsAction="ifRoom"を定義するとチェックボックスが表示されなくなります。 チェックボックス自体はメニューを定義しているxmlandroid:checkable="true"を加えるだけで表示されます。 最初からチェック済みにしたい場合はandroid:checked="true"を定義してください。

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MyActivity" >
    <item android:id="@+id/action_checkbox"
        android:title="チェックボックス"
        android:checkable="true"
        app:showAsAction="never" />
</menu>

最も注意すべき点として、チェックボックスの状態変更をソースコード上で行う必要があることに気をつけてください。 また、チェックボックスの状態はMenuItem.isChecked()で取得できますが、ユーザ操作がチェックボックスに反映された後かどうかを意識する必要があります。

````MyActivity.java @Override public boolean onCreateOptionsMenu(Menu menu) { // メニュー生成 getMenuInflater().inflate(R.menu.menu, menu); return true; }

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.action_checkbox) {
        // チェックボックスの状態変更を行う
        item.setChecked(!item.isChecked());
        // 反映後の状態を取得する
        boolean checked = item.isChecked();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

````

以下の様な表示になります。 Screenshot_2014-08-31-15-13-57.png

ラジオボタンの実装

ラジオボタンを使うといくつかのオーバーフローメニューからひとつを選ばせるようなUIを作ることができます。 チェックボックス同様、オーバーフローメニュー以外ではラジオボタンが表示されないことに注意してください。 各<item>要素にはshowAsAction="never"を指定する必要があります。

ラジオボタンでは、選択肢となる<item>要素の親として<group>を定義します。 この<group>要素にandroid:checkableBehavior="single"を定義することで、checked状態になる<item>要素をひとつだけに限定することができます。 このとき、各<item>要素にはandroid:checkable="true"を定義するとチェックボックスが表示されてしまうので注意してください。 また、特定の<item>を最初から選択状態にしたい場合はその<item>android:checked="true"を定義してください。

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MyActivity">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/action_radio1"
            android:title="ラジオ1"
            app:showAsAction="never" />
        <item
            android:id="@+id/action_radio2"
            android:title="ラジオ2"
            app:showAsAction="never" />
    </group>

</menu>

ラジオボタンでもチェックボックス同様、状態変更をソースコード上で行う必要があることに気をつけてください。 ただし、android:checkableBehavior="single"を定義している場合、<group>内のどれかひとつがMenuItem#setChecked(true)されたときに他のMenuItemMenuItem#setChecked(false)された状態になるため、選択された要素の状態のみ反映すれば良いことになります。

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id){
            case R.id.action_radio1:
                item.setChecked(!item.isChecked());
                Toast.makeText(this,"action_radio1",Toast.LENGTH_SHORT).show();
                return true;
            case R.id.action_radio2:
                item.setChecked(!item.isChecked());
                Toast.makeText(this,"action_radio2",Toast.LENGTH_SHORT).show();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

以下のような表示になります。 Screenshot_2014-08-31-15-30-21.png

トグルボタンの実装

トグルボタンとは

トグルボタンとは、ユーザが2つの状態(On/Off)を交互に切り替えることのできるUIです。 AndroidではToggleButtonCheckBoxがこれに当たります。 ToggleButton

API Level 14でON/OFFをわかりやすく切り替えるためのViewとしてSwitchが追加されました。 Switch

http://developer.android.com/reference/android/widget/Switch.html

トグルボタンについてより詳しい解説は以下にあります。 http://developer.android.com/guide/topics/ui/controls/togglebutton.html

問題

残念ながら、SwitchはSupportLibraryに含まれていません。 そのため、API Level 14未満の端末ではSwitchを使うことができません。

解決方法

主な解決方法は2つあります。

ひとつはAPI Level 14未満でも動作するSwitchと似たViewを自作することです。 GitHubでも以下のようなバックポートプロジェクトがいくつか存在します。 BoD/android-switch-backport https://github.com/BoD/android-switch-backport

もうひとつの方法は、API Levelに応じて表示するViewを差し替える方法です。 API Level 14以降ではSwitch、それ以前の端末であればToggleButtonというように出し分けを行います。 一件複雑に思えますが、Androidではトグルボタン系のViewをまとめてCompoundButtonとして扱うことができるため、レイアウトファイルを分けるだけで簡単に対応することができます。

実装

まず、API Level 14未満の端末向けにToggleButtonを使ったレイアウトを定義します。 レイアウト階層に「API Level 14未満」という記述はできないので、デフォルトレイアウトに定義する形になります。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MyActivity">

    <ToggleButton
        android:id="@+id/toggle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

次に、API Level 14以上の端末向けにSwitchを使ったレイアウトを定義します。 このとき、レイアウトファイル名とトグルボタンのandroid:idはは完全に一致させる必要があります。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MyActivity">

    <Switch
        android:id="@+id/toggle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

最後に、Activity側の処理です。 ソースコード上ではSwitchToggleButtonも一括してCompoundButtonとして扱います。 CompoundButtonSwitchのように2つの状態を持つViewの抽象クラスで、状態の取得やリスナ関連の処理などが集約されており、 SwitchToggleButtonCheckBoxなどはいずれもCompoundButtonを継承したサブクラスになっています。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity);

        CompoundButton toggle = (CompoundButton)findViewById(R.id.compoundButton);
        toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // 状態が変更された
                Toast.makeText(MyActivity.this, "isChecked : " + isChecked, Toast.LENGTH_SHORT).show();
            }
        });
    }

これでどちらのトグルボタンもタップ時に現在の状態に応じたトーストが表示されるようになります。

結果

ここまでの実装で、以下のように端末バージョンに応じて表示の出し分けができるようになりました。 1枚目が2.3端末、2枚目が4.4端末での表示となります。

 

<uses-permission>設定の罠

<uses-permission>

Androidアプリが特定の機能を利用する場合、AndroidManifest.xmlにその機能の一覧を<uses-permission>として記述します。 たとえば、マイクによる録音を行うアプリの場合、以下の様な記述が必要となります。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.nein37.kanidaisuki" >
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

この<uses-permission>の定義はアプリの中で使用する全ての機能に関して記述します。 <uses-permission>の内容はPlayストアのアプリページに記載され、その機能が重要なものであればインストール時に権限を許可しても良いかを確認するダイアログが表示されます。

<uses-feature>

Androidアプリが特定の機能を必要とする場合、AndroidManifest.xmlにその機能の一覧を<uses-feature>として記述します。 必要とするというのは、例えばOpenGL ESの特定のVersion以降が必要であるとか、カメラ機能が必須であるという場合です。 たとえば、マイク機能が必須であるアプリは以下の様な記述が必要となります。 (この記述だけでは録音機能を使うことはできませんが、マイクは必須となります)

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.nein37.kanidaisuki" >
    <uses-feature android:name="android.hardware.microphone" android:required="true" />

この<uses-feature>情報はPlayストアには記載されません。 <uses-feature>を満たしている端末の場合、Playストア上から何の問題もなくインストールされます。 このとき、<uses-permission>と違い、特に確認ダイアログなどは表示されません。 <uses-feature>を満たしていない端末の場合、そもそもアプリがPlayストア上に表示されません。 ブラウザ版から該当端末にインストールしようとした場合でも「お使いの端末にはインストールできません」という旨のメッセージが表示され、インストールすることができません。

2つの設定の違い

<uses-permission>と<uses-feature>の違いは、それがチェックされるタイミングになります。 <uses-permission>がアプリを許可するかどうかをユーザに判断させているのに対し、 <uses-feature>はそもそもアプリがインストール可能かどうかをPlayストアが判定しています。 <uses-feature>の設定を失敗すると潜在的なアプリユーザを狭めてしまうので、要注意です。

<uses-permission>の罠

<uses-permission>を設定した時、その機能が参照するハードウェア機能の<uses-feature>が暗黙的に設定されます。

    <uses-permission android:name="android.permission.RECORD_AUDIO" />

上記の設定は、Playストア上では以下のように解釈されます。

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-feature android:name="android.hardware.microphone" android:required="true" />

通常、上記のような場合はあまり問題になることはありません。 録音機能を利用するためにマイクが必要なのは当然だからです。 しかし、次の様な場合もあります。

このアプリはメモ録音と文字起こしのためにマイク機能を利用します。しかし必須ではありません。 マイクがない端末でもキーボードによる文字入力で代替したいです。

この時、<uses-permission>だけ設定してしまうと、<uses-feature>も補完されてしまい、マイクがない端末にはインストールできなくなってしまいます。 このように<uses-permission>が必須機能でない場合、以下のように記述します。

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-feature android:name="android.hardware.microphone" android:required="false" />

これでこのアプリにマイクは必須ではないと宣言することができました。 マイクのない端末でもインストールできるようになります。 ただし、実行時にマイクがあるかどうかを判定する必要があるので注意が必要です。

おまけ

<uses-permission>と<uses-feature>の対応表はAndroid Developersの以下のページに書いてあります。 http://developer.android.com/guide/topics/manifest/uses-feature-element.html#permissions

AndroidのUtilsクラスまとめ

はじめに

androidのUtilsをまとめた資料が見当たらなかったので作りました。 android.*パッケージに含まれるものだけまとめています。

TextUtils

文字列操作用Utils。 isEmpty()とかequals()とかよく使う。 文字列操作系も大体揃っていて便利。 isGraphic()とかellipsize()とか使ったことないけど気になるメソッドもある。 SupportLibraryに最新版との差分をまとめたTextUtilsCompatがある。 http://developer.android.com/reference/android/text/TextUtils.html http://developer.android.com/reference/android/support/v4/text/TextUtilsCompat.html

NavUtils

Up動作を実装するのに使う。 これだけ使っても思ったように実装できないことが多い気がする。 Up動作の実装については以前まとめたhttp://developer.android.com/reference/android/support/v4/app/NavUtils.html

DatabaseUtils

DBとCursorを扱うためのUtils。 Cursorの中身をContentValuesに入れるメソッドが大量にある。 concatenateWhere()という2つのwhere句をANDでつないでくれるメソッドが微妙に便利。 SupportLibraryに最新版との差分をまとめたDatabaseUtilsCompatがある。 http://developer.android.com/reference/android/database/DatabaseUtils.html http://developer.android.com/reference/android/support/v4/database/DatabaseUtilsCompat.html

DateUtils

formatDateRange()formatDateTime()で色々な日付表現ができる。 でも大抵はSimpleDateFormatで事足りるイメージ。 非推奨のメソッドもあるので、使う際は注意。 http://developer.android.com/reference/android/text/format/DateUtils.html

URLUtil

URLを扱うためのUtils。 ただしURL型ではなくStringのみ受け付ける。 有効なURLかどうかを判定してくれるisValidUrl()やウェブURL判定のisNetworkUrl()isHttpsUrl()あたりは使えそう。 なぜかこいつだけ名前がUtil。 http://developer.android.com/reference/android/webkit/URLUtil.html

PhoneNumberUtils

電話番号を扱うためのUtils。 Intentから電話番号を取得するgetNumberFromIntent()tel:sip:も対応してて便利。 表示用に日本向け(!)に整形してくれるformatJapaneseNumber()というのもあるらしい。 isDialable()とか便利そうだけどちゃんと動くのか未確認…。 http://developer.android.com/reference/android/telephony/PhoneNumberUtils.html

AnimationUtils

リソースからアニメーションの生成をしてくれるUtils。 loadInterpolator()くらいしか使ったことがない…。 http://developer.android.com/reference/android/view/animation/AnimationUtils.html

ThumbnailUtils

サムネイルの生成Utils。 なんと画像だけでなく動画からもサムネイルの生成をしてくれる。 ただし、動画の場合はサイズが2種類しか選べない。 画像からは指定サイズで作れるから二重に生成すれば良いのだが…。 http://developer.android.com/reference/android/media/ThumbnailUtils.html

TouchUtils

タッチイベントをシミュレートするためのUtils。 ActivityInstrumentationTestCase2と合わせてUIテストに使う。 http://developer.android.com/reference/android/test/TouchUtils.html

GLUtils

OpenGL扱うときに使うっぽいUtils。 使ったことがない…。 http://developer.android.com/reference/android/opengl/GLUtils.html

GestureUtils

ジェスチャー関連の解析とかをやるときに使うらしい。 使ったことがない…。 http://developer.android.com/reference/android/gesture/GestureUtils.html

DebugUtils

DebugUtils.isObjectSelected()メソッドしかない。 ログ出すときにオブジェクトの状態がANDROID_OBJECT_FILTERという環境変数の設定とマッチするかチェックしてくれる。 ANDROID_OBJECT_FILTER環境変数ってどうやってセットするんだ? http://developer.android.com/reference/android/util/DebugUtils.html

Androidに最適化されたJavaクラス一覧

はじめに

Androidではモバイル端末での処理に最適化されたいくつかの代替クラスが用意されています。 ほとんどがHashMap関係のメモリ消費を抑えるためのものですが、Android Developersにも代替クラスをまとめたページはないようなので、知っている範囲でまとめてみました。

SparseArray

似ている機能:HashMap<Integer,T> SparseArrayはAndroid向けにパフォーマンスが改良されたHashMap<Integer,T>の代替クラス。 Supportライブラリに最新のSparseArrayと同じ実装になったSparseArrayCompatがある。 http://developer.android.com/reference/android/support/v4/util/SparseArrayCompat.html

LongSparseArray

似ている機能:HashMap<Long,T> API level 16から追加された、keyがintからlongになったSparseArray。 Supportライブラリにもある。 http://developer.android.com/reference/android/support/v4/util/LongSparseArray.html

SparseBooleanArray

似ている機能:HashMap<Integer,Boolean> valueがboolean型のSparseArrayHashMap<Integer,Boolean>の置き換えができるが、value型がBooleanではなくbooleanなので注意。 http://developer.android.com/reference/android/util/SparseBooleanArray.html

SparseIntArray

似ている機能:HashMap<Integer,Integer> valueがint型のSparseArrayHashMap<Integer,Integer>の置き換えができるが、value型がIntegerではなくintなので注意。 http://developer.android.com/reference/android/util/SparseIntArray.html

SparseLongArray

似ている機能:HashMap<Integer,Long> API level 18から追加された、valueがlong型のSparseArrayHashMap<Integer,Long>の置き換えができるが、value型がLongではなくlongなので注意。 Supporライブラリには存在しない。 https://developer.android.com/reference/android/util/SparseLongArray.html

ArrayMap

似ている機能:HashMap<K,V> API level 19で追加された、Map<K,V>の新しい実装。 HashMapよりもメモリ効率が良い。 Supportライブラリにもある。 http://developer.android.com/reference/android/support/v4/util/ArrayMap.html

SimpleArrayMap

似ている機能:HashMap<K,V> Supportライブラリにしか存在しない。 ArrayMapからMapインターフェイスの実装を外したバージョン。 …というよりも、ArrayMapがこのクラスにMapの実装を追加している。 おそらくこちらのほうが軽い。 http://developer.android.com/reference/android/support/v4/util/SimpleArrayMap.html

FloatMath

似ている機能:Math(一部) float専用の数値演算処理クラス。 javaMathに比べて速いが、肝心のメソッドが少ない…。 http://developer.android.com/reference/android/util/FloatMath.html

Pair

似ている機能:AbstractMap.SimpleEntry<K,V> key,valueの2つの値を任意の型で保持することができるクラス。 AndroidSDK上ではPairのほうが先に実装されているが、AbstractMap.SimpleEntry<K,V>とほぼ同様。 http://developer.android.com/reference/android/util/Pair.html

xmlns:toolsでAndroid Studioのレイアウトエディタを活用する

xmlns:tools?

Androidのレイアウトファイルに以下のような記述が含まれていることがあります。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MyActivity"

このxmlns:toolstools:contextとはなんでしょうか。

答えは、Android Tools Projectに書いてありました。 http://tools.android.com/tech-docs/tools-attributes

英語よくわからん

という僕自身のために、内容を簡単にまとめました。

tools:ignore

lint用 tools:ignoreはリソースのすべてのxml要素に定義できる。 これを定義したxml要素とその子孫要素は、lintによるチェックで指定したissueが無視されるようになる。 複数のissueを無視したい場合、カンマ区切りで指定する。

<string name="show_all_apps" tools:ignore="MissingTranslation">All</string>

tools:targetApi

lint用 javaの@TargetApiと同じようなものでlintによるチェック時に適用される。 ApiLevelの指定はコードネームと整数両方いけるらしい。

<GridLayout tools:targetApi="ICE_CREAM_SANDWICH" >

tools:locale

lint/AndroidStudio用 values系リソースファイルのルート要素に定義できる。 これを指定したリソースの文字列は指定ロケール扱いになるらしい。 …デフォルトvaluesの文字列リソースが英語じゃない場合に使うと思うのだけど正直わからん。 結局日本語アプリではどうするべきなの?

<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="es">

tools:context

lint/AndroidStudio/Eclipse用 レイアウトxmlのルート要素で定義する。 レイアウトエディタでの表示に指定Activityのテーマが適用されるようになる。 Activityの指定はAndroidManifest同様packageからの相対パスで指定できるらしい。

<android.support.v7.widget.GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity"

tools:layout

AndroidStudio/Eclipse用 レイアウトxmlのfragment要素で定義する。 レイアウトエディタでのfragment要素の表示に指定したレイアウトが適用されるようになる。

<fragment android:name="com.example.master.ItemListFragment" tools:layout="@android:layout/list_content" />

tools:listitem / listheader / listfooter

AdapterView の子要素(ListViewなど)に定義できる。 それぞれ子要素のレイアウト、ヘッダのレイアウト、フッタのレイアウトを指定する。 レイアウトエディタでのAdapterViewの表示時に指定したレイアウトが適用されるようになる。

 <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:listitem="@android:layout/simple_list_item_2" />

tools:showIn

AndroidStudio(0.5.8以降)用。 他のレイアウトから<include>されるレイアウトのルート要素に定義できる。 AndroidStudioでレイアウトエディタ表示時に親レイアウトに埋め込まれた状態で表示されるらしい。 http://tools.android.com/recent/androidstudio058released

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:text="@string/hello_world"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:showIn="@layout/activity_main" />

tools:menu

AndroidStudio(0.8.0以降)用。 レイアウトのルート要素に定義できる。 AndroidStudioのレイアウトエディタではtools:contextActivityが指定されている場合、 Activity#onCreateOptionsMenuまでみてメニューアイテムを表示するらしい。 この要素が定義されているとそれを無視して指定したメニューアイテムを描画するようだ。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:menu="menu1,menu2" />

tools:actionBarNavMode

AndroidStudio(0.8.0以降)用。 レイアウトのルート要素に定義できる。 この要素が定義されている場合、レイアウトエディタにおいてActionBarを指定したモードで描画することができる。 "standard", "list", "tabs"のいずれかを指定する。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:actionBarNavMode="tabs" />

まとめ

toolsについて調べていたつもりがAndroidStudioのレイアウトエディタの進化に驚かされました。 レイアウトエディタからキャプチャも作れるので、tools属性を駆使すれば実機で確認ステップを少し減らせそうですね。 ぜひ活用していきたいです。

レイアウトの余白を埋める

余白を埋める

開発中、ViewとViewの間に余白を設けたい場合があります。 通常はmargindividerで調整しますが、間に余白のためのViewを置く場合もあると思います。 実はAndroidには、余白調整のためのSpaceというViewが存在しているのです。

Space

SpaceApi level 14で追加されたGridLayoutで発生する空のカラムを表現するために作られました。 Support Library v7にGridLayoutが収録された際、Spaceも同時に収録されました。

Spaceと他のViewとの大きな違いとして、描画を行わないという特徴があります。 以下のコードはSpace#drawメソッドの実装になります。

    /**
     * Draw nothing.
     *
     * @param canvas an unused parameter.
     */
    @Override
    public void draw(Canvas canvas) {
    }

Draw nothingの言葉通り、Spaceでは背景色を含む一切の描画が行われません。 余白のみ背景色を変えたいという場合には使えませんが、Viewの中で最も描画負荷が少ないというメリットがあります。

実装

Gradleの場合、以下のようにgridlayout-v7ライブラリを取り込みます。

compile 'com.android.support:gridlayout-v7:20.0.+'

例として、縦に並んだカニ画像の間に50dpの余白を設けてみます。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/darker_gray"
    android:orientation="vertical">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/kani" />

    <android.support.v7.widget.Space
        android:layout_width="match_parent"
        android:layout_height="50dp" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/kani" />

</LinearLayout>

layout-2014-08-21-195827_convert_20140821201849.png

こうなりました。 余白部分はLinearLayoutの背景が透過されています。

注意点

繰り返しになりますが、Spaceに背景色を設定しても無視されます。 以下のような記述はできますが、描画には反映されません。

    <android.support.v7.widget.Space
        android:layout_width="match_parent"
        android:background="@android:color/white"
        android:layout_height="50dp" />

使いどころ

正直、GridLayout以外で使える場面はあまりないと思います。 大抵はmargindividerで十分です。 しかし、どうしても余白のためにViewを配置したい場合Spaceの存在を思い出してください。