flutter-svg-icon-colorfilter-visibility

Par divinevideo · divine-mobile

Corriger les icônes SVG invisibles ou peu visibles dans Flutter lors de l'utilisation du package flutter_svg. À utiliser quand : (1) les icônes SVG apparaissent invisibles malgré des couleurs correctes dans le fichier SVG, (2) l'utilisation du widget Opacity pour modifier la visibilité/l'état des icônes ne produit pas un rendu correct, (3) les icônes de tab bar ou de navigation disparaissent ou ont de mauvaises couleurs, (4) les icônes avec `fill="white"` ne s'affichent pas sur fond sombre. La solution consiste à utiliser `ColorFilter.mode()` à la place du widget Opacity pour le style d'état des icônes SVG.

npx skills add https://github.com/divinevideo/divine-mobile --skill flutter-svg-icon-colorfilter-visibility

Flutter SVG Icon ColorFilter vs Opacity

Problème

Les icônes SVG rendus avec flutter_svg apparaissent invisibles ou ont une visibilité incorrecte lorsque vous utilisez le widget Opacity pour indiquer les états sélectionné/non sélectionné. Cela se produit généralement dans les barres de navigation inférieure, les barres d'onglets, ou toute interface utilisateur avec des changements d'état d'icône.

Contexte / Conditions de déclenchement

  • Utilisation du package flutter_svg avec SvgPicture.asset()
  • Les fichiers SVG ont des couleurs de remplissage explicites (ex. fill="white")
  • Les icônes enveloppées dans le widget Opacity pour les états sélectionné/non sélectionné
  • Les icônes apparaissent invisibles ou à peine visibles malgré un contenu SVG correct
  • La couleur de fond devrait fournir un contraste suffisant (ex. blanc sur vert foncé)

Solution

Remplacez le widget Opacity par ColorFilter sur le SvgPicture :

Avant (problématique) :

Widget _buildTabButton(String iconPath, bool isSelected) {
  return Opacity(
    opacity: isSelected ? 1.0 : 0.5,
    child: SvgPicture.asset(iconPath, width: 32, height: 32),
  );
}

Après (correct) :

Widget _buildTabButton(String iconPath, bool isSelected) {
  final iconColor = isSelected ? Colors.white : Colors.grey;

  return SvgPicture.asset(
    iconPath,
    width: 32,
    height: 32,
    colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
  );
}

Points clés

  1. ColorFilter.mode avec BlendMode.srcIn remplace la couleur de remplissage du SVG par la couleur spécifiée partout où le SVG a des pixels opaques

  2. Ne vous fiez pas à Opacity pour les changements de couleur - Opacity affecte la transparence mais ne change pas la couleur réelle rendue, ce qui peut causer des problèmes de visibilité

  3. L'attribut fill du SVG est remplacé - Même si votre SVG a fill="white", le ColorFilter le remplacera par votre couleur spécifiée

Vérification

Après application de la correction :

  1. Les icônes sélectionnées doivent s'afficher dans la couleur sélectionnée (ex. blanc)
  2. Les icônes non sélectionnées doivent s'afficher dans la couleur non sélectionnée (ex. gris)
  3. Les deux états doivent être clairement visibles sur le fond

Exemple

Barre de navigation inférieure avec coloration appropriée des icônes :

Widget _buildNavIcon(String assetPath, int tabIndex, int currentIndex) {
  final isSelected = tabIndex == currentIndex;
  final iconColor = isSelected ? Colors.white : const Color(0xFF8A9A94);

  return GestureDetector(
    onTap: () => _onTabTap(tabIndex),
    child: Container(
      width: 48,
      height: 48,
      padding: const EdgeInsets.all(8),
      child: SvgPicture.asset(
        assetPath,
        width: 32,
        height: 32,
        colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
      ),
    ),
  );
}

Remarques

  • Cela s'applique spécifiquement au package flutter_svg ; les autres solutions de rendu SVG peuvent se comporter différemment
  • Si vous avez besoin à la fois du changement de couleur ET de l'opacité, appliquez d'abord le ColorFilter, puis enveloppez dans Opacity si vraiment nécessaire
  • Pour les icônes qui doivent conserver leur apparence multicolore d'origine, n'utilisez pas ColorFilter - mais dans ce cas Opacity seul peut fonctionner correctement
  • BlendMode.srcIn signifie spécifiquement « afficher la couleur source où la destination (SVG) est opaque »

Références

Skills similaires