Actualités des produits

Sélecteur de photos intégré

Temps de lecture : 8 min

Sélecteur de photos intégré : un moyen plus fluide de demander des photos et des vidéos de manière privée dans votre application

photopicker.png

Préparez-vous à améliorer l'expérience utilisateur de votre application grâce à une nouvelle façon d'utiliser le sélecteur de photos Android. Le nouveau sélecteur de photos intégré offre aux utilisateurs un moyen fluide et respectueux de la confidentialité de sélectionner des photos et des vidéos directement dans l'interface de votre application. Votre application peut désormais bénéficier de tous les avantages du sélecteur de photos, y compris l'accès au contenu cloud, directement intégré à l'expérience de votre application.

Pourquoi l'intégration ?

Nous comprenons que de nombreuses applications souhaitent offrir une expérience très intégrée et fluide aux utilisateurs lorsqu'ils sélectionnent des photos ou des vidéos. Le sélecteur de photos intégré est conçu à cet effet. Il permet aux utilisateurs d'accéder rapidement à leurs photos récentes sans jamais quitter votre application. Ils peuvent également explorer l'intégralité de leur bibliothèque dans leur fournisseur de services multimédias cloud préféré (par exemple, Google Photos), y compris les favoris, les albums et la fonctionnalité de recherche. Les utilisateurs n'ont donc plus besoin de passer d'une application à l'autre ni de se demander si la photo qu'ils recherchent est stockée localement ou dans le cloud.

Intégration parfaite, confidentialité renforcée

Avec le sélecteur de photos intégré, votre application n'a pas besoin d'accéder aux photos ou vidéos de l'utilisateur tant qu'il n'en a pas sélectionné. Cela signifie une confidentialité accrue pour vos utilisateurs et une expérience plus fluide. De plus, le sélecteur de photos intégré permet aux utilisateurs d'accéder à l'ensemble de leur bibliothèque multimédia basée dans le cloud, tandis que l'autorisation photo standard est limitée aux fichiers locaux uniquement.

Sélecteur de photos intégré à Google Messages

Google Messages met en avant la puissance du sélecteur de photos intégré. Voici comment ils l'ont intégré :

  • Positionnement intuitif  : le sélecteur de photos se trouve juste en dessous du bouton de l'appareil photo, ce qui permet aux utilisateurs de choisir clairement entre prendre une nouvelle photo ou en sélectionner une existante.
  • Aperçu dynamique : immédiatement après qu'un utilisateur a appuyé sur une photo, un grand aperçu s'affiche, ce qui lui permet de confirmer facilement sa sélection. S'il désélectionne la photo, l'aperçu disparaît, ce qui permet de conserver une expérience claire et épurée.
  • Développer pour afficher plus de contenu  : la vue initiale est simplifiée et permet d'accéder facilement aux photos récentes. Toutefois, les utilisateurs peuvent facilement développer le sélecteur de photos pour parcourir et choisir parmi toutes les photos et vidéos de leur bibliothèque, y compris le contenu cloud de Google Photos.
  • Respect des choix de l'utilisateur : le sélecteur de photos intégré n'accorde l'accès qu'aux photos ou vidéos spécifiques sélectionnées par l'utilisateur. Cela signifie que vous pouvez cesser de demander les autorisations d'accès aux photos et vidéos. Cela évite également à Messages d'avoir à gérer les situations où les utilisateurs n'accordent qu'un accès limité aux photos et vidéos.
gif1.gif
gif2.gif

Mise en œuvre

L'intégration du sélecteur de photos intégré est facilitée par la bibliothèque Jetpack du sélecteur de photos.  

Jetpack Compose

Commencez par inclure la bibliothèque Jetpack Photo Picker en tant que dépendance.

implementation("androidx.photopicker:photopicker-compose:1.0.0-alpha01")

La fonction composable EmbeddedPhotoPicker fournit un mécanisme permettant d'inclure l'UI du sélecteur de photos intégré directement dans votre écran Compose. Ce composable crée une SurfaceView qui héberge l'UI du sélecteur de photos intégré. Il gère la connexion au service EmbeddedPhotoPicker, traite les interactions des utilisateurs et communique les URI des éléments multimédias sélectionnés à l'application appelante.  

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

Vues

Commencez par inclure la bibliothèque Jetpack Photo Picker en tant que dépendance.

implementation("androidx.photopicker:photopicker:1.0.0-alpha01")

Pour ajouter le sélecteur de photos intégré, vous devez ajouter une entrée à votre fichier de mise en page.  

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

Initialisez-le dans votre activité/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()
    )
}

Vous pouvez appeler différentes méthodes de EmbeddedPhotoPickerSession pour interagir avec le sélecteur intégré.

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

Il est important de noter que l'expérience du sélecteur de photos intégré est disponible pour les utilisateurs exécutant Android 14 (niveau d'API 34) ou version ultérieure avec les extensions SDK 15+. En savoir plus sur la disponibilité du sélecteur de photos sur les appareils

Pour renforcer la confidentialité et la sécurité des utilisateurs, le système affiche le sélecteur de photos intégré de manière à empêcher tout dessin ou superposition. Ce choix de conception intentionnel signifie que votre UX doit considérer la zone d'affichage du sélecteur de photos comme un élément distinct et dédié, tout comme vous le feriez pour une bannière publicitaire.

Si vous avez des commentaires ou des suggestions, envoyez des tickets à notre outil de suivi des problèmes.

Écrit par :

Lire la suite