# camerax-sample **Repository Path**: mengjingbo/camerax-sample ## Basic Information - **Project Name**: camerax-sample - **Description**: Android相机拍照 - **Primary Language**: Kotlin - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 1 - **Created**: 2020-11-27 - **Last Updated**: 2025-03-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # camerax-sample ## 前言 在Camera,Camera2之后Google的Jetpack项目新增了CameraX库,利用该库,可以更轻松地向应用添加相机功能。并且CameraX适用于大多数 Android 设备,并可向后兼容至 Android 5.0(API 级别 21)。相对Camera,Camera2而言,CameraX只要简单的几行代码就可以实现拍照。 --- ## 效果图 ![输入图片说明](https://images.gitee.com/uploads/images/2020/1203/125343_ec8e4141_2018073.jpeg "20201130173407175.jpg") ## Gradle依赖 ```kotlin dependencies { // ... // CameraX implementation 'androidx.camera:camera-core:1.0.0-beta12' implementation 'androidx.camera:camera-camera2:1.0.0-beta12' implementation 'androidx.camera:camera-lifecycle:1.0.0-beta12' implementation 'androidx.camera:camera-view:1.0.0-alpha19' } ``` ## 布局 ```xml ``` 属性说明: |属性|说明| |:----|:---| |captureMode|拍摄模式,image:启用图像捕获的模式,video:启用视频捕获的模式。mixed:同时启用图像捕获和视频捕获的模式| |flash|闪光灯,auto:自动,on:开启,off:关闭| |lensFacing|设备镜头,none:默认值,默认使用后置镜头,back:后置镜头,front:前置镜头| |scaleType|捕获比例类型| |pinchToZoomEnabled|是否支持手势缩放| ScaleType枚举值: |缩放类型|说明| |:----|:----| |fillStart|缩放预览,并保持捕获的数据源长宽比,使其充满整个预览视图,并将其与视图的开始对齐。| |fillCenter|缩放预览,并保持捕获的数据源长宽比,使其充满整个预览视图,并在视图中居中。| |fillEnd|缩放预览,并保持捕获的数据源长宽比,使其充满整个预览视图,然后将其与视图的末端对齐。| |fitStart|缩放预览,并保持捕获的数据源长宽比,使其完全包含在中预览视图中,并将其与视图的开始对齐。| |fitEnd|缩放预览,并保持捕获的数据源长宽比,使其完全包含在预览视图中,并将其与视图的末端对齐。| CameraView属性源码: ```xml ``` ## 镜头切换 ```kotlin private fun switchLensFacing() { binding.cameraView.toggleCamera() val isFacingBack = binding.cameraView.cameraLensFacing == CameraSelector.LENS_FACING_FRONT binding.cameraSwitch.animate().rotationY(if (isFacingBack) 180f else 0f).start() } ``` ## 拍照 在Android不同版本中拍照存储地址都有所变更,这里对图片输出地址做了一个适配,让捕获到的图片都存储在SDCard下面的Picture文件夹中。 ```kotlin /** * 使用ContentValues存储图片输出信息 */ fun getContentValues(): ContentValues { // 创建拍照后输出的图片文件名 val fileName = "$PHOTO_PREFIX${SimpleDateFormat(FILENAME, Locale.getDefault()).format(System.currentTimeMillis())}$PHOTO_EXTENSION" return ContentValues().apply { put(MediaStore.MediaColumns.MIME_TYPE, MIME_TYPE) // 适配Android Q版本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) put(MediaStore.MediaColumns.DISPLAY_NAME, fileName) } else { val fileDir = File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES).also { if (!it.exists()) it.mkdir() } val filePath = fileDir.absolutePath + File.separator + fileName put(MediaStore.Images.Media.DATA, filePath) } } } ``` 具体拍照动作 ```kotlin private fun takePicture() { val fileOptions = ImageCapture.OutputFileOptions.Builder(requireContext().contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, CameraCompat.getContentValues()).build() binding.cameraView.takePicture(fileOptions, executorService, object : ImageCapture.OnImageSavedCallback { override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { requireActivity().runOnUiThread { takePictureUri = outputFileResults.savedUri binding.preview.setImageURI(outputFileResults.savedUri) Toast.makeText(requireContext(), "Take Picture Uri:${outputFileResults.savedUri}", Toast.LENGTH_SHORT).show() } } override fun onError(exception: ImageCaptureException) { requireActivity().runOnUiThread { Toast.makeText(requireContext(), "Take Picture Error:${exception.message}", Toast.LENGTH_SHORT).show() } } }) } ```