內嵌相片挑選工具

動畫:顯示連續相片挑選器選取程序

內嵌相片挑選器是另一種相片挑選體驗,可直接在應用程式的使用者介面中互動。相較於傳統相片挑選器,它提供更完善的整合和自訂選項。由於是透過 SurfaceView 使用 setChildSurfacePackage 方法算繪,因此與非嵌入式版本一樣,具備相同的安全和隱私權功能。

有了內嵌的相片挑選工具,使用者就能持續從裝置和雲端相片庫選取相片和影片,不必離開用戶端應用程式。用戶端應用程式會保持啟用狀態,其活動會處於恢復狀態,並可即時回應使用者選取的項目。

內嵌相片挑選工具可提供更流暢的使用者介面整合體驗,但仍保有與標準相片挑選工具相同的安全性和隱私權功能,因為這項工具是在特殊的 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 (建議使用) 或 Views 整合內嵌相片挑選器。

整合 Jetpack Compose

EmbeddedPhotoPicker 可組合函式提供機制,可直接在 Jetpack Compose 畫面中加入內嵌的相片挑選工具 UI。這個可組合函式會建立 SurfaceView,用於代管內嵌的相片挑選工具 UI。這項服務會管理與 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
    },
)

持續選取

動畫:顯示連續相片挑選器選取程序

內嵌的相片挑選工具可讓使用者從相片庫中持續選取和取消選取項目,不必關閉挑選工具。應用程式 UI 中選取和取消選取的項目會與相片挑選器同步,提供流暢的使用者體驗。

使用 deselectUrideselectUris 方法從 pickerState 取消選取 Uri,通知內嵌挑選器使用者已從應用程式的 UI 取消選取項目。您必須手動更新自己的應用程式 UI 狀態,因為呼叫這些方法不會透過 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 Design 指南設定。如要自訂挑選器的強調色,請定義 EmbeddedPhotoPickerFeatureInfo 選項:

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

EmbeddedPhotoPicker(
    embeddedPhotoPickerFeatureInfo = info,
    ...
)
未設定強調色 使用強調色 (最高用量) 使用強調色 (展開)
未設定強調色的相片挑選器螢幕截圖 相片挑選器螢幕截圖,顯示強調色 (最高值) 螢幕截圖:相片挑選器 (已展開),顯示輔色

輔色必須完全不透明。系統會忽略 Alpha 透明層的值。只允許亮度值介於 0.05 和 0.9 之間的顏色。

尺寸

根據預設,內嵌挑選器的大小沒有限制,但您可以指定修飾符來限制大小:

EmbeddedPhotoPicker(
    modifier = Modifier.height(500.dp),
    ...
)
無限制 (擴充) 寬度上限為 500 dp (已展開)
相片挑選工具的螢幕截圖 相片挑選工具的螢幕截圖

Views 整合

如要使用 Views 新增內嵌的相片選擇器,請在版面配置檔案中新增項目:

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

接著,在活動的 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)