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 さんです!