Seletor de fotos incorporado

Animação mostrando o processo de seleção contínua do seletor de fotos

O seletor de fotos incorporado é uma forma diferente de escolher fotos, permitindo que ele seja usado diretamente nas interfaces de usuário dos apps. Ele oferece opções de integração e personalização aprimoradas em comparação com o seletor de fotos clássico. Como ele é renderizado em um SurfaceView usando o método setChildSurfacePackage ele mantém os mesmos recursos de segurança e privacidade da versão não incorporada.

Com o seletor de fotos incorporado, os usuários podem selecionar continuamente fotos e vídeos do dispositivo e da biblioteca de fotos na nuvem sem perder o foco no app cliente. O app cliente permanece ativo, sua atividade está em um estado retomado e pode responder às seleções do usuário em tempo real.

O seletor de fotos incorporado oferece uma integração de UI mais perfeita, mas mantém os mesmos recursos de segurança e privacidade do seletor de fotos padrão porque é renderizado em um SurfaceView especial.

Disponibilidade de dispositivos

O seletor de fotos incorporado é compatível com dispositivos que executam o Android 14 (nível 34 da API) com as extensões do SDK versão 15 ou mais recente.

Dispositivos que não correspondem a esses recursos podem usar o seletor de fotos clássico ou a versão de backport com o Google Play Services.

Dependência da biblioteca do Jetpack

Inclua a biblioteca do seletor de fotos do Jetpack como uma dependência:

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

É possível integrar o seletor de fotos incorporado usando o Jetpack Compose (recomendado) ou Views.

Integração do Jetpack Compose

A função combinável EmbeddedPhotoPicker oferece um mecanismo para incluir a interface do seletor de fotos incorporado diretamente na tela do Jetpack Compose. Esse elemento combinável cria um SurfaceView que hospeda a interface do seletor de fotos incorporado. Ele gerencia a conexão com o serviço EmbeddedPhotoPicker, processa as interações do usuário e comunica os URIs de mídia selecionados ao aplicativo de chamada com poucos parâmetros para trabalhar:

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

Seleção contínua

Animação mostrando o processo de seleção contínua do seletor de fotos

Com o seletor de fotos incorporado, os usuários podem selecionar e desmarcar itens da biblioteca de fotos sem fechar o seletor. Os itens selecionados e desmarcados na interface do app são sincronizados com o seletor de fotos, proporcionando uma experiência do usuário otimizada.

Desmarque Uri usando o método deselectUri ou deselectUris de pickerState para notificar o seletor incorporado de que o usuário desmarcou um item da interface do app. É necessário atualizar manualmente o estado da interface do seu app, já que chamar esses métodos não vai notificar o app sobre URIs revogados recentemente pelo callback 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
}

Personalizar o seletor de fotos

O seletor de fotos incorporado oferece opções de personalização, permitindo que você adapte a aparência e o comportamento dele para integrar melhor ao design e à experiência do usuário do app.

Cor de destaque

Por padrão, o seletor de fotos incorporado usa as cores dinâmicas fornecidas pelo sistema, que o usuário pode definir em todos os apps nas opções de temas do dispositivo. A cor de destaque será usada em vários elementos principais no seletor de fotos. Todas as outras cores serão definidas com base nas diretrizes do Material Design do Android. Para personalizar a cor de destaque do seletor, defina a opção EmbeddedPhotoPickerFeatureInfo:

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

EmbeddedPhotoPicker(
    embeddedPhotoPickerFeatureInfo = info,
    ...
)
Sem definir a cor de destaque Com cor de destaque (pico) Com cor de destaque (aberta)
Captura de tela do seletor de fotos sem definir a cor de destaque Captura de tela do seletor de fotos com cor de destaque (pico) Captura de tela do seletor de fotos com cor de destaque (expandido)

A cor de destaque precisa ser totalmente opaca. O valor alfa (transparência) é ignorado. Só são permitidas cores com um valor de luminância (brilho) entre 0,05 e 0,9.

Dimensões

Por padrão, o tamanho do seletor incorporado não é limitado, mas você pode especificar um modificador para limitar:

EmbeddedPhotoPicker(
    modifier = Modifier.height(500.dp),
    ...
)
Sem limite (expandido) Com limite de 500 dp (expandido)
Captura de tela do seletor de fotos Captura de tela do seletor de fotos

Integração de visualizações

Para adicionar o seletor de fotos incorporado usando Views, adicione uma entrada ao arquivo de layout:

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

Em seguida, inicialize o seletor de fotos no método onCreate da sua atividade fazendo o seguinte:

  1. Receber uma referência ao seu EmbeddedPhotoPickerView do layout
  2. Adicione o EmbeddedPhotoPickerStateChangeListener para processar eventos de seleção
  3. Configure o seletor de fotos com EmbeddedPhotoPickerFeatureInfo, incluindo qualquer configuração personalizada, como cor de destaque.
// 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()
    )
}

É possível chamar com os diferentes métodos de EmbeddedPhotoPickerSession para interagir com o seletor incorporado:

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