Selektor zdjęć w ramce

Animacja pokazująca proces wyboru zdjęć w trybie zdjęć seryjnych

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

Dzięki wbudowanemu selektorowi zdjęć użytkownicy mogą nieprzerwanie wybierać zdjęcia i filmy z urządzenia i z biblioteki zdjęć w chmurze, nie tracąc ostrości w aplikacji klienckiej. Aplikacja kliencka pozostaje aktywna, jej działanie jest wznawiane i może reagować na wybory użytkownika w czasie rzeczywistym.

Wbudowany selektor zdjęć zapewnia 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 pakietu SDK w wersji 15 lub nowszej.

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

Zależność 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 EmbeddedPhotoPicker umożliwia umieszczenie interfejsu selektora zdjęć bezpośrednio na ekranie Jetpack Compose. Ten komponent tworzy SurfaceView, który zawiera interfejs osadzonego 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 z kilkoma parametrami:

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 trybie zdjęć seryjnych

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łynne działanie.

Odznacz Uri za pomocą metody deselectUri lub deselectUrispickerState, aby powiadomić osadzony 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 adresach 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 pozwalają dostosować jego wygląd i działanie, aby lepiej zintegrować go z designem aplikacji i wrażeniami użytkowników.

Kolor uzupełniający

Domyślnie wbudowany selektor zdjęć korzysta z dynamicznych kolorów udostępnianych 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 głównych w selektorze zdjęć. Pozostałe kolory zostaną ustawione zgodnie z wytycznymi dotyczącymi materiałów w Androidzie. 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 (szczyt) Z kolorem uzupełniającym (rozwinięty)
Zrzut ekranu selektora zdjęć bez ustawionego koloru akcentu Zrzut ekranu selektora zdjęć z kolorem akcentującym (wartość szczytowa) Zrzut ekranu selektora zdjęć z kolorem akcentu (rozwinięty)

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

Wymiary

Domyślnie rozmiar osadzonego 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 (rozwinięty)
Zrzut ekranu selektora zdjęć Zrzut ekranu selektora zdjęć

Integracja wyświetleń

Aby dodać osadzony 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. Uzyskiwanie odwołania do elementu 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()
    )
}

Możesz wywołać osadzony selektor za pomocą różnych metod EmbeddedPhotoPickerSession, aby wchodzić z nim w interakcje:

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