Superdry Memorandom :-p

旧「superdry memorandum :-D」です

Android UIデザインのための10のTips

古い記事(2011年5月)ですが下記リンクからピンポイントなとこをまとめメモ。ユーザの操作とかは日本ではちっと違うなーてとこもありますが、おおむね役立つと思います。

1.起動画面の体験性

以下のポイントが2、3秒で理解できるようにしないとダメ。

  • ココはどこで
  • ココでは何ができて
  • ココからさらに進んだところで何ができるか

ユーザはアプリを理解するために時間を使いたがらない。マニュアルなんておいても見ずに何かのボタンを押してしまう。

上記のGowallaの画面では、パスポートがゆっくりと開いたあと、自分の個人情報に素早くアクセスでき、簡単なサジェスチョンとそれ以降のアクションと通知を表現している。

2.全ての入力には価値がある

  • 端末が本当はどのように使われているかを確認する。
  • ほとんどの場合、親指1本で操作している時間がほとんど*1
  • スクロール、フリップ、タップなどが大事で、マルチタッチやそれ以上の複雑な操作は捨てること。
  • 全ての入力タイミングで、変に指や腕をのばしたりなしに、素早く情報の遷移が行えるようにする。

上記の図では、ワンタップでタスクを追加できるようになっている。タスクには詳細な設定できるが、省略可能となっている。

3.コントラスト

開発環境では端末は直射日光のあたらない場所にあり、画面もきれいに見えるが、ユーザが使用する状況によってはそうでない場合がある。直射日光下だと、色は区別しにくく詳細はとらえにくくなり、いくつかの要素は反射が原因で消えてしまう。だからといって、白黒のみの味気ない画面にしろという訳ではない

  • 色情報を使う場合はシンプルなテキストラベルのようにする。
  • 詳細情報がある場合でも、その情報なしで動作できることが多いはず。アプリでそんなに重要でないものを削除。
  • 最も価値のある機能を明るく表示して、インタフェース階層を明確にする。

上記のSoundHoundの画面には表示されてる要素は多いが、主な機能は明らかにするため、上部に明るく、大胆に表示されている。

4.待たせない工夫

特にモバイルのせかいではだれも待つことを望んでいない。本当にやりたい事のために少しでも多くの自由時間を得るために、外出先で行えることは行いたいからである。なのでパフォーマンスの向上と関連する情報がすぐ受け取れるようにUIを微調整する。

  • ボタンにpressedとselectedの状態を追加する
  • スピナーで、あとどのくらい時間がかかるか進捗を表示する

Googleリーダーアプリは上部の小さなスピナーがあり、1〜2分待つことをユーザに認識させます。

5.Landscape対応を忘れない

ほとんどの人はPortrait(縦方向)でアプリを使用するが、物理キーがある端末を使用するユーザやタブレットユーザはLandscape(横方向)でのアプリの使用に慣れている。しかし縦方向でのレイアウトをそのまま横に広げて横方向のレイアウトとするのはよくない。

  • 文字入力の多いアプリでは、Landscapeでは親指が2本を使うことになり*2、かつタイピングが簡単になることを考えると、Landscapeが使いやすい。その場合はLandscpae対応は必須。
  • LandscapeではPortraitと全く異なるユーザエクスペリエンスもあり。

Youtubeアプリだと、LandscapeとPortraitで2つの異なるレイアウトを使用してるが、それぞれがその特性を生かしている。

6.アプリのエコシステム

ユーザが端末を使う時のアクションフローにどう自分のアプリを組み込むかを考える。ユーザーのアクション全体をアプリに組み込む必要はないので、アクションフローのどこにフックさせるかを考える。


Androidでは「共有」いう仕組みがあるため、多くのアプリは、「共有」でフックできるように対応している。

7.アプリがUniqueとなるように

Androidマーケットにおける膨大な数のアプリがあるため、まともなダウンロード数を獲得することは難しい。しかしもう参入余地がない訳ではない。

