2013年11月14日木曜日

KitKat (Android 4.4) の UI について

Android 4.4 KitKat 冬コミ原稿リレーの 11/14 分です。

Android 4.4 KitKat の API の内、User Interface に関わる部分を取り上げます。


■ Immersive full-screen mode

昔々、2.x まではフルスクリーンモードというものがありました。このときはホームキーやバックキーがハードキー(ハードボタン)だったため、ステータスバーが隠れ、画面全体がアプリの領域になるというものでした。

3.x になると、画面下部がナビゲーションバーというものになり、ステータスバーの情報はナビゲーションバーの右側に、ホームキーやバックキーは左側に移動しました。 このナビゲーションバーは、これまでのフルスクリーンモードを指定しても表示されたままでした。

4.0 ICS (API Level 14) になると、スマホにもナビゲーションバーが導入されました。
ハードキーよ、さようなら。
ナビゲーションバーを暗くしたり、インタラクションがない間(動画を見てるなど)非表示にすることができるようになりました。
  • SYSTEM_UI_FLAG_VISIBLE (0x00000000)
  • SYSTEM_UI_FLAG_LOW_PROFILE (0x00000001)
    ナビゲーションバーを暗くする(オーバーフローメニューを表示するとなぜかクリアされる。Action Item のクリックではクリアされない)
  • SYSTEM_UI_FLAG_HIDE_NAVIGATION (0x00000002)
    インタラクションがない間ナビゲーションバーを非表示にする (ちなみに、SYSTEM_UI_FLAG_LOW_PROFILE と SYSTEM_UI_FLAG_HIDE_NAVIGATION を両方指定すると、ナビゲーションバーは非表示になり、インタラクションがあって表示された瞬間は暗くなっていて、すぐに明るくなる)

4.1 Jelly Bean (API Level 16) では、ナビゲーションバーやステータスバー(これらを合わせてシステムバーとドキュメントでは書かれている)の見た目を制御するためのフラグがいくつか追加されました。
  • SYSTEM_UI_FLAG_FULLSCREEN (0x00000004)
    ステータスバーを非表示にする
    SYSTEM_UI_FLAG_LOW_PROFILE や SYSTEM_UI_FLAG_HIDE_NAVIGATION と組み合わせて指定すると、ナビゲーションバーが表示されるタイミングでステータスバーも表示される
    単体で指定した場合はインタラクションがあっても非表示のまま
  • SYSTEM_UI_FLAG_LAYOUT_STABLE (0x00000100)
  • SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION (0x00000200)
    ナビゲーションバーが非表示であるかのようにビューをレイアウトする
  • SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN (0x00000400)
    ステータスバーが非表示であるかのようにビューをレイアウトする
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN だけを指定した状態


4.4 KitKat (API Level 19) では、インタラクションがあってもシステムバーを非表示のままにできるようになりました。
  • SYSTEM_UI_FLAG_IMMERSIVE (0x00000800)
  • SYSTEM_UI_FLAG_IMMERSIVE_STICKY (0x00001000)
* immersive は没入とか没頭という意味です。

SYSTEM_UI_FLAG_HIDE_NAVIGATION フラグや SYSTEM_UI_FLAG_FULLSCREEN フラグと組み合わせて setSystemUiVisibility() に指定します。
これらを指定すると、ステータスバー(SYSTEM_UI_FLAG_FULLSCREEN)やナビゲーションバー(SYSTEM_UI_FLAG_HIDE_NAVIGATION)が非表示になり、画面全体をアプリの領域にできます。
システムバーを表示するには、「システムバーが表示されるべき領域から内側に向かってフリック」します。
ユーザーがこの操作を行うと、SYSTEM_UI_FLAG_HIDE_NAVIGATION フラグと SYSTEM_UI_FLAG_FULLSCREEN フラグがクリアされるので、全画面表示ではなくなります。
SYSTEM_UI_FLAG_IMMERSIVE を指定した場合は、そのまま全画面表示が解除されたままになり、SYSTEM_UI_FLAG_IMMERSIVE_STICKY を指定すると数秒後に再び全画面表示に戻ります。

