Afficher une image découpée selon une forme

Vous pouvez adapter une image à une forme découpée et dessiner des ombres autour du périmètre de la forme pour lui donner un aspect tridimensionnel. Cette technique est utile pour créer des designs tels que des avatars et des miniatures de produits, ou pour afficher des logos avec des formes personnalisées.

Pour afficher une image découpée selon une forme, vous devez procéder comme suit :

  • Créez la forme.
  • Découpez l'image selon la forme.

Résultats

Chien dans un hexagone avec une ombre appliquée sur les bords
Figure 1. Forme personnalisée appliquée comme clip.

Compatibilité des versions

Cette implémentation nécessite que le minSDK de votre projet soit défini sur le niveau d'API 21 ou supérieur.

Dépendances

Créer une forme

Le code suivant crée une forme personnalisée qui peut dessiner et afficher dynamiquement un polygone arrondi :

fun RoundedPolygon.getBounds() = calculateBounds().let { Rect(it[0], it[1], it[2], it[3]) }
class RoundedPolygonShape(
    private val polygon: RoundedPolygon,
    private var matrix: Matrix = Matrix()
) : Shape {
    private var path = Path()
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        path.rewind()
        path = polygon.toPath().asComposePath()
        matrix.reset()
        val bounds = polygon.getBounds()
        val maxDimension = max(bounds.width, bounds.height)
        matrix.scale(size.width / maxDimension, size.height / maxDimension)
        matrix.translate(-bounds.left, -bounds.top)

        path.transform(matrix)
        return Outline.Generic(path)
    }
}

Points clés concernant le code

  • RoundedPolygon.getBounds() définit une fonction d'extension sur la classe RoundedPolygon pour calculer ses limites.
  • La classe RoundedPolygonShape implémente l'interface Shape, ce qui vous permet de définir une forme personnalisée (un polygone arrondi) dans Jetpack Compose.
  • La forme utilise un Matrix pour gérer les opérations de mise à l'échelle et de translation pour un rendu flexible.
  • La fonction createOutline() prend un objet RoundedPolygon, le met à l'échelle et le traduit pour l'adapter à une taille donnée, puis renvoie un objet Outline qui décrit la forme finale à dessiner.

Découper l'image selon une forme

Le code suivant recadre l'image en hexagone et ajoute une ombre portée subtile pour donner une impression de profondeur :

val hexagon = remember {
    RoundedPolygon(
        6,
        rounding = CornerRounding(0.2f)
    )
}
val clip = remember(hexagon) {
    RoundedPolygonShape(polygon = hexagon)
}
Box(
    modifier = Modifier
        .clip(clip)
        .background(MaterialTheme.colorScheme.secondary)
        .size(200.dp)
) {
    Text(
        "Hello Compose",
        color = MaterialTheme.colorScheme.onSecondary,
        modifier = Modifier.align(Alignment.Center)
    )
}

Points clés concernant le code

  • Les objets RoundedPolygon et RoundedPolygonShape sont utilisés pour définir et appliquer une forme hexagonale à l'image.
  • Le code utilise graphicsLayer pour ajouter une ombre basée sur l'élévation à l'image. Cela crée une impression de profondeur et une séparation visuelle de l'arrière-plan.
  • L'utilisation de blocs remember optimise les performances en garantissant que les définitions de forme et de découpage sont calculées une seule fois et mémorisées pour les recompositions ultérieures de l'UI.

Collections contenant ce guide

Ce guide fait partie des collections de guides de démarrage rapide organisées qui couvrent des objectifs de développement Android plus larges :

Découvrez des techniques pour utiliser des visuels lumineux et attrayants afin de donner à votre application Android une apparence agréable.

Vous avez des questions ou des commentaires ?

Consultez notre page de questions fréquentes et découvrez nos guides rapides. Vous pouvez également nous contacter pour nous faire part de vos commentaires.