人々は、常に別のものを好む。テキストエディタ機能を備えたアプリたくさんあるが、単純なアプリを好む人もいればきれいなUIをもつアプリを好む人がいる。基本的な機能は内部に備わっているので、それをどう提供するかが大事。

Feedly は単に Google Reader を統合した別のニュースリーダーだが、雑誌のような見た目とすっきりしたデザインで他のニュースリーダーと差別化している。

8.ガイドラインにこだわる

GoogleAndroidアプリの設計と開発のガイドラインをたくさん提案している。このガイドラインに精通すること。人がスマートフォンの複雑さに慣れるには、思うよりも長く時間がかかる。そのため全てにおいてカスタマイズしたインタラクション要素を使うことは避けること。

タッチ、タイピング、スワイプ、振る、時々ハードキーを押す、入力エリアへの入力、ボックスを選択したり、モーダルダイアログ、長押しするとどうなるか、ということをユーザに認識させなければならない。全部認識させるのは大変。なのでガイドラインに従うとユーザの学習コストがすこし軽減される。なぜなら他のガイドラインに従っているアプリで既に学習しているから。

まずは主な機能を表明できるよう、ダッシュボードを使用する。そして最も一般的な機能へのアクセスを提供するActionBarを追加し、ユーザが迷子になったときに戻れるようにする。これらのメタファを劇的に改善できる場合以外はガイドラインに従っておくのがよい、アプリとシステム全体の一貫性につながる。

タイトルバーに頻繁に使われるアクションをおき、大きくてシンプルなアイコンをbodyにおいている。Catch Note は基本にこだわることですばらしいアプリとなっている。

9.ゲリラテスト

全てのユーザに使いやすいものなんてできない。しかしこれは言い訳にしてはいけない。

大企業だとUIに巨額の予算をつぎ込むことができるが、小さい開発者にも少ないコストで素早くゲリラテストができる。ステッカーや少しのお金と引き換えに端末にアプリのプロトタイプを入れてもらう。最初は同僚や友人、そこから知らない人へと拡大する。

ユーザテストは慎重に観察することが大事。何のためのアプリだけを話し、手助けは最小限とする。ユーザが立ち往生している部分を注目する。

10.アプリの公開

アプリ以外にマーケットでの公開で必要なものを下記に示す

  • アプリケーションの機能の説明
  • アプリの高解像度アイコン
  • Androidマーケットで表示される小さなプロモーション画像
  • Web版マーケットのみに表示される大きな宣伝用画像

これらを軽んじてはいけない。他のアプリとの差別化にもつながる。できるならちゃんとしたデザイナーに依頼すること。加えて、アプリにフィットするTwitterアカウントを取得し煽動したり宣伝するのも一つの手。


*1:日本ではちっと違う

*2:日本ではちっと違う

android developers blogのAndroid’s HTTP Clientsのまとめ

Android developers blogがまた更新されてました。androidでのhttpクライアントについてです。メモがてらざっとまとめます。ネットワークについては弱く用語にも疎いのでおかしな言い回しがあったら 各リンクで原文の方を確認してみてください。

端的に言うと、Ecrair/Froyoの場合はApache HTTP Clientが、Gingerbread以降はHttpURLConnectionがおすすめのようです。

AndroidのHTTPクライアントの使い分け


HttpURLConnection と Apache HTTP Clientの2種類あってこれをどう使い分けるか。

Apache HTTP Clientについて

DefaultHttpClientAndroidHttpClientwebブラウザに最適なHTTPクライアントで幅広いAPIがあり、実装もバグが少なく安定している。しかしAPI自体が大きすぎるので互換性を維持したまま改善するのはむずかしく、Android開発チームは積極的に取り組んでいない。

HttpURLConnectionについて

HttpURLConnectionはほとんどのアプリに適した軽量のHTTPクライアントであり、もともと質が低かったがAndroid開発チームも積極的に取り組んでおり、向上している。

