InkWell no muestra efecto dominó


94

Al tocar el contenedor, se activa el onTap()controlador, pero no se muestra ningún efecto de salpicadura de tinta.

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

Intenté poner el InkWellinterior Containertambién pero en vano.

Respuestas:


151

Creo que agregar color al recipiente cubre el efecto de tinta.

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

Este código parece funcionar

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

simplemente haga clic en el cuadrado del medio.

Editar: encontré el informe de error. https://github.com/flutter/flutter/issues/3782

En realidad, esto es lo que se esperaba, aunque deberíamos actualizar los documentos para que sea más claro.

Lo que sucede es que la especificación del material dice que las salpicaduras son en realidad tinta sobre el material. Entonces, cuando salpicamos, lo que hacemos es literalmente hacer que el widget Material haga el efecto. Si tiene algo encima del Material, salpicamos debajo de él y no puede verlo.

He querido agregar un widget "MaterialImage" que imprime conceptualmente su imagen en el Material también para que luego las salpicaduras estén sobre la imagen. Podríamos tener un MaterialDecoration que haga algo similar para una Decoración. O podríamos hacer que el propio Material tome una decoración. Ahora mismo toma un color, pero podríamos extenderlo a una decoración completa. Sin embargo, no está claro si es realmente compatible con las especificaciones del material tener un material con un degradado, por lo que no estoy seguro de si deberíamos hacer eso.

A corto plazo, si solo necesita una solución alternativa, puede colocar un Material en la parte superior del contenedor, con el material configurado para usar el tipo de "transparencia", y luego poner la tinta bien dentro.

--hixie

Actualización: Hixie fusionó una nueva solución de tinta el año pasado. La tinta proporciona una forma cómoda de salpicar imágenes.

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

Nota: no probé el nuevo Ink Widget. Copié el código de ink_paint_test.dart y los documentos de la clase 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


2
Puede simplemente poner el color en Materialsí mismo y omitir el Container.
Herohtar

1
Me imaginé un poco cuando CopsOnRoad publicó su respuesta.
user1462442

1
@KoenVanLooveren Prueba la respuesta de CopsOnRoad. No edité mi solución porque la solución de CopsOnRoad es bastante elegante
user1462442

Eso es lo que usé después de una refactorización: D gracias
Koen Van Looveren

en mi caso fue la forma del contenedor, gracias por la solución
Mohammad Ersan

106

Salida:

ingrese la descripción de la imagen aquí


Simplemente use el Inkwidget envuelto en un InkWell.

InkWell(
  onTap: () {}, // needed
  child: Ink( // use Ink
    width: 200,
    height: 200,
    color: Colors.blue,
  ),
)

La fuente confirma el paso 3: github.com/flutter/flutter/blob/… En cada controlador verifican si la devolución de llamada está disponible, de lo contrario no pasa nada.
Nightking

@CopsOnRoad, ¿puedo pedirle que tenga una pregunta relacionada con el aleteo aquí: stackoverflow.com/questions/60539378/… ?
Istiaque Ahmed

Si por el código completo te refieres al ejemplo que has dado, entonces sí. Descubrí que esta es la solución> stackoverflow.com/a/58556613/12140067
Chris

@ Chris creo que puede estar teniendo algunos Theme'o Material' interferencia s, ya que este código funciona durante todo el día.
CopsOnRoad

1
esta es la única solución que funcionó para mí
easazade

24

InkWell () nunca mostrará el efecto dominó hasta que agregue el

onTap : () {} 

o cualquiera de las devoluciones de llamada como onDoubleTap, onLongPress, etc.

dentro de InkWell, ya que comienza a escuchar sus toques solo cuando especifica este parámetro.


Sí, lo hice, y es cierto. Verifique la fuente: github.com/flutter/flutter/blob/… En cada controlador verifican si la devolución de llamada está disponible, de lo contrario no pasa nada.
Nightking

