アプリにプレビューを追加する場合は、PreviewView
を使用します。これは適切な表示に合わせて切り抜き、サイズ変更、回転ができる View
です。
画像プレビューは、カメラがアクティブになったときに PreviewView
内のサーフェスにストリーミングされます。
PreviewView を使用する
PreviewView
を使用して CameraX のプレビューを実装するには、以下の手順(後のセクションで説明)を行います。
- 必要に応じて
CameraXConfig.Provider
を設定します。 - レイアウトに
PreviewView
を追加します。 ProcessCameraProvider
をリクエストします。View
を作成するときは、ProcessCameraProvider
を確認します。- カメラを選択してライフサイクルとユースケースをバインドします。
PreviewView
の使用には、いくつかの制限事項があります。PreviewView
を使用する場合、次のいずれの操作も実行できません。
SurfaceTexture
を作成し、TextureView
とPreview.SurfaceProvider
に設定する。TextureView
からSurfaceTexture
を取得し、Preview.SurfaceProvider
に設定する。SurfaceView
からSurface
を取得し、Preview.SurfaceProvider
に設定する。
これらのうちいずれかの操作が行われた場合、Preview
は PreviewView
へのフレームのストリーミングを停止します。
PreviewView をレイアウトに追加する
次のサンプルは、レイアウト内の PreviewView
を示しています。
<FrameLayout android:id="@+id/container"> <androidx.camera.view.PreviewView android:id="@+id/previewView" /> </FrameLayout>
CameraProvider をリクエストする
次のコードは、CameraProvider
をリクエストする方法を示しています。
Kotlin
import androidx.camera.lifecycle.ProcessCameraProvider import com.google.common.util.concurrent.ListenableFuture class MainActivity : AppCompatActivity() { private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider> override fun onCreate(savedInstanceState: Bundle?) { cameraProviderFuture = ProcessCameraProvider.getInstance(this) } }
Java
import androidx.camera.lifecycle.ProcessCameraProvider import com.google.common.util.concurrent.ListenableFuture public class MainActivity extends AppCompatActivity { private ListenableFuture<ProcessCameraProvider> cameraProviderFuture; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { cameraProviderFuture = ProcessCameraProvider.getInstance(this); } }
CameraProvider が利用可能かどうかを確認する
CameraProvider
をリクエストした後、ビューの作成時に初期化が成功したことを確認します。次のコードに、その方法を示します。
Kotlin
cameraProviderFuture.addListener(Runnable { val cameraProvider = cameraProviderFuture.get() bindPreview(cameraProvider) }, ContextCompat.getMainExecutor(this))
Java
cameraProviderFuture.addListener(() -> { try { ProcessCameraProvider cameraProvider = cameraProviderFuture.get(); bindPreview(cameraProvider); } catch (ExecutionException | InterruptedException e) { // No errors need to be handled for this Future. // This should never be reached. } }, ContextCompat.getMainExecutor(this));
たとえば、このサンプルで使用されている bindPreview
関数については、次のセクションに示されているコードをご覧ください。
カメラを選択してライフサイクルとユースケースをバインドする
CameraProvider
を作成して確認したら、次のようにします。
Preview
を作成します。- 希望のカメラの
LensFacing
オプションを指定します。 - 選択したカメラとユースケースをライフサイクルにバインドします。
Preview
をPreviewView
に接続します。
次のコードに、例を示します。
Kotlin
fun bindPreview(cameraProvider : ProcessCameraProvider) { var preview : Preview = Preview.Builder() .build() var cameraSelector : CameraSelector = CameraSelector.Builder() .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build() preview.setSurfaceProvider(previewView.getSurfaceProvider()) var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview) }
Java
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) { Preview preview = new Preview.Builder() .build(); CameraSelector cameraSelector = new CameraSelector.Builder() .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build(); preview.setSurfaceProvider(previewView.getSurfaceProvider()); Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview); }
bindToLifecycle()
は Camera
オブジェクトを返します。ズームや露出など、カメラ出力の制御について詳しくは、カメラ出力をご覧ください。
これでカメラ プレビューの実装は完了です。アプリをビルドし、プレビューがアプリに表示され、意図したとおりに動作することを確認します。
PreviewView の追加コントロール
CameraX PreviewView
には、次のようなプロパティを設定するための追加 API が用意されています。
実装モード
PreviewView
は、以下のいずれかのモードを使用して、プレビュー ストリームをターゲット View
にレンダリングできます。
PERFORMANCE
モード(デフォルト モード):PreviewView
はSurfaceView
を使用して動画ストリームを表示しますが、特定のケースではTextureView
にフォールバックします。SurfaceView
には専用の描画サーフェスがあり、特にプレビュー動画上に他の UI 要素(ボタンなど)がない場合、内部ハードウェア コンポジターによりハードウェア オーバーレイで実装される可能性が高くなります。ハードウェア オーバーレイでレンダリングすると、動画フレームが GPU パスを回避するので、プラットフォームの電力消費とレイテンシを削減できます。COMPATIBLE
モード:PreviewView
はTextureView
を使用しますが、SurfaceView
とは異なり、専用の描画サーフェスはありません。その結果、動画を表示するにはブレンディングでレンダリングされます。このステップでは、動画を制限なしで拡大縮小したり回転させたりするなど、アプリケーションで追加の処理を実行できます。
PreviewView.setImplementationMode()
を使用して、アプリケーションに適した実装モードを選択します。デフォルトの PERFORMANCE
モードがアプリケーションに適していない場合のために、次のコードサンプルで COMPATIBLE
モードの設定方法を示します。
Kotlin
// viewFinder is a PreviewView instance viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
スケールタイプ
プレビュー動画の解像度がターゲット PreviewView
のサイズと異なる場合は、動画コンテンツを切り抜くかレターボックス表示にするかして、ビューに合わせる必要があります(アスペクト比は変えないでください)。PreviewView
には、この目的のために次の ScaleTypes
が用意されています。
FIT_CENTER
、FIT_START
、FIT_END
(レターボックス表示用): 動画コンテンツ全体が、ターゲットPreviewView
で表示できる最大サイズに拡大縮小されます。ただし、動画フレーム全体が表示されても、画面の一部が空白になることがあります。選択した 3 つのスケールタイプに応じて、ターゲット ビューの中央、始点、または終点に合わせて動画フレームが配置されます。FILL_CENTER
、FILL_START
、FILL_END
(切り抜き用): 動画がPreviewView
のアスペクト比と一致しない場合、コンテンツは一部しか表示されませんが、動画はPreviewView
全体に表示されます。
CameraX が使用するデフォルトのスケールタイプは FILL_CENTER
です。PreviewView.setScaleType()
を使用して、アプリケーションに最適なスケールタイプを設定してください。次のコードサンプルでは、FIT_CENTER
スケールタイプを設定しています。
Kotlin
// viewFinder is a PreviewView instance viewFinder.scaleType = PreviewView.ScaleType.FIT_CENTER
動画の表示は、以下のステップから処理されます。
- 動画を拡大縮小します。
FIT_*
スケールタイプの場合、min(dst.width/src.width, dst.height/src.height)
で動画を拡大縮小します。FILL_*
スケールタイプの場合、max(dst.width/src.width, dst.height/src.height)
で動画を拡大縮小します。
- 拡大縮小された動画を表示先
PreviewView
に合わせます。FIT_CENTER/FILL_CENTER
の場合、拡大縮小された動画と表示先PreviewView
を、それぞれの中央を合わせて配置します。FIT_START/FILL_START
の場合、拡大縮小された動画と表示先PreviewView
を、それぞれの左上端を合わせて配置します。FIT_END/FILL_END
の場合、拡大縮小された動画と表示先PreviewView
を、それぞれの右下端を合わせて配置します。
たとえば、元になる動画が 640x480 で、表示先の PreviewView
が 1920x1080 だとします。
次の図は、FIT_START
/ FIT_CENTER
/ FIT_END
の拡大縮小処理を示しています。
この処理は次のように行われます。
- 動画フレームを(アスペクト比を変えずに)
min(1920/640, 1080/480) = 2.25
倍に拡大して、1440x1080 の中間動画フレームを生成します。 - 1440x1080 の動画フレームを 1920x1080 の
PreviewView
に合わせます。FIT_CENTER
の場合、動画フレームをPreviewView
ウィンドウの中央に合わせます。PreviewView
の始点側と終点側の 240 ピクセルの列は空白です。FIT_START
の場合、動画フレームをPreviewView
ウィンドウの始点(左上端)に合わせます。PreviewView
の終点側の 480 ピクセルの列は空白です。FIT_END
の場合、動画フレームをPreviewView
ウィンドウの終点(右下端)に合わせます。PreviewView
の始点側の 480 ピクセルの列は空白です。
次の図は、FILL_START
/ FILL_CENTER
/ FILL_END
の拡大縮小処理を示しています。
この処理は次のように行われます。
- 動画フレームを
max(1920/640, 1080/480) = 3
倍に拡大して、1920x1440 の中間動画フレーム(PreviewView
より大きい)を生成します。 - 1920x1440 の動画フレームを 1920x1080 の
PreviewView
ウィンドウに合うよう切り抜きます。FILL_CENTER
の場合、拡大済みの 1920x1440 の動画の中央から 1920x1080 を切り抜きます。動画の上下 180 行は表示されません。FILL_START
の場合、拡大済みの 1920x1440 の動画の始点から 1920x1080 を切り抜きます。動画の下側の 360 行は表示されません。FILL_END
の場合、拡大済みの 1920x1440 の動画の終点から 1920x1080 を切り抜きます。動画の上側 360 行は表示されません。
参考情報
CameraX について詳しくは、以下の参考情報をご確認ください。
Codelab
コードサンプル