この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
先日のGoogle I/Oにて発表されたCameraXを試してみました。
本稿では、プレビュー表示までを行います。
Dependencies
// projectRoot/build.gradle
allprojects {
repositories {
google()
jcenter()
}
}
// app/build.gradle
dependencies {
def camerax_version = "1.0.0-alpha01"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
}
Implementation
パーミッションまわりは、PermissionsDispatcher にお任せしています。
いつもお世話になっております(感謝)
@RuntimePermissions
class CameraPreviewFragment : Fragment() {
private lateinit var finder: TextureView
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_camera_preview, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
finder = view.findViewById(R.id.preview)
// View描画後にカメラを開始
finder.post { startCameraWithPermissionCheck() }
}
override fun onDestroyView() {
super.onDestroyView()
CameraX.unbindAll()
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
onRequestPermissionsResult(requestCode, grantResults)
}
@NeedsPermission(Manifest.permission.CAMERA)
fun startCamera() {
CameraX.unbindAll()
val preview = AutoFitPreviewBuilder.build(PreviewConfig.Builder().build(), finder)
// 作成したUseCaseをバインド
CameraX.bindToLifecycle(this, preview)
}
@OnPermissionDenied(Manifest.permission.CAMERA)
fun close() {
findNavController().popBackStack()
}
}
Preview
CameraXでは、各機能をUseCaseで管理しています。
提供されているUseCaseは以下です。
プレビューの表示を行いたいので、Previewを利用します。
TextureView
TextureViewをカメラ解像度のアスペクト比に合わせる必要がありますが、大体同じような処理になってしまうので、今回は公式サンプルのUtilを活用します。
色々とやってくれていますが、目的の処理はこちらです。
一部改変しています。
private fun updateTransform(
textureView: TextureView?,
rotation: Int?,
newBufferDimens: Size,
newViewFinderDimens: Size
) {
// ~~
val matrix = Matrix()
val centerX = viewFinderDimens.width / 2f
val centerY = viewFinderDimens.height / 2f
matrix.postRotate(-viewFinderRotation!!.toFloat(), centerX, centerY)
val bufferRatio = bufferDimens.width / bufferDimens.height.toFloat()
if (viewFinderDimens.width > viewFinderDimens.height) {
val scaledHeight = Math.round(viewFinderDimens.width * bufferRatio)
val yScale = scaledHeight / viewFinderDimens.height.toFloat()
matrix.preScale(1f, yScale, centerX, centerY)
} else {
val scaledWidth = Math.round(viewFinderDimens.height / bufferRatio)
val xScale = scaledWidth / viewFinderDimens.width.toFloat()
matrix.preScale(xScale, 1f, centerX, centerY)
}
tv.setTransform(matrix)
}
Viewに合わせて、回転・拡縮を行います。
※回転は今までセンサー・画面向きを考慮していましたが、ライブラリ内部のCameraOrientationUtil
にて対応してくれています。
単純に回転している分、マイナスで戻すだけになっています。
おわりに
TextureViewの設定(Camera2でもやっていたこと)以外、特筆すべき点もなく簡単にプレビュー表示できました!
Camera2でプレビューを表示するまでを考えると、とても簡単になったと感じます。
今までのカメラ機能は、「お作法」的な部分に時間を取られていましたが
今後は要件・仕様に合わせてカスタマイズすることに集中できそうです。
AutoFitPreviewBuilder
はリファクタリングしたいと思います。