嵌入式照片选择器:一种在应用中私下请求照片和视频的更顺畅方式
做好准备,通过一种令人兴奋的新方式来使用 Android 照片选择器,从而提升应用的用户体验!借助新的嵌入式照片选择器,用户可以直接在应用界面中顺畅地选择照片和视频,同时注重隐私保护。现在,您的应用可以获得照片选择器提供的所有相同优势,包括直接集成到应用体验中的云内容访问权限。
为什么要嵌入?
我们知道,许多应用都希望在用户选择照片或视频时提供高度集成且顺畅的体验。嵌入式照片选择器正是为此而设计的,让用户无需离开应用即可快速访问最近的照片。他们还可以在自己偏好的云媒体提供商(例如 Google 相册)中浏览完整的媒体库,包括收藏夹、相册和搜索功能。这样一来,用户就不必在应用之间切换,也不必担心想要的照片是存储在本地还是云端。
无缝集成,增强隐私保护
借助嵌入式照片选择器,您的应用无需访问用户的照片或视频,除非用户实际选择了某些内容。这意味着为用户提供更好的隐私保护和更顺畅的体验。此外,嵌入式照片选择器可让用户访问其整个基于云的媒体库,而标准照片权限仅限于本地文件。
Google 信息中的嵌入式照片选择器
Google 信息展示了嵌入式照片选择器的强大功能。下面介绍了 Google 信息如何集成该选择器:
- 直观的位置: 照片选择器位于相机按钮的正下方,让用户可以清楚地选择是拍摄新照片还是选择现有照片。
- 动态预览: 用户点按照片后,系统会立即显示大尺寸预览,方便用户确认选择。如果用户取消选择照片,预览就会消失,从而保持体验简洁明了。
- 展开即可查看更多内容: 初始视图经过简化,方便用户轻松访问最近的照片。不过,用户可以轻松展开照片选择器,浏览并选择媒体库中的所有照片和视频,包括 Google 相册中的云内容。
- 尊重用户选择: 嵌入式照片选择器仅授予对用户选择的特定照片或视频的访问权限,这意味着用户可以完全停止请求照片和视频权限。这样一来,Google 信息就不必处理用户仅授予对照片和视频的有限访问权限的情况。
实现
借助 Photo Picker Jetpack 库,您可以轻松集成嵌入式照片选择器。
Jetpack Compose
首先,将 Jetpack Photo Picker 库作为依赖项添加。
implementation("androidx.photopicker:photopicker-compose:1.0.0-alpha01")
EmbeddedPhotoPicker 可组合函数提供了一种机制,可将嵌入式照片选择器界面直接包含在 Compose 屏幕中。此可组合项会创建一个 SurfaceView,用于托管嵌入式照片选择器界面。它会管理与 EmbeddedPhotoPicker 服务的连接,处理用户互动,并将所选媒体 URI 传达给调用应用。
@Composable
fun EmbeddedPhotoPickerDemo() {
// We keep track of the list of selected attachments
var attachments by remember { mutableStateOf(emptyList<Uri>()) }
val coroutineScope = rememberCoroutineScope()
// We hide the bottom sheet by default but we show it when the user clicks on the button
val scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberStandardBottomSheetState(
initialValue = SheetValue.Hidden,
skipHiddenState = false
)
)
// Customize the embedded photo picker
val photoPickerInfo = EmbeddedPhotoPickerFeatureInfo
.Builder()
// Set limit the selection to 5 items
.setMaxSelectionLimit(5)
// Order the items selection (each item will have an index visible in the photo picker)
.setOrderedSelection(true)
// Set the accent color (red in this case, otherwise it follows the device's accent color)
.setAccentColor(0xFF0000)
.build()
// The embedded photo picker state will be stored in this variable
val photoPickerState = rememberEmbeddedPhotoPickerState(
onSelectionComplete = {
coroutineScope.launch {
// Hide the bottom sheet once the user has clicked on the done button inside the picker
scaffoldState.bottomSheetState.hide()
}
},
onUriPermissionGranted = {
// We update our list of attachments with the new Uris granted
attachments += it
},
onUriPermissionRevoked = {
// We update our list of attachments with the Uris revoked
attachments -= it
}
)
SideEffect {
val isExpanded = scaffoldState.bottomSheetState.targetValue == SheetValue.Expanded
// We show/hide the embedded photo picker to match the bottom sheet state
photoPickerState.setCurrentExpanded(isExpanded)
}
BottomSheetScaffold(
topBar = {
TopAppBar(title = { Text("Embedded Photo Picker demo") })
},
scaffoldState = scaffoldState,
sheetPeekHeight = if (scaffoldState.bottomSheetState.isVisible) 400.dp else 0.dp,
sheetContent = {
Column(Modifier.fillMaxWidth()) {
// We render the embedded photo picker inside the bottom sheet
EmbeddedPhotoPicker(
state = photoPickerState,
embeddedPhotoPickerFeatureInfo = photoPickerInfo
)
}
}
) { innerPadding ->
Column(Modifier.padding(innerPadding).fillMaxSize().padding(horizontal = 16.dp)) {
Button(onClick = {
coroutineScope.launch {
// We expand the bottom sheet, which will trigger the embedded picker to be shown
scaffoldState.bottomSheetState.partialExpand()
}
}) {
Text("Open photo picker")
}
LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 64.dp)) {
// We render the image using the Coil library
itemsIndexed(attachments) { index, uri ->
AsyncImage(
model = uri,
contentDescription = "Image ${index + 1}",
contentScale = ContentScale.Crop,
modifier = Modifier.clickable {
coroutineScope.launch {
// When the user clicks on the media from the app's UI, we deselect it
// from the embedded photo picker by calling the method deselectUri
photoPickerState.deselectUri(uri)
}
}
)
}
}
}
}
}
视图
首先,将 Jetpack Photo Picker 库作为依赖项添加。
implementation("androidx.photopicker:photopicker:1.0.0-alpha01")
如需添加嵌入式照片选择器,您需要在布局文件中添加一个条目。
<view class="androidx.photopicker.EmbeddedPhotoPickerView"
android:id="@+id/photopicker"
android:layout_width="match_parent"
android:layout_height="match_parent" />
并在 activity/fragment 中对其进行初始化。
// We keep track of the list of selected attachments
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) {
openSession = newSession
}
override fun onSessionError (throwable: Throwable) {}
override fun onUriPermissionGranted(uris: List<Uri>) {
_attachments += uris
}
override fun onUriPermissionRevoked (uris: List<Uri>) {
_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)
//
// Add the embedded photo picker to a bottom sheet to allow the dragging to display the full photo library
//
picker = findViewById(R.id.photopicker)
picker.addEmbeddedPhotoPickerStateChangeListener(pickerListener)
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)
请务必注意,嵌入式照片选择器体验适用于搭载 Android 14(API 级别 34)或更高版本且 SDK 扩展程序版本为 15+ 的用户。详细了解照片选择器的设备可用性。
为了增强用户隐私保护和安全性,系统会以防止任何绘制或叠加的方式呈现嵌入式照片选择器。这种有意为之的设计选择意味着,您的用户体验应将照片选择器的显示区域视为一个独立且专用的元素,就像您规划广告横幅一样。
如果您有任何反馈或建议,请向我们的问题跟踪器提交工单。
继续阅读
-
产品动态
隐私保护和用户控制仍然是 Android 体验的核心。正如照片选择器让媒体分享变得安全且易于实现一样,我们现在也将同样级别的隐私保护、简洁性和出色的用户体验带到了联系人选择功能中。
Roxanna Aliabadi Walker • 4 分钟阅读时间
-
产品动态
如果您是 Android 开发者,并且希望在应用中实现创新的 AI 功能,那么您一定会对我们最近发布的功能强大的新更新感兴趣。
Thomas Ezan • 3 分钟阅读时间
-
产品动态
Android 17 已发布 Beta 版 4,这是此发布周期中计划发布的最后一个 Beta 版,是应用兼容性和平台稳定性的重要里程碑。
Daniel Galpin • 4 分钟阅读时间
随时了解最新动态
每周通过电子邮件接收最新的 Android 开发洞见 每周。