Selektor zdjęć w ramce

Animacja pokazująca proces wyboru zdjęć w selektorze zdjęć w trybie ciągłym

Wbudowany selektor zdjęć to inna forma wybierania zdjęć, która umożliwia bezpośrednią interakcję w interfejsach aplikacji. W porównaniu z klasycznym selektorem zdjęć oferuje on większe możliwości integracji i dostosowywania. Ponieważ jest renderowany na SurfaceView za pomocą metody setChildSurfacePackage, zachowuje te same funkcje bezpieczeństwa i prywatności co wersja niewbudowana.

Dzięki wbudowanemu selektorowi zdjęć użytkownicy mogą w sposób ciągły wybierać zdjęcia i filmy zarówno z urządzenia, jak i z biblioteki zdjęć w chmurze, bez utraty ostrości w aplikacji klienckiej. Aplikacja kliencka pozostaje aktywna, jej aktywność jest w stanie wznowienia i może reagować na wybory użytkownika w czasie rzeczywistym.

Wbudowany selektor zdjęć oferuje płynniejszą integrację interfejsu, ale zachowuje te same funkcje bezpieczeństwa i prywatności co standardowy selektor zdjęć, ponieważ jest renderowany na specjalnym SurfaceView.

Dostępność urządzeń

Wbudowany selektor zdjęć jest obsługiwany na urządzeniach z Androidem 14 (poziom interfejsu API 34) z rozszerzeniami SDK w wersji 15 lub nowszej.

Urządzenia, które nie spełniają tych wymagań, mogą korzystać z klasycznego selektora zdjęć lub jego wstecznie przeportowanej wersji za pomocą Usług Google Play.

Zależność od biblioteki Jetpack

Dodaj bibliotekę selektora zdjęć Jetpack jako zależność:

// 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")

Wbudowany selektor zdjęć możesz zintegrować za pomocą Jetpack Compose (zalecane) lub widoków.

Integracja z Jetpack Compose

Funkcja typu „composable” EmbeddedPhotoPicker zapewnia mechanizm umożliwiający umieszczenie interfejsu wbudowanego selektora zdjęć bezpośrednio na ekranie Jetpack Compose. Ta funkcja kompozycyjna tworzy SurfaceView, który hostuje interfejs wbudowanego selektora zdjęć. Zarządza połączeniem z usługą EmbeddedPhotoPicker, obsługuje interakcje użytkownika i przekazuje wybrane identyfikatory URI multimediów do aplikacji wywołującej za pomocą kilku parametrów:

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
    },
)

Ciągły wybór

Animacja pokazująca proces wyboru zdjęć w selektorze zdjęć w trybie ciągłym

Wbudowany selektor zdjęć umożliwia użytkownikom ciągłe wybieranie i odznaczanie elementów z biblioteki zdjęć bez zamykania selektora. Elementy wybrane i odznaczone w interfejsie aplikacji są synchronizowane z selektorem zdjęć, co zapewnia płynną obsługę.

Odznacz Uri za pomocą metody deselectUri lub deselectUris z pickerState aby powiadomić wbudowany selektor, że użytkownik odznaczył element w interfejsie aplikacji. Konieczne jest ręczne zaktualizowanie stanu interfejsu aplikacji, ponieważ wywołanie tych metod nie powiadomi aplikacji o nowo cofniętych identyfikatorach URI za pomocą wywołania zwrotnego onUriPermissionRevoked.

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
}

Personalizowanie selektora zdjęć

Wbudowany selektor zdjęć oferuje opcje personalizacji, które umożliwiają dostosowanie jego wyglądu i działania do projektu aplikacji i wygody użytkowników.

Kolor uzupełniający

Domyślnie wbudowany selektor zdjęć korzysta z dynamicznych kolorów dostarczanych przez system, które użytkownik może ustawić w opcjach motywu urządzenia. Kolor uzupełniający będzie używany w przypadku różnych elementów podstawowych w selektorze zdjęć. Wszystkie inne kolory zostaną ustawione zgodnie z wytycznymi Material Design dla Androida. Aby spersonalizować kolor uzupełniający selektora, zdefiniuj opcję EmbeddedPhotoPickerFeatureInfo:

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

EmbeddedPhotoPicker(
    embeddedPhotoPickerFeatureInfo = info,
    ...
)
Bez ustawiania koloru uzupełniającego Z kolorem uzupełniającym (maksymalnym) Z kolorem uzupełniającym (rozszerzonym)
Zrzut ekranu selektora zdjęć bez ustawionego koloru uzupełniającego Zrzut ekranu selektora zdjęć z kolorem uzupełniającym (wartość szczytowa) Zrzut ekranu selektora zdjęć z kolorem uzupełniającym (rozwinięty)

Kolor uzupełniający musi być całkowicie nieprzezroczysty. Wartość alfa (przezroczystość) jest ignorowana. Dozwolone są tylko kolory o luminancji (jasności) od 0,05 do 0,9.

Wymiary

Domyślnie rozmiar wbudowanego selektora nie jest ograniczony, ale możesz określić modyfikator, aby go ograniczyć:

EmbeddedPhotoPicker(
    modifier = Modifier.height(500.dp),
    ...
)
Bez limitu (rozszerzony) Z limitem 500 dp (rozszerzony)
Zrzut ekranu selektora zdjęć Zrzut ekranu selektora zdjęć

Integracja z widokami

Aby dodać wbudowany selektor zdjęć za pomocą widoków, dodaj wpis do pliku układu:

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

Następnie zainicjuj selektor zdjęć w metodzie onCreate aktywności, wykonując te czynności:

  1. Uzyskaj odwołanie do EmbeddedPhotoPickerView z układu.
  2. Dodaj EmbeddedPhotoPickerStateChangeListener, aby obsługiwać zdarzenia wyboru.
  3. Skonfiguruj selektor zdjęć za pomocą EmbeddedPhotoPickerFeatureInfo, w tym wszelkich ustawień niestandardowych, takich jak kolor uzupełniający.
// 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()
    )
}

Aby wchodzić w interakcję z wbudowanym selektorem, możesz wywoływać różne metody 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)