Froyo以前ではHttpURLConnectionはいくつかのバグがあり、特にInputStreamでclose()を呼ぶとコネクションプールがおかしくなる現象があった。これにはコネクションプーリングを無効することで避けられる。

private void disableConnectionReuseIfNecessary() {
    // HTTP コネクションの再利用はfroyo以前だとバグがある
    if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
        System.setProperty("http.keepAlive", "false");
    }
}

Gingerbread以降から透過なレスポンス圧縮が追加された。HttpURLConnectionは送信されるリクエストに以下のヘッダーを付与し、対応するレスポンスを扱えるようになった。

Accept-Encoding: gzip

レスポンスの圧縮をサポートしているクライアントの場合はWebサーバを設定することで効果が出る。もしレスポンス圧縮が問題となった場合は、ココを参照して無効とすること。

HTTPの「Content-Length」ヘッダーが圧縮したサイズを返すので、 無圧縮のバッファサイズを得ようとgetContentLength() を使うことは間違い。代わりに、InputStream.read()が-1を返すまでレスポンスからバイトを読むことでサイズを得ることができる。

他にも、GingerbreadでHTTPSについて改良している。HttpsURLConnectionは、多数のHTTPSホストが1つのIPアドレスを共有することを可能にする Server Name Indication (SNI) で接続することを試みている。これにより、圧縮とセッションチケットを可能としている。もしコネクションが切れた場合、自動的に(圧縮とセッションチケットなしで)再試行される。互換性を維持しつつ最新のサーバに接続する場合、HttpsURLConnectionは効率がいい。

In Ice Cream Sandwichでは、レスポンスキャッシュが追加される予定。キャッシュ機構がある場合、HTTPリクエストは下記の3つの方法のうちいずれかで処理される。

  • フルキャッシュレスポンス:ローカル・ストレージから直接提供される。ネットワーク接続を確立する必要はないので、このレスポンスはすぐに利用可能。
  • 条件付きキャッシュレスポンス:ウェブサーバによって監視されて最新であるべき。クライアントが「Give me /foo.png if it changed since yesterday」といったリクエストを贈るとサーバはコンテンツの更新または「304 Not Modified」のどちらかで応答する。もしコンテンツが変わってなければダウンロードはされない。
  • アンキャッシュレスポンス:webから提供される。このレスポンスは後にキャッシュに格納される予定。

バイス上にキャッシュするHTTPレスポンス*1を使用したい場合はリフレクションを使う。下記サンプルコードは、Ice Cream Sandwich以前のリリースでは影響ないように、Ice Cream Sandwichでレスポンスキャッシュを有効にする。

private void enableHttpResponseCache() {
    try {
        long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
        File httpCacheDir = new File(getCacheDir(), "http");
        Class.forName("android.net.http.HttpResponseCache")
            .getMethod("install", File.class, long.class)
            .invoke(null, httpCacheDir, httpCacheSize);
    } catch (Exception httpResponseCacheNotAvailable) {
    }
}

HTTPレスポンスでキャッシュヘッダをセットするように、Webサーバも設定する必要がある。

結局どうなの?

  • Ecrair/Froyoの場合、バグが少ないのでApache HTTP Clientがおすすめ。
  • Gingerbread以降はHttpURLConnectionがおすすめ。APIがシンプルでサイズが小さいためAndroid向き。
  • 新しく作るならHttpURLConnectionがベスト。透過圧縮とレスポンスキャッシングが、ネットワークの使用量を減らし通信速度を改善し、バッテリーにも優しいため。

*1:原文ではHTTPSとなっているけど…

Android Developer BlogのPreparing for Handsetsのまとめ

Android Developer Blogに新しい記事がのってました。いつもは適当ながら最初から最後まで翻訳するんですが、今日は時間がないのでざっとピンポイントにしてみました。おかしなところは下記の参照元リンクより確認してください。

