作成日

8 March 2011

パート 1 では、AIR のステージを自動回転する場合の使用例を紹介しました。自動回転の機能は、向きの変更を AIR に任せることができるため、開発やテストの手間を省けます。しかし、自動回転を使わずに、スクリプトから表示の向きを制御したい場合もあるかもしれませ ん。そこで、この記事では、加速度計を使ってデバイスの向きを判別する方法と、ステージを回転させる代わりにデバイス内の表示を回転させる方法を紹介しま す。

必要な環境

  • Adobe Flash Professional CS5 Extension for AIR 2.5
    Adobe Labs からダウンロードしてインストール

  • Android デバイス
    Android 2.2 以降がインストールされているもの

StageOrientationEvent

最初に、StageOrientationEvent について少し説明します。

Stage オブジェクトは、ステージの向きが変化するタイミングで StageOrientationEvent を送出します。キーボードをスライドして引き出せるタイプのデバイスでは、キーボードを開くと StageOrientationEvent が送出されるものもあります。setAspectRatio() メソッドでステージの向きを変更したときにも、このイベントは発生します。

StageOrientationEvent には 2 種類あります。

  • ORIENTATION_CHANGING : ステージが新しい向きに変わる前に発行される
  • ORIENTATION_CHANGE : ステージが新しい向きに変わった後に発行される

前者は、ステージの向きが変わる前に通知されるイベント、後者は、ステージの向きが変わった後に通知されるイベントです。Android では ORIENTATION_CHANGING がサポートされません。向きの変更が通知されるのはステージ回転の処理が完了した後のみ、ということになります。そのため、多くの場合、StageOrientationEvent だけに頼って表示をコントロールするのは "遅すぎ" ます。

さて、StageOrientationEvent には 2 つの属性があります。

  • beforeOrientation : 変更前のステージの向き
  • afterOrientation : 変更後のステージの向き

取り得る値は、どちらも StageOrientation クラスの

  • DEFAULT
  • ROTATED_LEFT
  • ROTATED_RIGHT
  • UNKNOWN

のいずれかです。現バージョンの Android では UPSIDE_DOWN は通知されません。

これらの値はステージの向きを指していることに注意してください。デバイスの向きではありません。また、ステージの向きはデバイスに対する相対的な向きであって、ユーザーから見た方向ではありません。例えば、デバイスが左を向いていて afterOrientation が ROTATED_RIGHT であれば、ユーザーからは正常に表示されている (ステージが物理的に上を向いている) ことになります。

前述のように、ORIENTATION_CHANGE はステージの回転処理が終了した後に発行されるため、確実に回転の完了を待って行いたい処理を記述するのには役立ちます。 ORIENTATION_CHANGE イベントを使用するときの基本的なコードは以下のようなものです。

// イベントハンドラーを追加 stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGE, onOrientationChange); function onOrientationChange(event:StageOrientationEvent):void { switch (event.afterOrientation) { case StageOrientation.DEFAULT: // ステージが上向きになったときの処理を記述 break; case StageOrientation.ROTATED_RIGHT: // ステージが右向きになったときの処理を記述 break; case StageOrientation.ROTATED_LEFT: // ステージが左向きになったときの処理を記述 break; case StageOrientation.UPSIDE_DOWN: // ステージが下向きになったときの処理を記述 break; } }

加速度計を使った向きの検知

ステージを自動回転させている場合は、resize イベントのタイミングで表示を調整できます。ステージの幅と高さが分かればレイアウトには十分、という場合は、デバイスの向きすら気にする必要はありません。

一方、自動回転機能を利用しない場合は、デバイスの向きが変わっても、ステージの状態は変わりません。つまり、 待っていても向きの変化を通知するイベントは発生しません。従って、加速度計を使用して、デバイスの向きの変化の検知から始める必要があります。

加速度計の値は Accelerometer クラスを使って取得します。Accelerometer クラスは、加速度センサーにより検知されたデバイスの傾きや動きの情報を AccelerometerEvent.UPDATE イベントとして通知します。AccelerometerEvent には、以下の 4 つの属性が定義されています。

  • accelerationX -- x 軸方向の加速度、単位はG
  • accelerationY -- y 軸方向の加速度、単位はG
  • accelerationZ -- z 軸方向の加速度、単位はG
  • timestamp -- 実行環境が初期化されてからの時間、単位はミリ秒

下は、AccelerometerEvent から加速度の値を取得する簡単な例です。

// インスタンスの生成 _accelerometer = new Accelerometer(); // イベントハンドラーを追加 _accelerometer.addEventListener(AccelerometerEvent.UPDATE, onUpdate); private function onUpdate(event:AccelerometerEvent):void { // イベントオブジェクトから3軸それぞれの方向の加速度を取得できる trace("acceleration X: " + evt.accelerationX.toString() + "\n" + "acceleration Y: " + evt.accelerationY.toString() + "\n" + "acceleration Z: " + evt.accelerationZ.toString() ); }

