嵌入式照片选择器

动画:显示连续照片选择器选择过程

嵌入式照片选择器是一种不同的照片选择体验,可直接在应用的用户界面中进行互动。与经典的照片选择器相比,它提供了增强的集成和自定义选项。由于它是在 SurfaceView 上使用 setChildSurfacePackage 方法呈现的,因此与非嵌入式版本一样,它也具有相同的安全和隐私权功能。

借助嵌入式照片选择器,用户可以持续从设备和云端照片库中选择照片和视频,而不会在客户端应用中失去焦点。客户端应用保持活动状态,其 activity 处于已恢复状态,并且可以实时响应用户选择。

嵌入式照片选择器可提供更顺畅的界面集成,但由于它在特殊的 SurfaceView 上呈现,因此可保持与标准照片选择器相同的安全和隐私保护功能。

适用的设备

搭载 Android 14(API 级别 34)且 SDK 扩展版本为 15 或更高版本的设备支持嵌入式照片选择器。

不符合这些功能的设备可以依赖于使用 Google Play 服务的传统照片选择器或向后移植的版本

Jetpack 库依赖项

将 Jetpack 照片选择器库作为依赖项包含在内:

// For apps using Jetpack Compose
implementation("androidx.photopicker:photopicker-compose:1.0.0-alpha01")

// For apps using Views
implementation("androidx.photopicker:photopicker:1.0.0-alpha01")

您可以使用 Jetpack Compose(推荐)或 View 集成嵌入式照片选择器。

Jetpack Compose 集成

EmbeddedPhotoPicker 可组合函数提供了一种机制,可用于将嵌入式照片选择器界面直接包含在 Jetpack Compose 屏幕中。此可组合函数会创建一个 SurfaceView,用于托管嵌入式照片选择器界面。它管理与 EmbeddedPhotoPicker 服务的连接,处理用户互动,并使用少量参数将所选媒体 URI 传达给调用应用:

val coroutineScope = rememberCoroutineScope()
val pickerState = rememberEmbeddedPhotoPickerState()

EmbeddedPhotoPicker(
    state = pickerState,
    onUriPermissionGranted = { uris ->
        _attachments.value += uris
    },
    onUriPermissionRevoked = { uris ->
        _attachments.value -= uris
    },
    onSelectionComplete = {
        // Hide the embedded photo picker as the user is done with the
        // photo/video selection
    },
)

持续选择

动画:显示连续照片选择器选择过程

借助嵌入式照片选择器,用户可以持续选择和取消选择照片库中的项目,而无需关闭选择器。在应用界面中选择和取消选择的项目会与照片选择器同步,从而提供顺畅的用户体验。

使用 pickerState 中的 deselectUrideselectUris 方法取消选择 Uri,以通知嵌入式选择器用户已从应用的界面中取消选择某个项。您需要手动更新自己的应用界面状态,因为调用这些方法不会通过 onUriPermissionRevoked 回调通知您的应用任何新撤消的 URI。

coroutineScope.launch {
    // Signal unselected media to the picker
    pickerState.deselectUris(uris)
    // Remove them from the list of selected media to be reflected in the app's UI
    _attachments.value -= uris
}

个性化照片选择器

嵌入式照片选择器提供个性化选项,让您可以根据应用的设计和用户体验调整其外观和行为,以便更好地集成。

强调色

默认情况下,嵌入式照片选择器依赖于系统提供的动态颜色,用户可以在设备主题选项中跨应用设置这些颜色。强调色将用于照片选择器中的各种主要元素。所有其他颜色将根据 Android Material 指南进行设置。如需自定义选择器的强调色,请定义 EmbeddedPhotoPickerFeatureInfo 选项:

val info = EmbeddedPhotoPickerFeatureInfo.Builder().setAccentColor(0xFF0000).build()

EmbeddedPhotoPicker(
    embeddedPhotoPickerFeatureInfo = info,
    ...
)
未设置强调色 带有强调色(峰值) 带有强调色(展开)
未设置强调色的照片选择器屏幕截图 照片选择器屏幕截图,其中显示了强调色(峰值) 照片选择器屏幕截图,其中显示了强调色(展开)

强调色必须完全不透明。系统会忽略 Alpha(透明度)值。只允许使用亮度值介于 0.05 和 0.9 之间的颜色。

尺寸

默认情况下,嵌入式选择器的大小不受限制,但您可以指定一个修饰符来限制它:

EmbeddedPhotoPicker(
    modifier = Modifier.height(500.dp),
    ...
)
无限制(扩展) 高度上限为 500 dp(展开)
照片选择器屏幕截图 照片选择器屏幕截图

视图集成

如需使用视图添加嵌入式照片选择器,请向布局文件添加一个条目:

<view class="androidx.photopicker.EmbeddedPhotoPickerView"
    android:id="@+id/photopicker"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

然后,在 activity 的 onCreate 方法中初始化照片选择器,方法如下:

  1. 从布局中获取对 EmbeddedPhotoPickerView 的引用
  2. 添加 EmbeddedPhotoPickerStateChangeListener 以处理选择事件
  3. 使用 EmbeddedPhotoPickerFeatureInfo 配置照片选择器,包括任何自定义设置(例如强调色)
// Keep track of the selected media
private val _attachments = MutableStateFlow(emptyList<Uri>())
val attachments = _attachments.asStateFlow()

private lateinit var picker: EmbeddedPhotoPickerView
private var openSession: EmbeddedPhotoPickerSession? = null

val pickerListener = object : EmbeddedPhotoPickerStateChangeListener {
    override fun onSessionOpened(newSession: EmbeddedPhotoPickerSession) {
        // Keep reference to the session to notify the embedded picker of user
        // interactions on the calling app
        openSession = newSession
    }

    override fun onSessionError(throwable: Throwable) {}

    override fun onUriPermissionGranted(uris: List<Uri>) {
        // Add newly selected media to our tracked list
        _attachments += uris
    }

    override fun onUriPermissionRevoked(uris: List<Uri>) {
        // Remove newly unselected media from our tracked list
        _attachments -= uris
    }

    override fun onSelectionComplete() {
        // Hide the embedded photo picker as the user is done with the
        // photo/video selection
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.main_view)
    picker = findViewById(R.id.photopicker)

    // Attach the embedded picker event listener to update the app's UI
    picker.addEmbeddedPhotoPickerStateChangeListener(pickerListener)

    // Customize embedded picker's features: accent color, max selectable items,
    // pre-selected URIs, filter out mime types
    picker.setEmbeddedPhotoPickerFeatureInfo(
        // Set a custom accent color
        EmbeddedPhotoPickerFeatureInfo.Builder().setAccentColor(0xFF0000).build()
    )
}

您可以使用 EmbeddedPhotoPickerSession 的不同方法与嵌入式选择器互动:

// Notify the embedded picker of a configuration change
openSession.notifyConfigurationChanged(newConfig)

// Update the embedded picker to expand following a user interaction
openSession.notifyPhotoPickerExpanded(/* expanded: */ true)

// Resize the embedded picker
openSession.notifyResized(/* width: */ 512, /* height: */ 256)

// Show/hide the embedded picker (after a form has been submitted)
openSession.notifyVisibilityChanged(/* visible: */ false)

// Remove unselected media from the embedded picker after they have been
// unselected from the host app's UI
openSession.requestRevokeUriPermission(removedUris)