今回は「次バージョンであるIce Cream Sandwichがきたとき、タブレット専用アプリでも対応が必要だよ。いきなりリリースされてもビビらんように、ちゃんとタブレットだけで動作するようにし、また事前にスマートフォンに対応しやすいようにしときましょうね。」という話です。

タブレット専用アプリが、タブレットスマートフォンと両対応させるためのポイント


Honeycombがタブレット専用なので、アプリもタブレット専用に作ってるものが多い。けど、もうすぐIce Cream Sandwichもでるし、前方互換性も考えるとそのときの準備をしておいた方がいい。そのためには、以下の対応が必要。

  • small screenな端末にインストールさせない
  • 同じapkファイルでsmall screenもサポートする

まずアプリをタブレット専用に設定する


おそらく、supports-screensにandroid:xlargeScreens="true"を指定しているだけの場合も多いが、以下のようにちゃんと定義する。2つの方法がある。

  1. xlarge 以外のsmall、normal、largeを明示的にfalseにする
  2. 画面のwidthの最小サイズを600dpに定義する
<manifest ... >
    <supports-screens android:smallScreens="false"
                      android:normalScreens="false"
                      android:largeScreens="false"
                      android:xlargeScreens="true"
                      android:requiresSmallestWidthDp="600" />
    <application ... >
        ...
    </application>
</manifest>

1.はSDK version 3.1以前、2.は3.2以降で使用できる。

android:requiresSmallestWidthDpという属性は3.2以上しか使用できないため、3.1以下ではコンパイルエラーとなる。この属性を使うならminSdkVersionを指定する必要がある。

この例では600dpに設定してる。これは大体画面サイズが7インチ以上の場合で、9インチ以上にしたい場合は720dpを指定する。詳細はAndroid Developers Blog: New Tools For Managing Screen Sizesを参照のこと。

Honeycombアプリをスマートフォンでも動くようにする


multiple APK*1より、アプリのマルチデバイス対応の方を推奨している。以下に2つのガイダンスを示す。

  • スマートフォン向けにシングルペイン/タブレット向けにマルチペインなど、異なった組み合わせで再利用できるようにFragmentまわりを設計する
  • 画面サイズに沿うように Action Barのデザインを控えめなものとする
シングルペインとマルチペインの両対応レイアウトの作り方

2つのアプローチがあって

どちらにするかはアプリの作りに応じて選ぶべき。

前者は、動的にfragmentをaddしたりremoveしたりするので、fragmentの変更に応じてActionBarを更新しないといけない。挙動を管理しきれるのなら、特にレイアウトファイルを分けるよりもいい場合もある。

後者は、要はFragmentの使い分けを定義した各端末向けのレイアウトファイルを使って、Fragmentの実装コードのモジュール化、ActionBarの簡素化し、stack処理をシステムにまかすことができる。将来的にいい方法だけど、複数のFragmentが分割されたActivityを縦断してアクセスされるので、状況に応じて選択した方がいい。

後者についてはさらに以下のようなレイアウトをもつアプリの場合を例に考えてみる。Activity AがメインとなるActivityで、スマートフォンにはFragment Aのみ、タブレットにはFragment A とFragment Bの両方のレイアウトをもつとする。

スマートフォン用の場合、main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment class="com.example.android.TitlesFragment"
              android:id="@+id/list_frag"
              android:layout_width="match_parent"
              android:layout_height="match_parent"/>
</FrameLayout>

タブレットの場合、

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/frags">
  <fragment class="com.example.android.TitlesFragment"
            android:id="@+id/list_frag"
            android:layout_width="@dimen/titles_size"
            android:layout_height="match_parent"/>
  <fragment class="com.example.android.DetailsFragment"
            android:id="@+id/details_frag"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
</LinearLayout>

