Android アプリは、縦向きで保持するスマートフォンだけでなく、さまざまなフォーム ファクタで実行されます。 デスクトップ ウィンドウ機能、接続されたディスプレイ、折りたたみ式デバイスの導入に伴い、カメラアプリは動的なウィンドウ サイズ、さまざまなアスペクト比、外部ハードウェアに対応する必要があります。
スマートフォンのロジックが機能しない理由
カメラアプリは、マルチフォーム ファクタ環境で重大な障害を引き起こす可能性のある想定に基づいて動作することがよくあります。
画面の向き
- 想定: デバイスの自然な画面の向き
ROTATION_0は常に 縦向きである - 現実: タブレット、一部の折りたたみ式デバイスのインナー ディスプレイ、デスクトップ モニターでは、
ROTATION_0は横向きであることが多い - 結果: プレビューが 90 度回転する
センサーのアライメント
- 想定: カメラセンサーの長辺が画面の長辺と揃っている
- 現実: サイズ変更可能なウィンドウは正方形または横向きにできますが、センサーは固定されたままです(通常は 4:3)
- 結果: 画像が引き伸ばされたり、歪んだりする
画面密度とサイズ
- 想定: 画面の密度とサイズは実行時に変化しない
- 現実: デスクトップ環境では、ユーザーが自由にウィンドウのサイズを変更する
- 結果: ドラッグ イベントごとにカメラセッションを再起動すると、ユーザー エクスペリエンスが中断され、クラッシュが発生する可能性がある
解決策 1: システム インテントを使用する
アプリで写真や動画を撮影する必要があるものの、専用の カスタム カメラ インターフェースが必要ない場合は、デバイスにプリインストールされているシステム カメラを 起動するのが、さまざまなフォーム ファクタに対応する最善の方法です(カメラ インテントを参照)。
システム インテントを使用すると、キャプチャ エクスペリエンス全体がデバイスの相手先ブランド供給(OEM)メーカーが開発したカメラアプリに委任されます。これにより、フォーム ファクタのサポートの複雑さ(以下を含む)が効果的に外部委託されます。
- 組み込みのリサイズと回転のサポート \- 折りたたみ式デバイスやタブレットのデフォルトのカメラアプリは、その特定のデバイスの形状に対応するようにメーカーが明示的に構築しています。このアプリは、デバイスが広げられたとき、回転されたとき、マルチウィンドウ モードになったときに適切に動作するように設計されています。
- 高度なハードウェア機能へのアクセス \- OEM カメラアプリは、手動で再現することが難しい、または不可能なハードウェア チューニング アルゴリズム(夜間モード、HDR、特定のレンズ切り替え)に排他的にアクセスできます。
解決策 2: Jetpack CameraX を使用する
CameraX は、カメラアプリの開発を 容易にするために構築された Jetpack ライブラリです。CameraX はライフサイクルを認識し、サーフェス指向です。デバイスの折りたたみ、回転、サイズ変更のたびにセンサーの向きとサーフェスのサイズを手動で再計算する必要がある Camera2 とは異なり、CameraX はマルチウィンドウのリサイズ時やアプリが接続されたディスプレイに移動したときにカメラセッションの再構成を自動的に処理し、プレビューストリームが途切れたり引き伸ばされたりすることなく適応するようにします。
PreviewView などのコンポーネントは、折りたたみ式デバイスがカバー画面からインナー ディスプレイに移行するなど、さまざまな状態でのアスペクト比とスケールタイプをインテリジェントに管理します。これにより、デバイス固有のエッジケースの複雑なコレクションではなく、単一の一貫した実装で幅広いハードウェアをサポートできます。
作成
Jetpack Compose では、専用の androidx.camera:camera-compose
ライブラリを使用します。このライブラリには、CameraXViewfinder コンポーザブルが用意されており、Compose ライフサイクル内のサイズ変更、回転、アスペクト比の複雑なジオメトリを処理するように特別に設計されています。
CameraXViewfinder コンポーネントは、カメラアプリで最も一般的なエラーの原因を排除します。
- 座標の自動変換 \- カメラアプリの構築で最も難しいことの 1 つは、ユーザーのタップ(画面上の x、y 座標)をカメラセンサーの座標系(0 ~ 1、0 ~ 1 回転)にマッピングして、フォーカスと測光を行うことです。
CameraXViewfinderには、CoordinateTransformerが ウィンドウのサイズ変更や デバイスの折りたたみ時でも、数学的な処理を自動的に行うように用意されています。 - 正しいレイアウト動作 \-
SurfaceViewやTextureViewとは異なり、CameraXViewfinderは Compose の Z オーダーで正しく動作します。アーティファクトをレンダリングせずに、UI 要素(フォーカス リング、コントロール)を重ねたり、修飾子(角の丸め、アニメーション)を適用したりできます。 - リサイズとアスペクト比:
CameraXViewfinderは、内部で 中央クロップと中央フィットのロジックを処理し、アプリ ウィンドウのサイズが標準外のアスペクト比( 分割画面モードやデスクトップ ウィンドウ機能モードなど)に変更されたときにプレビューが 引き伸ばされないようにします。
View
ビューベースのアプリでは、PreviewView または ViewFinderView を使用します。
SurfaceView または TextureView を直接使用する場合は、アスペクト比を計算し、
正しい 変換行列 を自分で適用する必要があります。
解決策 3: 画面の向きとサイズ変更を動的に処理する
プラットフォーム API を直接使用する場合は、デバイスの回転、アクティビティ の再起動、アスペクト比に注意してください。
デバイスの回転の使用を停止する
UI レイアウトを決定する際に、Display#getRotation() や物理センサーの向きだけに依存しないでください
。
- ウィンドウ指標を使用する \- アプリ ウィンドウの幅と高さを比較し、レイアウト(横向きと縦向きの
UI)を決定します。
WindowManager#getCurrentWindowMetrics() - 自然な向きを無視する \- アプリは、横向きのモニターで縦向きのウィンドウに表示されることがあります。デバイスの画面の向きは UI の境界に関係ありません。
アクティビティの再起動を回避する
デフォルトの Android の動作では、構成 の変更(ウィンドウのリサイズなど)時にアプリのアクティビティが破棄されます。カメラアプリの場合、これはディスプレイのちらつきや、ビデオ通話中の接続の切断として現れます。
- マニフェスト構成 \- 再起動せずにリサイズを処理するには、マニフェストで 構成の変更を宣言します。
- 動的な更新 \-
onConfigurationChanged()で、新しいウィンドウ サイズに合わせてカメラ プレビューのレイアウト パラメータを更新します。
アスペクト比と切り抜き
折りたたみ式デバイスとデスクトップ ウィンドウでよくある問題は、プレビューの引き伸ばしです。これは、 4:3 のカメラフィードが 16:9 または 1:1 のウィンドウに強制的に表示されることです。
- 引き伸ばさない \- プレビューとウィンドウのアスペクト比が異なる場合は、カメラ バッファをビューの境界に正確に合わせないでください。
- 中央クロップ(推奨): プレビューをウィンドウの短い方の辺に合わせて拡大し、余分な部分を切り抜きます。これにより、被写体が歪むことなくフレームに収まります。
- 中央フィット(代替): 完全な画角を表示することが重要な場合(ドキュメントのスキャンなど)は、ウィンドウ内にプレビューをレターボックス表示します。
ボーナス: 折りたたみ式デバイス優先のエクスペリエンスのサポート
折りたたみ式デバイスは、単に曲がるスマートフォンではありません。ユーザーが写真や動画を撮影する方法を根本的に改善できる独自のハードウェア状態も提供します。折りたたみ式デバイスでは、折りたたみを解決すべき問題として扱うのではなく、折りたたみ式でないデバイスでは不可能な機能を構築するために使用します。
テーブルトップ モード(ハンズフリー キャプチャ)
テーブルトップ モードでは、デバイスを半分に折りたたんで表面に置き、 長時間のビデオ通話、タイムラプス撮影、長時間露光の夜間 撮影を行うことができます。
背面ディスプレイ モード(高画質の自撮り)
- 折りたたみ式デバイスでは、背面カメラは通常、ユーザー側のカメラよりも高画質です。背面ディスプレイ モードでは、デバイスを広げて裏返し、小さなカバー画面をメインの背面カメラのライブ ビューファインダーとして使用できます。
- 背面ディスプレイ モードでは、追加の機材を持ち運ぶことなく、50 メガピクセル以上の自撮り、超広角のグループ写真、高画質の VLOG を撮影できます。
デュアル スクリーン モード(被写体のプレビュー)
- デュアル スクリーン モードでは、インナー ディスプレイとアウター ディスプレイの両方にカメラ プレビューを同時に表示できます。これは人物の撮影に最適です。撮影者はインナー ディスプレイで構図を決めながら、被写体はアウター ディスプレイで自分の姿を確認してポーズを調整できます。
- 背面ディスプレイ モード(アプリ全体を移動する)とは異なり、デュアル スクリーン モードでは、カバー画面にセカンダリ プレゼンテーション ウィンドウが作成されます。