17
  1. El widget InkWell debe tener un widget Material como antepasado, de lo contrario no puede mostrar efectos. P.ej:

    Material(
      child : InkWell(
        child : .....
    
  2. tienes que agregar un onTapmétodo para ver los efectos reales como

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

Vayamos a los puntos principales, veamos algunos ejemplos a continuación e intentemos comprender los conceptos reales de InkWell.

  • En el ejemplo siguiente, el material es padre de InkWell con onTap, pero todavía no funciona. Intente comprender el concepto de la misma. Debe proporcionar algún margen al contenedor u otro widget para mostrar los efectos. En realidad, el código debajo funciona bien, pero no podemos ver porque no proporcionamos ningún margen o alineación, por lo que no tiene espacio para mostrar los efectos.

    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,
            ),  
          ),
        ),
      );
    }
    
  • El siguiente ejemplo muestra los efectos InkWell solo hacia arriba porque proporcionamos espacio {margen}.

    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,
            ),
          ),
        ),
      );
    }
    
  • Por debajo de exp. muestre los efectos en toda la página porque el centro crea un margen desde todos los lados. Alinee al centro su widget secundario desde la parte superior, izquierda, derecha e inferior.

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

9

Una mejor forma es utilizar el Inkwidget en lugar de cualquier otro widget.

En lugar de definir el colorcontenedor interior, puede definirlo en el Inkpropio widget.

El siguiente código funcionará.

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

No olvide agregar un onTap: () {}en el caso InkWellcontrario, no mostrará el efecto dominó también.


4

He encontrado esta solución para mí. Creo que te puede ayudar:

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

Colorse le da al widget Material. Es el color predeterminado de su widget. Puede ajustar el color del efecto dominó usando la splashColorpropiedad de Inkwell.


3

Esta es la mejor manera que encontré y la uso siempre. Puedes probarlo.

  • Envuelve tu WidgetconInkWell
  • Envolver InkWellconMaterial
  • Establezca la opacidad al 0% de todos modos. p.ej: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");},
      ),
    )
    

2

Me encontré con este mismo problema al intentar crear un color alternativo de InkWell en un ListView. En ese caso particular, hay una solución simple: envuelva las alternativas en un contenedor que usa un cambio de tinte / brillo en su mayoría transparente; la animación táctil de InkWell seguirá siendo visible debajo de él. No se necesita material. Tenga en cuenta que hay otros problemas al intentar solucionar esto con un Materal, por ejemplo, anulará un DefaultTextStyle que está utilizando con el predeterminado (instala un AnimatedDefaultTextStyle) que es un gran dolor.


2

Esto es trabajo para mí:

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

Después de probar muchas respuestas aquí, fue una combinación de:

  1. Ajuste splashColor
  2. envolver InkWellenMaterial(color: Colors.white.withOpacity(0.0), ..)

Gracias a las respuestas aquí que hacen esos 2 puntos


1

Después de agregar onTap:(){}oyente, el efecto dominó debería funcionar bien. No funciona si lo usa BoxShadow()con en el InkWell()widget.


Ese es el truco. Ripple no funcionará sin onTap (). ¡Gracias hombre!
Hardik Joshi

0

Me golpeó un problema similar al agregar un Inkwell a un Widget complejo existente con un Contenedor que envuelve un BoxDecoration con un color. Al agregar el material y el tintero de la manera sugerida, el tintero todavía estaba oscurecido por BoxDecoration, así que hice que el color de BoxDecoration fuera ligeramente opaco, lo que permitió que se viera el tintero.


0

La solución a los widgets circulares, haga lo siguiente:

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: () {}),
        ],
      ),
    ),
  )

0

Para mí fue otro problema. InkWell no mostraba un efecto dominó cuando tenía la función onTap como parámetro de mi widget definido como se muestra a continuación.

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

No sé cuál es la diferencia, pero el siguiente código está funcionando bien.

onTap: (){ onTapItem(result); },
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.