実装としては、レイアウトに Fragment Bがあるかどうかで処理を分け、ある場合はActivity AからActivity Bへの更新通知を実装し、ない場合は、Activity AからActivity Bを起動するよう実装する。このときポイントは2つ。

  • 片方のFragmentからもう片方のFragmentを操作しない
  • コンテンツ関係のコードはFragmentの中ではなく、Activityの中に実装する

前者については、コールバックインタフェースを各Fragmentクラスの中に定義すると、ホストとなるActivityへイベントを通知できる。Activityがコールバックを受け取る時に、現在のFragmentの設定に基づいて適切に処理される。

今回の例の場合、以下のような実装となる。

/** Fragment A でアイテム選択時のコールバック */
public void onItemSelected(int position) {
  // DisplayFragment (Fragment B) がレイアウトに存在するかどうかのフラグ
  DisplayFragment fragB = (DisplayFragment) getFragmentManager().findFragmentById(R.id.display_frag);
  if (fragB == null) {
      // レイアウトにない場合、DisplayActivity (Activity B) を起動する。
      Intent intent = new Intent(this, DisplayActivity.class);
      intent.putExtra("position", position);
      startActivity(intent);
  } else {
      // レイアウトにある場合、更新する。
      fragB.updateContent(position);
  }
}

このあたりの完全なデモコードとして、Honeycomb Gallery サンプル (ZIP ファイル)があるのでみておくこと。


スマートフォンでも対応するようなAction Barを作っておく

コツは3つ。

  • Action Itemを設定するとき「always」の使用は避ける。「isRoom」を使う。
  • できるならアイコンも用意しておき、showAsAction="ifRoom|withText"と定義する。
  • カスタムナビゲーションモードの使用は避ける。ビルドインされたタブ&ドロップダウンのものを使う。もし使用したい場合はICSのリリース後、テストをする必要がある。

上記に従っておけば、スマートフォン画面では以下の図のように対応される。スマートフォンでは2つのAction ItemがAction Barに配置され、残りはMenuに配置される。


その他の考慮点
  • ListViewを使用してる場合、画面サイズが変わることで表示する情報量に影響があるので、あらかじめ考慮したレイアウトを準備しておく必要がある
  • リソースファイル(特に integers、dimensions、booleansなどの値)をスマートフォンにあったものを用意しておく
テストについて

ICSがリリースされるまでは実際のテストできません。とはいえ、模擬的な切替テストは手間がかかるができる。それはlargeのかわりにlandを使う(例えば、res/layout-large/main.xmlのかわりにres/layout-land/main.xmlを使う)。最終的にlargeに戻しておく必要はあるが、Honeycombエミュレーターなどで切り替えテストは可能。

*1:SDKレベルによってAPKファイルを分けること

Androidがphoneかtabletかをチェックするには

SDKバージョンをみてHoneycombかどうか、画面サイズを見てタブレットかどうかでチェックをする。よく忘れてぐぐるのでここにメモ。

public static boolean isHoneycomb() {
    // Can use static final constants like HONEYCOMB, declared in later versions
    // of the OS since they are inlined at compile time. This is guaranteed behavior.
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
}

public static boolean isTablet(Context context) {
    return (context.getResources().getConfiguration().screenLayout
            & Configuration.SCREENLAYOUT_SIZE_MASK)
            >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}

public static boolean isHoneycombTablet(Context context) {
    return isHoneycomb() && isTablet(context);
}

Xperia端末では地磁気センサ自体はとれるものの値は0しか返ってこないよ

今までXperia端末もってなかったので初めて知りました…。とりあえずrayとacroとminiとX10で試したけど全滅だった…。同じAK8975というセンサを使ってるSamsung Galaxy S2がちゃんと取得してるんだからセンサの問題じゃないはず。せっかくセンサーは乗ってるんだから、ソニエリさん対応してください(涙)。

俺得なAnimationのInterporatorビューワ

ビルドインされたAnimationのInterporatorをぱっと知りたくて、単に見るだけのサンプルアプリをつくりました。せっかくなので野良アプリとして公開します。ソースはGitHubにあります。apkはこちら