You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合相机选项实现Android新版Photo Picker?

实现新版Android Photo Picker与相机拍照的组合选择方案

因为新版Photo Picker基于Activity Result API实现,没有对应的Intent实例,确实无法直接沿用原有Intent.createChooser的组合方式。要保持类似原选择器的交互体验,推荐以下两种方案:

方案1:自定义统一选择器(推荐)

自己实现一个底部弹出式选择器,模拟系统Chooser的交互逻辑,同时集成新版Photo Picker和相机拍照功能,既能保持体验一致性,还能自定义样式。

步骤1:创建选择器布局

新建layout_bottom_photo_selector.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp"
    android:background="@android:color/white">

    <Button
        android:id="@+id/btn_pick_from_gallery"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="从相册选择"
        android:textSize="16sp"/>

    <Button
        android:id="@+id/btn_take_photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="拍照"
        android:textSize="16sp"
        android:layout_marginTop="8dp"/>

</LinearLayout>

步骤2:实现Activity Result逻辑

在你的Activity/Fragment中注册两个Launcher,分别对应Photo Picker和相机拍照:

import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.content.ContentValues
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.bottomsheet.BottomSheetDialog

class MainActivity : AppCompatActivity() {
    // 新版Photo Picker启动器
    private val pickPhotoLauncher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri: Uri? ->
        uri?.let { handleSelectedImage(it) }
    }

    // 相机拍照启动器
    private val takePhotoLauncher = registerForActivityResult(ActivityResultContracts.TakePicture()) { success: Boolean ->
        if (success) {
            photoUri?.let { handleTakenImage(it) }
        }
    }

    private var photoUri: Uri? = null

    // 弹出自定义选择器
    private fun showPhotoSourceSelector() {
        val bottomSheet = BottomSheetDialog(this)
        val selectorView = layoutInflater.inflate(R.layout.layout_bottom_photo_selector, null)
        bottomSheet.setContentView(selectorView)

        selectorView.btn_pick_from_gallery.setOnClickListener {
            bottomSheet.dismiss()
            // 启动新版Photo Picker,仅选择图片
            pickPhotoLauncher.launch(
                ActivityResultContracts.PickVisualMediaRequest(
                    ActivityResultContracts.PickVisualMedia.ImageOnly
                )
            )
        }

        selectorView.btn_take_photo.setOnClickListener {
            bottomSheet.dismiss()
            // 创建拍照输出的Uri(适配Android 10+分区存储)
            photoUri = createImageOutputUri()
            photoUri?.let { takePhotoLauncher.launch(it) }
        }

        bottomSheet.show()
    }

    // 创建拍照文件的Uri
    private fun createImageOutputUri(): Uri {
        val contentValues = ContentValues().apply {
            put(MediaStore.Images.Media.DISPLAY_NAME, "IMG_${System.currentTimeMillis()}.jpg")
            put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/YourAppName")
            }
        }
        return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)!!
    }

    // 处理选中的图片
    private fun handleSelectedImage(uri: Uri) {
        // 替换为你的业务逻辑:显示图片、上传等
    }

    // 处理拍摄的图片
    private fun handleTakenImage(uri: Uri) {
        // 替换为你的业务逻辑:显示图片、上传等
    }
}

方案2:版本分支兼容

如果需要兼容旧版系统,可做版本判断:

  • 当系统不支持新版Photo Picker(Android < 13,或未预装Photo Picker的设备),继续使用你原有Intent组合的方式;
  • 当系统支持新版Photo Picker时,使用方案1的自定义选择器,保证体验一致。

关键判断逻辑

private fun isPhotoPickerAvailable(): Boolean {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ||
            (Build.VERSION.SDK_INT == Build.VERSION_CODES.S &&
             packageManager.hasSystemFeature("android.software.photopicker"))
}

内容的提问来源于stack exchange,提问作者shagberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:13:20