なぜか、オーバーフローメニューを表示すると immersive mode がクリアされてしまいます。。。


SYSTEM_UI_FLAG_IMMERSIVE | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION

わーい。全画面だー。

SYSTEM_UI_FLAG_IMMERSIVE_STICKY | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION で「システムバーが表示されるべき領域から内側に向かってフリック」したとき

View の上に半透明で表示されます

初めて全画面表示したときは、こんなポップアップが自動で出ました。




■ Translucent system bars

システムバーを透明にすることができるようになりました。

システムバーが透明のテーマが用意されています。
  • Theme.Holo.NoActionBar.TranslucentDecor
  • Theme.Holo.Light.NoActionBar.TranslucentDecor
ActionBar とは併用できないんですかね。。。

Theme.Holo.NoActionBar.TranslucentDecor

黒わからん。。。w

Theme.Holo.Light.NoActionBar.TranslucentDecor
1592 ステータスバーを透明にする属性が android:windowTranslucentStatus
ナビゲーションバーを透明にする属性が android:windowTranslucentNavigation
です。

試しに ActionBar と併用してみました。 としたら、こうなりました。。。ひどいw


android:fitsSystemWindows="true" を指定すると、システムバー分のパディングがセットされます。 ただし、android:paddingXXX で指定したパディングが上書きされるので注意が必要。 ... 左右の padding もなくなってしまった。。。



■ Enhanced notification listener

API Level 18 で追加された NotificationListenerService が拡張されました。

Notification に新しく extras というフィールドが増えて、この Bundle 用のキーがいろいろ追加されました。 また、新しく actions というフィールドも増えました。このフィールドは Notification.Action の配列で、Notification.Builder の addAction() で格納されます。



■ Scenes and transitions

新しく android.transtion フレームワークが提供されるようになりました。

ユーザーインタフェースの異なる状態間のアニメーションを促進するためのものだそうです。 Scene.getSceneForLayout() を使って Scene を作ります。 レイアウトを切り替える領域の ViewGroup を第1引数に、切り替えるレイアウトを第2引数に、第3引数には Context を指定します。 あとは、TransitionManager.go() を呼べば、いい感じにアニメーションでレイアウトが切り替わります。 findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ViewGroup view = (ViewGroup) findViewById(android.R.id.content); Scene scene = Scene.getSceneForLayout(view, R.layout.scene2, MainActivity.this); TransitionManager.go(scene); } }); レイアウトを切り替える領域の ViewGroup を指定して TransitionManager.beginDelayedTransition() を呼ぶと、ViewGroup の子 View が変わったときに自動でいい感じにアニメーションしてくれます。 この方法だと Scene を作る必要はありません。

# やってみたけど、アニメーションしてくれない。。。 final ViewGroup view = (ViewGroup) findViewById(android.R.id.content); TransitionManager.beginDelayedTransition(view); findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { View inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.scene2, view, false); view.addView(inflate); } }); 特定のアニメーションを指定するには、Transition を継承したクラスのインスタンスを指定します。 指定されていないときは AutoTransition が利用されます。 Fade や ChangeBounds、Visibility などいくつかのクラスがあらかじめ用意されています。 Scene scene = Scene.getSceneForLayout(view, R.layout.scene2, MainActivity.this); TransitionManager.go(scene, new ChangeBounds()); res/transition/ に定義した XML ファイルに対して TransitionInflater.inflateTransition() を使うことでも Transition のインスタンスを作成することができます。 XML については TransitionManager のドキュメントの説明を読むのがいいです。



# 今のところ、これだ!という使い道がわかってません。。。w



明日は @checkela さんです!

0 件のコメント:

コメントを投稿