InkWell ne montre pas d'effet d'entraînement

96

Appuyer sur le conteneur déclenche le onTap()gestionnaire mais n'affiche aucun effet d'éclaboussure d'encre.

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new InkWell(
          onTap: (){print("tapped");},
          child: new Container(
            width: 100.0,
            height: 100.0,
            color: Colors.orange,
          ),
        ),
      ),
    );
  }
}

J'ai essayé de mettre l' InkWellintérieur Containeraussi mais en vain.

J. Sarkar
la source

Réponses:

152

Je pense que l'ajout de couleur au conteneur recouvre l'effet d'encre

https://docs.flutter.io/flutter/material/InkWell/InkWell.html

Ce code semble fonctionner

  body: new Center(
    child: new Container(
      child: new Material(
        child: new InkWell(
          onTap: (){print("tapped");},
          child: new Container(
            width: 100.0,
            height: 100.0,
          ),
        ),
        color: Colors.transparent,
      ),
      color: Colors.orange,
    ),
  ),

cliquez simplement sur le carré du milieu.

Edit: j'ai trouvé le rapport de bogue. https://github.com/flutter/flutter/issues/3782

C'est en fait comme prévu, bien que nous devions mettre à jour la documentation pour la rendre plus claire.

Ce qui se passe, c'est que la spécification du matériau indique que les éclaboussures sont en fait de l'encre sur le matériau. Ainsi, lorsque nous éclaboussons, nous faisons littéralement éclabousser le widget Matériel. Si vous avez quelque chose sur le matériau, nous éclaboussons dessous et vous ne pouvez pas le voir.

J'ai voulu ajouter un widget "MaterialImage" qui imprime conceptuellement son image dans le Material afin que les éclaboussures soient alors sur l'image. Nous pourrions avoir un MaterialDecoration qui fait quelque chose de similaire pour une décoration. Ou nous pourrions demander à Material lui-même de prendre une décoration. À l'heure actuelle, il faut une couleur, mais nous pourrions l'étendre à toute une décoration. Il n'est pas clair s'il est vraiment compatible avec les spécifications des matériaux d'avoir un matériau avec un dégradé, donc je ne suis pas sûr que nous devrions le faire.

À court terme, si vous avez juste besoin d'une solution de contournement, vous pouvez placer un matériau sur le dessus du conteneur, avec le matériau défini pour utiliser le type «transparence», puis mettre bien l'encre à l'intérieur.

--hixie