AccelerometerEvent より得られる 3 方向の加速度からは、デバイスの傾きを判断できます。例えば、デバイスを縦方向に持ったときと横方向に持ったときそれぞれの値は以下のようになります。

  • 上側を上にして垂直に持った → (accelerationX: 0.0, accelerationY: 1.0, accelerationZ: 0.0)
  • 右側を上にして垂直に持った → (accelerationX: 1.0, accelerationY: 0.0, accelerationZ: 0.0)

これより、accelerationX と accelerationY の値を比較して、accelerationX の方が大きければ縦向きに近い、accelerationY の方が大きければ横向きに近い、という判断ができることが分かります。

この条件を利用して、向きが変わったら ORIENTATION_CHANGE イベントを送出するユーティリティクラスを作ることができます。下はその例です。

public class StageOrientationObserver extends EventDispatcher { private var _accelerometer:Accelerometer; private var _lastOrientation:String; public function StageOrientationObserver() { // コンストラクタでAccelerometerのインスタンスにイベントハンドラを追加 _accelerometer = new Accelerometer(); _accelerometer.setRequestedUpdateInterval(1500); _accelerometer.addEventListener(AccelerometerEvent.UPDATE, onAccelerometer); } private function onAccelerometer(event:AccelerometerEvent):void { var newOrientation:String; if (Math.abs(event.accelerationX) < Math.abs(event.accelerationY)) { // 縦向きに近い状態 if (event.accelerationY > 0) { // デバイスの上部が上を向いている newOrientation = StageOrientation.DEFAULT; } else { // デバイスの上部が下を向いている newOrientation = StageOrientation.UPSIDE_DOWN; } } else { // 横向きに近い状態 if (event.accelerationX > 0) { // デバイスの上部が左を向いている newOrientation = StageOrientation.ROTATED_LEFT; } else { // デバイスの上部が右を向いている newOrientation = StageOrientation.ROTATED_RIGHT; } } if (_lastOrientation != newOrientation) { // デバイスの向きが変わったためORIENTATION_CHANGEイベントを送出 dispatchEvent(new StageOrientationEvent( StageOrientationEvent.ORIENTATION_CHANGE, false, false, _lastOrientation, newOrientation)); // 新しい向きを保存 _lastOrientation = newOrientation; } } }

自動回転機能を使用しない場合、デバイスの向きとステージの向きはおんなじです。そのため、加速度計から得られた方向をそのまま ORIENTATION_CHANGE として通知しています。

Stage オブジェクトの代わりに、上のクラスのインスタンスにイベントハンドラーを追加すると、自動回転の場合と同様に ORIENTATION_CHANGE イベントを利用できるようになります。ただし、実際にステージが回転している訳ではないため、イベントハンドラー内で、表示オブジェクトの位置と大きさ、 更に角度の調整を行う必要があります。下はそのサンプルです。

// インスタンスの生成 soo = new StageOrientationObserver(); // イベントハンドラーを追加 soo.addEventListener(StageOrientationEvent.ORIENTATION_CHANGE, onOrientationChange); private function onOrientationChange(event:StageOrientationEvent):void { // デバイスの向きに応じて表示オブジェクトの位置と角度を変更する _currentOrientation = event.afterOrientation; switch (_currentOrientation) { case StageOrientation.DEFAULT: // デバイスの上部が上を向いている this.rotation = 0; this.x = 0; this.y = 0; break; case StageOrientation.ROTATED_RIGHT: // デバイスの上部が右を向いている this.rotation = -90; this.x = 0; this.y = _stageHeight; break; case StageOrientation.ROTATED_LEFT: // デバイスの上部が左を向いている this.rotation = 90; this.x = _stageWidth; this.y = 0; break; case StageOrientation.UPSIDE_DOWN: // デバイスの上部が下を向いている this.rotation = 180; this.x = _stageWidth; this.y = _stageHeight; break; } // 残りの処理は resize イベントハンドラーに任せる onResize(event); }

このやり方だと、Android でも UPSIDE_DOWN つまり上下逆の状態を扱えるという利点があります。ただし、文字を使用している場合は、表示される可能性のある文字全てを埋め込まないと、標準以外の向き では表示されません。やはり、一般的には自動回転を利用する方がお薦めのようです。

最後に

この記事では、デバイスの向きに応じて表示を回転させる方法をいくつか紹介しました。画面の小さなデバイスでは状況に合わせて表示を調整することで使い勝手が向上します。

これから開発を始めてみよう、という方は、以下の記事もご覧下さい。

Flash Professional CS5でAIR for Androidをはじめよう

Flexで作るAndroidアプリ開発チュートリアル 1

Flexで作るAndroidアプリ開発チュートリアル 2