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
  1. 1592     <style name="Theme.Holo.NoActionBar.TranslucentDecor">  
  2. 1593         <item name="android:windowTranslucentStatus">true</item>  
  3. 1594         <item name="android:windowTranslucentNavigation">true</item>  
  4. 1595         <item name="android:windowContentOverlay">@null</item>  
  5. 1596     </style>  
ステータスバーを透明にする属性が android:windowTranslucentStatus
ナビゲーションバーを透明にする属性が android:windowTranslucentNavigation
です。

試しに ActionBar と併用してみました。
  1. <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">  
  2.      <item name="android:windowTranslucentStatus">true</item>  
  3.      <item name="android:windowTranslucentNavigation">true</item>  
  4.      <item name="android:windowContentOverlay">@null</item>  
  5. </style>  
としたら、こうなりました。。。ひどいw


android:fitsSystemWindows="true" を指定すると、システムバー分のパディングがセットされます。 ただし、android:paddingXXX で指定したパディングが上書きされるので注意が必要。
  1. <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" ...="" android:fitssystemwindows="true">  
  2.   
  3.     ...  
  4.   
  5. </relativelayout>  
左右の 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() を呼べば、いい感じにアニメーションでレイアウトが切り替わります。
  1. findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {  
  2.   
  3.     @Override  
  4.     public void onClick(View v) {  
  5.         ViewGroup view = (ViewGroup) findViewById(android.R.id.content);  
  6.         Scene scene = Scene.getSceneForLayout(view, R.layout.scene2, MainActivity.this);  
  7.         TransitionManager.go(scene);  
  8.     }  
  9. });  
レイアウトを切り替える領域の ViewGroup を指定して TransitionManager.beginDelayedTransition() を呼ぶと、ViewGroup の子 View が変わったときに自動でいい感じにアニメーションしてくれます。 この方法だと Scene を作る必要はありません。

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



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



明日は @checkela さんです!

0 件のコメント:

コメントを投稿