Mise à jour: Hixie a fusionné une nouvelle solution d'encre l'année dernière. L'encre offre un moyen pratique d'éclabousser les images.

  testWidgets('Does the Ink widget render anything', (WidgetTester tester) async {
    await tester.pumpWidget(
      new Material(
        child: new Center(
          child: new Ink(
            color: Colors.blue,
            width: 200.0,
            height: 200.0,
            child: new InkWell(
              splashColor: Colors.green,
              onTap: () { },
            ),
          ),
        ),
      ),
    );


Material(
  color: Colors.grey[800],
  child: Center(
    child: Ink.image(
      image: AssetImage('cat.jpeg'),
      fit: BoxFit.cover,
      width: 300.0,
      height: 200.0,
      child: InkWell(
        onTap: () { /* ... */ },
        child: Align(
          alignment: Alignment.topLeft,
          child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: Text('KITTEN', style: TextStyle(fontWeight: FontWeight.w900, color: Colors.white)),
          ),
        )
      ),
    ),
  ),
)

Remarque: je n'ai pas testé le nouveau widget d'encre. J'ai copié le code de ink_paint_test.dart et la documentation de la classe Ink

https://github.com/Hixie/flutter/blob/1f6531984984f52328e66c0cd500a8d517964564/packages/flutter/test/material/ink_paint_test.dart

https://github.com/flutter/flutter/pull/13900

https://api.flutter.dev/flutter/material/Ink-class.html

user1462442
la source
2
Vous pouvez simplement mettre la couleur sur Materialelle - même et laisser de côté le Container.
Herohtar
1
J'ai un peu pensé quand CopsOnRoad a posté sa réponse.
user1462442
1
@KoenVanLooveren Essayez la réponse CopsOnRoad. Je n'ai pas édité ma solution car la solution de CopsOnRoad est assez élégante
user1462442
C'est ce que j'ai utilisé après quelques refactoring: D merci
Koen Van Looveren
dans mon cas, c'était la forme du conteneur, merci pour la solution
Mohammad Ersan
106

Production:

entrez la description de l'image ici


Utilisez simplement un Inkwidget enveloppé dans un fichier InkWell.

InkWell(
  onTap: () {}, // needed
  child: Ink( // use Ink
    width: 200,
    height: 200,
    color: Colors.blue,
  ),
)
CopsOnRoad
la source
La source confirme l'étape 3: github.com/flutter/flutter/blob/… Dans chaque gestionnaire, ils vérifient si le rappel est disponible, sinon rien ne se passe.
Nightking
@CopsOnRoad, puis-je vous demander d'avoir une question liée au flutter ici: stackoverflow.com/questions/60539378/… ?
Istiaque Ahmed
Si par le code complet vous entendez l'exemple que vous avez donné, alors oui. J'ai trouvé que c'était la solution> stackoverflow.com/a/58556613/12140067
Chris
Je pense que vous @ Chris pourriez avoir quelques - uns Theme« ou Materiall » ingérence, parce que ce code fonctionne toute la journée.
CopsOnRoad
1
c'est la seule solution qui a fonctionné pour moi
easazade
24

InkWell () n'affichera jamais l'effet d'entraînement tant que vous n'aurez pas ajouté le

onTap : () {} 

ou l'un des rappels comme onDoubleTap, onLongPress etc.

à l'intérieur du InkWell lorsqu'il commence à écouter vos taps uniquement lorsque vous spécifiez ce paramètre.

Jaswant Singh
la source
Ouais je l'ai fait, et c'est vrai. Vérifiez la source: github.com/flutter/flutter/blob/… Dans chaque gestionnaire, ils vérifient si le rappel est disponible, sinon rien ne se passe.
Nightking
17
  1. Le widget InkWell doit avoir un widget Material comme ancêtre, sinon il ne peut pas afficher d'effets. Par exemple:

    Material(
      child : InkWell(
        child : .....
    
  2. vous devez ajouter une onTapméthode pour voir les effets réels comme

     Buttons {RaisedButton,FlatButton etc}.
     e.g -> Material(
                 child : InkWell(
                         onTap : (){}
                         child : .....
    

Venons-en aux points principaux, voyons quelques exemples ci-dessous et essayons de comprendre les concepts réels d'InkWell.

  • Dans l'exemple ci-dessous, Material est le parent d'InkWell avec onTap mais il ne fonctionne toujours pas. Veuillez essayer d'en comprendre le concept. Vous devez fournir une marge au conteneur ou à un autre widget pour afficher les effets. En fait, le code ci-dessous fonctionne bien, mais nous ne pouvons pas le voir car nous n'avons fourni aucune marge ou alignement, il n'a donc pas d'espace pour afficher les effets.

    Widget build(BuildContext context) {
      return Center(
        child: Material(
          child: new InkWell(
            onTap: () {
              print("tapped");
            },
            child: new Container(
              width: 100.0,
              height: 100.0,
              color: Colors.orange,
            ),  
          ),
        ),
      );
    }
    
  • L'exemple ci-dessous montre les effets InkWell uniquement vers le haut car nous fournissons de l'espace {margin}.

    Widget build(BuildContext context) {
      return Center(
        child: Material(
          child: new InkWell(
            onTap: () {
              print("tapped");
            },
            child: new Container(
              margin: EdgeInsets.only(top: 100.0),
              width: 100.0,
              height: 100.0,
              color: Colors.orange,
            ),
          ),
        ),
      );
    }
    
  • Ci-dessous exp. afficher les effets dans toute la page car le centre crée une marge de tous les côtés. Alignez au centre son widget enfant en haut, à gauche, à droite et en bas.

    Widget build(BuildContext context) {
      return Center(
        child: Material(
          child: new InkWell(
            onTap: () {
              print("tapped");
            },
            child: Center(
              child: new Container(
                width: 100.0,
                height: 100.0,
                color: Colors.orange,
              ),
            ),
          ),
        ),
      );
     }
    
97loser
la source
9

Une meilleure façon est d'utiliser le Inkwidget au lieu de tout autre widget.

Au lieu de définir le colorconteneur à l'intérieur, vous pouvez le définir dans le Inkwidget lui-même.

Le code ci-dessous fonctionnera.

Ink(
  color: Colors.orange,
  child: InkWell(
    child: Container(
      width: 100,
      height: 100,
    ),
    onTap: () {},
  ),
)

N'oubliez pas d'ajouter un onTap: () {}dans le InkWellsinon cela ne montrera pas l'effet d'entraînement aussi.

ibhavikmakwana
la source
4

J'ai trouvé cette solution pour moi. Je pense que cela peut vous aider:

Material(
      color: Theme.of(context).primaryColor,
      child: InkWell(
        splashColor: Theme.of(context).primaryColorLight,
        child: Container(
          height: 100,
        ),
        onTap: () {},
      ),
    )

Colorest donné au widget Matériel. C'est la couleur par défaut de votre widget. Vous pouvez ajuster la couleur de l'effet d'entraînement en utilisant la splashColorpropriété de Inkwell.

Kanan Yusubov
la source
3

C'est la meilleure façon que je trouve et utilise toujours. Tu peux l'essayer.

  • Enveloppez votre WidgetavecInkWell
  • Envelopper InkWellavecMaterial
  • Définissez quand même l'opacité à 0%. par exemple:color: Colors.white.withOpacity(0.0),

    Material(
      color: Colors.white.withOpacity(0.0),
      child: InkWell(
        child: Container(width: 100, height: 100),
        onTap: (){print("Wow! Ripple");},
      ),
    )
    
Sa Sadik
la source
2

J'ai rencontré ce même problème en essayant de créer une couleur alternée d'InkWell dans un ListView. Dans ce cas particulier, il existe une solution simple: enveloppez les alternatives dans un conteneur qui utilise un changement de teinte / luminosité principalement transparent - l'animation tactile InkWell sera toujours visible en dessous. Aucun matériel nécessaire. Notez qu'il y a d'autres problèmes lorsque vous essayez de contourner ce problème avec un Materal - par exemple, il remplacera un DefaultTextStyle que vous utilisez avec la valeur par défaut (il installe un AnimatedDefaultTextStyle), ce qui est très pénible.

user3483238
la source
2

Cela fonctionne pour moi:

Material(
    color: Colors.white.withOpacity(0.0),
    child: InkWell(
      splashColor: Colors.orange,
      child: Text('Hello'), // actually here it's a Container wrapping an image
      onTap: () {
        print('Click');
      },
    ));

Après avoir essayé de nombreuses réponses ici, c'était une combinaison de:

  1. Réglage splashColor
  2. Emballage InkWelldansMaterial(color: Colors.white.withOpacity(0.0), ..)

Merci aux réponses ici qui font ces 2 points

Gene Bo
la source
1

Après avoir ajouté l' onTap:(){}auditeur, l'effet d'entraînement devrait fonctionner correctement. Cela ne fonctionne pas si vous utilisez BoxShadow()avec dans le InkWell()widget.

Aruna Warnasooriya
la source
Voilà le truc. Ripple ne fonctionnera pas sans onTap (). Merci mec!
Hardik Joshi le
0

J'ai été frappé par un problème similaire en ajoutant un encrier à un widget complexe existant avec un conteneur enveloppant un BoxDecoration avec une couleur. En ajoutant le matériau et l'encrier de la manière suggérée, l'encrier était toujours obscurci par la BoxDecoration, j'ai donc rendu la couleur de la BoxDecoration légèrement opaque, ce qui permettait de voir l'encrier.

Lee McLoughlin
la source
0

La solution aux widgets circulaires, faites comme ci-dessous:

Material(
    color: Colors.transparent,
    child: Container(
      alignment: Alignment.center,
      height: 100,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          IconButton(
              enableFeedback: true,
              iconSize: 40,
              icon: Icon(
                Icons.skip_previous,
                color: Colors.white,
                size: 40,
              ),
              onPressed: () {}),
          IconButton(
            iconSize: 100,
            enableFeedback: true,
            splashColor: Colors.grey,
            icon: Icon(Icons.play_circle_filled, color: Colors.white, size: 100),
            padding: EdgeInsets.all(0),
            onPressed: () {},
          ),
          IconButton(
              enableFeedback: true,
              iconSize: 40,
              icon: Icon(
                Icons.skip_next,
                color: Colors.white,
                size: 40,
              ),
              onPressed: () {}),
        ],
      ),
    ),
  )
Edeson Bizerril
la source
0

Pour moi, c'était un autre problème. InkWell ne montrait pas d'effet d'entraînement lorsque j'avais la fonction onTap comme paramètre de mon widget défini comme ci-dessous.

Function(Result) onTapItem;
...
onTap: onTapItem(result),

Je ne sais pas quelle est la différence, mais le code suivant fonctionne bien.

onTap: (){ onTapItem(result); },
maladroit
la source