Graphics, User Interface, User Input (Android 4.3 API)
お次はグラフィック関係。
Graphics
Support for OpenGL ES 3.0
Android4.3は、OpenGL ES 3.0をサポートする。OpenGL ES 3.0の新しい機能は以下。
- さらなる視覚効果の加速
- 標準機能としての高品質な ETC2/EAC texture圧縮
- integerと32bit小数をサポート
- 進化したテクスチャレンダリング
- テクスチャサイズとレンダリングバッファフォーマットの標準化
Androidでの OpenGE ES 3.0は、 GLES30として提供される。3.0を使用する場合は、manifestファイルの<uses-feature>でandroid:glEsVersion属性を定義する。
<manifest>
<uses-feature android:glEsVersion="0x00030000" />
...
</manifest>
OpenGL ES contextに setEGLContextClientVersion()で3を指定するのも忘れない事。
詳細は、OpenGL ES API guideを参照のこと。
Mipmapping for drawables
bitmapやdrawableをソースとするmipmapの使用は、多様なスケールでの高品質のイメージを提供するための簡単な方法。特にアニメーションにおいて効果が高い。
Android 4.2(API level 17)では、Bitmapによるmipmapのサポートが追加された。 (mipmap用のBitmapが用意され、setHasMipMap()でmipmapが有効になった時、AndroidはBitmapをmipmap用のイメージに変換していた)
4.3では、BitmapDrawableオブジェクトに関しても、リソースファイルの中でandroid:mipMap属性でアセットを指定するか、setHasMipMap()を呼ぶ事でmipmap用のソースとして利用できる。
User Interface
View overlays
新しいViewOverlayクラスは、レイアウト階層に影響を与えずに何かを描画するための、上層の 透過Viewを提供する。
getOverlay()を呼べばどんなViewのViewOverlayでも取得が可能で、元のViewと常に同じ大きさと位置となり、元のViewの手前に表示したいコンテンツを追加できる。なお、元のViewよ境界を拡張することはできない。
どんなViewでもというのは間違いで、今の所SurfaceViewとTextureViewはNGとAPI Documentには書いてありました…
ViewOverlayは、Viewをコンテナの外へスライドするアニメーションを作りたい時や、Viewの階層をかえることなくスクリーン上を動かしたい時に、特に有用である。 しかし、ViewOverlayの使用可能なエリアは、元になったViewと同じエリアに制限されており、アニメーションでレイアウトの外へ移動させたい時は、目的とするエリアを持つViewからViewOverlayを取得する必要がある。
ボタンのようなWidgetからViewOverlayを作る場合、add(Drawable)メソッドでDrawableオブジェクトを追加できる。RelativeLayoutのようなレイアウトViewでgetOverlay()を呼ぶと、ViewGroupOverlayが返って来る。ViewGroupOverlayは ViewOverlayのサブクラスで、add(VIew)メソッドでViewオブジェクトを追加できる。
- ViewOverlayに追加した全てのDrawableとViewオブジェクトは表示されるのみ、forcusやイベントを受け取ることはない。
以下は親Viewのoverlayの中でviewを右へスライドするアニメーションの例。
View view = findViewById(R.id.view_to_remove);
ViewGroup container = (ViewGroup) view.getParent();
container.getOverlay().add(view);
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
anim.start();
Optical bounds layout
9patch背景画像を持つViewの場合に、Viewのクリップ境界よりも視覚的な境界を基に配置しようとする機能。9patch画像は、ボタンやフォトフレームのような縁からパディングされたものが使われるため、見た目と実際のクリップ領域とが揃わないが、これを見た目で揃えられるようにする。
- 本家ページのサンプル画像では、開発者向けオプションの"レイアウト境界を表示"をonにしている。
optical boundで配置するなら、親のレイアウトのどこかのandroid:layoutMode属性を"opticalBounds"にする。
<LinearLayout android:layoutMode="opticalBounds" ... >
これを機能させるには、9patch画像を作る際に、optiocal boundを示すための赤のラインを下と右に設定する必要がある。赤のラインは、optical boundsを示し、クリップ境界から減算すべき場所を表す。
レイアウトの中でViewGroupのoptical boundsを有効にした場合は、明示的にlayoutModeを"clipBounds"に上書きしない限り、全ての子/孫ViewがopticalBoundsを継承する。
全てのレイアウト要素は、内包するviewのoptical boundsを基にしたものに自分の境界を適応させる。しかし、ViewGroupのサブクラスに関しては、今の所自身の背景画像でのoptical boundsの9patchをサポートしていない。
ViewやViewGroup,その他のサブクラスを継承するViewを生成した場合、そのクラスはoptical boundsの動作を継承する。
- HoloでサポートされているButton,Spinner,EditTextやその他の全てのウィジェットが、optical boundsを持つように更新されている。Holo系のテーマ使うなら、android:layoutModeを "opticalBounds"にすることですぐに恩恵を受けられる。
9-patchでoptical boundsを指定するには、9-patch toolで Controlキーを押したままクリックすればよい。
Animation for Rect values
新しいRectEvaluator で2つの矩形の間のアニメーションができる。この新しいクラスは、TypeEvaluatorの実装クラスでValueAnimator.setEvaluator()でセットできる。
Window attach and focus listener
ViewがWindowにattach/detachされた時や、フォーカスが変わった事を知りたい時、これまではViewのonAttachedToWindow()やonDetachedFromWindow(),onWindowsFocusChanged()をoverrideする必要があった。
これからは、それらのイベントを受け取るために、ViewTreeObserver.OnWindowAttachListener を実装し、addOnWindowAttachListener()でviewにセットすればよくなる。 同様に、フォーカスイベントも、ViewTreeObserver.OnWindowFocusChangeListenerを実装し、addOnWindowFocusChangeListener()でセットする。
TV overscan support
あなたのアプリが全てのテレビで画面全体を埋められるようにするために、レイアウトにoverscanを有効にできる。 OverscanモードはFLAG_LAYOUT_IN_OVERSCAN フラグで決められ、 Theme_DeviceDefault_NoActionBar_OverscanやカスタムテーマでwindowOverscanスタイルを有効にしたプラットホームで有効となる。
Screen orientation
manifestファイルの
userLandscape
"sensorLandscape"と同じ横向き(センサーによって天地が反転する)。ユーザーがauto-rotateを無効にしている場合、普通の横向きでロックされ反転しない。
userPortrait
"sensorPortrait"と同じ縦向き(センサーによって天地が反転する)。ユーザーがauto-rotateを無効にしている場合、普通の縦向きでロックされ反転しない。
fullUser
"fullSensor"と同じでセンサーによって4方向に回転する。ユーザーがauto-rotateを無効にしている場合、アプリもその固定された向きとなる。
locked
スクリーンの現在の向きでロックする。
Rotation animations
画面が回転(横<->縦など)する際に、どんなアニメーションを行うかをWindowManagerのrotationAnimationフィールドで設定できるようになった。
- ROTATION_ANIMATION_CROSSFADE
- ROTATION_ANIMATION_JUMPCUT
- ROTATION_ANIMATION_ROTATE
これらのアニメーションが有効になるのは、ActivityのテーマにTheme.Holo.NoActionBar.Fullscreenのようなフルスクリーンを指定した時だけとなる。
以下、crossfadeアニメーションの設定例
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowManager.LayoutParams params = getWindow().getAttributes();
params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
getWindow().setAttributes(params);
}
User Input
New sensor types
新しく追加された TYPE_GAME_ROTATION_VECTOR センサーは、磁気の影響を受けない回転を検出可能。
TYPE_ROTATION_VECTORセンサーと違って、TYPE_GAME_ROTATION_VECTORセンサーは磁北を基準としていない。
新しいTYPE_GYROSCOPE_UNCALIBRATEDとTYPE_MAGNETIC_FIELD_UNCALIBRATEDセンサーは、生のセンサーデータを提供する。
既存のTYPE_GYROSCOPEとTYPE_MAGNETIC_FIELDセンサーは、それぞれgyro-drift(数値の暴れ)と端末のhard-iron(磁化した金属や永久磁石等)によるバイアスを考慮している。
"uncalibrated"なこれらのセンサーは、生のデータと推定バイアス値を別で提供するため、外部データを使ってキャリブレーションを自前で行うことも可能となる。
いやぁ、とうとう来ましたか。 ずっとこれを待ってたんです。ちょっと自前のアプリを弄って試してみましたが、Nexus7ではどちらのSensorも有効だけど、GalaxyNexusではnullとなってだめみたい。データ量も単純に倍になって大変ですが、ジャイロと磁気センサーの生データとれないの?とか聞かれることも割とあるので、いつでも切り替えられるように準備だけはしておく必要がありそうです。
というわけで、あと1/4くらい。こうやって更新された部分をちゃんと追っかけておくとクライアントに説明しやすくていいですね。
んで、ぼちぼちiOS7の方もおっかけないといけないのですが、秋あたりからスマホ案件は別の人に振って、もっと儲かる案件へ転身な気配もあるので、その辺りの研究は出回ってから暇ならやろうかなと。
法と信念に反しない範囲で、機嫌良く儲かるコードを書くのが好きなだけなので、案件や環境や言語でさえどうでもいいんですが、老後はCOBOLでかかれたシステムのお守りができるような人になりたいなとか思いつつ、とりあえずいったんここで切ります。