InkWell nie pokazuje efektu tętnienia


94

Stuknięcie w pojemnik uruchamia onTap()uchwyt, ale nie pokazuje żadnego efektu rozpryskiwania atramentu.

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

Próbowałem też InkWellwłożyć wnętrze, Containerale na próżno.

Odpowiedzi:


151

Myślę, że dodanie koloru do pojemnika przesłania efekt tuszu

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

Ten kod wydaje się działać

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

po prostu kliknij środkowy kwadrat.

Edycja: znalazłem raport o błędzie. https://github.com/flutter/flutter/issues/3782

W rzeczywistości jest to zgodne z oczekiwaniami, chociaż powinniśmy zaktualizować dokumentację, aby była bardziej przejrzysta.

Chodzi o to, że specyfikacja materiału mówi, że plamy są w rzeczywistości atramentem na materiale. Więc kiedy się rozpryskujemy, dosłownie mamy widżet Material, który robi to splash. Jeśli masz coś na wierzchu Materiału, rozpryskujemy się pod tym i nie możesz tego zobaczyć.

Chciałem dodać widżet „MaterialImage”, który koncepcyjnie drukuje również swój obraz w materiale, tak aby plamy były nad obrazem. Moglibyśmy mieć MaterialDecoration, który robi coś podobnego do dekoracji. Albo możemy poprosić o dekorację samego Materiału. W tej chwili przybiera kolor, ale możemy to rozszerzyć na całą dekorację. Nie jest jednak jasne, czy posiadanie materiału z gradientem jest naprawdę zgodne ze specyfikacją materiału, więc nie jestem pewien, czy powinniśmy to zrobić.

Na krótką metę, jeśli potrzebujesz tylko obejścia tego problemu, możesz umieścić materiał na wierzchu pojemnika, z materiałem ustawionym na typ „przezroczystości”, a następnie dobrze włożyć atrament.

--hixie

Aktualizacja: Hixie połączyła w zeszłym roku nowe rozwiązanie Ink. Atrament zapewnia wygodny sposób na rozpryskiwanie się po obrazach.

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

Uwaga: nie testowałem nowego widżetu Ink. Skopiowałem kod z ink_paint_test.dart i dokumenty klasy 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
Możesz po prostu nałożyć kolor na Materialsiebie i pominąć Container.
Herohtar

1
Doszedłem do wniosku, że CopsOnRoad opublikował swoją odpowiedź.
user1462442

1
@KoenVanLooveren Wypróbuj odpowiedź CopsOnRoad. Nie edytowałem swojego rozwiązania, ponieważ rozwiązanie CopsOnRoad jest dość eleganckie
user1462442

Oto, czego użyłem po refaktoryzacji: D dzięki
Koen Van Looveren 22.04.19

w moim przypadku był to kształt kontenera, dzięki za rozwiązanie
Mohammad Ersan

106

Wynik:

wprowadź opis obrazu tutaj


Po prostu użyj Inkwidżetu opakowanego w plik InkWell.

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

Źródło potwierdza krok 3: github.com/flutter/flutter/blob/… W każdym module obsługi sprawdzają, czy wywołanie zwrotne jest dostępne, w przeciwnym razie nic się nie dzieje.
Nightking

@CopsOnRoad, czy mogę prosić o pytanie związane z trzepotaniem: stackoverflow.com/questions/60539378/… ?
Istiaque Ahmed

Jeśli przez pełny kod masz na myśli przykład, który podałeś, to tak. Uważam, że to rozwiązanie> stackoverflow.com/a/58556613/12140067
Chris,

@Chris Myślę, że możesz mieć jakieś zakłócenia Theme„lub Material”, ponieważ ten kod działa przez cały dzień.
CopsOnRoad

1
to jedyne rozwiązanie zadziałało dla mnie
easazade

24

InkWell () nigdy nie pokaże efektu tętnienia, dopóki nie dodasz

onTap : () {} 

lub jakiekolwiek wywołania zwrotne, takie jak onDoubleTap, onLongPress itp.

parametr wewnątrz InkWell, ponieważ zaczyna nasłuchiwać twoich dotknięć tylko po określeniu tego parametru.


Tak, zrobiłem i to prawda. Sprawdź źródło: github.com/flutter/flutter/blob/… W każdym module obsługi sprawdzają, czy wywołanie zwrotne jest dostępne, w przeciwnym razie nic się nie dzieje.
Nightking

17
  1. Widget InkWell musi mieć jako przodek widget Material, w przeciwnym razie nie będzie mógł wyświetlać efektów. Na przykład:

    Material(
      child : InkWell(
        child : .....
    
  2. musisz dodać onTapmetodę, aby zobaczyć rzeczywiste efekty jako podobne

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

Przejdźmy do głównych punktów, zobacz kilka przykładów poniżej i spróbuj zrozumieć rzeczywiste koncepcje InkWell.

  • W poniższym przykładzie Materiał jest rodzicem InkWell z onTap, ale nadal nie działa. Spróbuj zrozumieć jego koncepcję. Powinieneś zapewnić margines do kontenera lub innego widżetu, aby pokazać efekty. Właściwie poniższy kod działa dobrze, ale nie możemy go zobaczyć, ponieważ nie dostarczyliśmy żadnego marginesu ani wyrównania, więc nie ma miejsca na pokazanie efektów.

    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,
            ),  
          ),
        ),
      );
    }
    
  • Poniższy przykład pokazuje efekty InkWell tylko do góry, ponieważ zapewniamy spację {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,
            ),
          ),
        ),
      );
    }
    
  • Poniżej exp. pokaż efekty na całej stronie, ponieważ środek tworzy marginesy z każdej strony. Wyśrodkuj swój widżet podrzędny z góry, z lewej, z prawej i z dołu.

    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

Lepszym sposobem jest użycie Inkwidżetu zamiast dowolnego innego widżetu.

Zamiast definiować colorwewnątrz kontenera, możesz zdefiniować go w Inksamym widgecie.

Poniższy kod zadziała.

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

Nie zapomnij dodać litery a onTap: () {}w przeciwnym razie InkWellnie pokaże to również efektu tętnienia.


4

Znalazłem dla siebie to rozwiązanie. Myślę, że to może ci pomóc:

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

Colorjest przekazywany do widżetu Materiał. Jest to domyślny kolor Twojego widżetu. Możesz dostosować kolor efektu tętnienia za pomocą splashColorwłaściwości Inkwell.


3

To najlepszy sposób, jaki znalazłem i używam go zawsze. Możesz tego spróbować.

  • Owiń swój WidgetzInkWell
  • Owiń za InkWellpomocąMaterial
  • W każdym razie ustaw krycie na 0%. na przykład: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

Napotkałem ten sam problem, próbując utworzyć naprzemienny kolor InkWell w ListView. W tym konkretnym przypadku istnieje proste rozwiązanie: zawiń zamienniki w pojemniku, który używa przeważnie przezroczystej zmiany odcienia / jasności - animacja dotykowa InkWell będzie nadal widoczna pod nim. Nie potrzeba żadnego materiału. Zwróć uwagę, że podczas próby obejścia tego problemu za pomocą Materal występują inne problemy - np. Zastąpi on DefaultTextStyle, którego używasz, domyślnym (instaluje AnimatedDefaultTextStyle), co jest ogromnym problemem.


2

To działa dla mnie:

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

Po wypróbowaniu wielu odpowiedzi tutaj, była to kombinacja:

  1. Oprawa splashColor
  2. owijanie InkWellwMaterial(color: Colors.white.withOpacity(0.0), ..)

Dzięki odpowiedziom tutaj, które dają te 2 punkty


1

Po dodaniu onTap:(){}słuchacza efekt ripple powinien działać dobrze. Nie działa, jeśli używasz BoxShadow()w InkWell()widgecie.


To jest sztuczka. Ripple nie będzie działać bez onTap (). Dzięki stary!
Hardik Joshi

0

Uderzył mnie podobny problem podczas dodawania Inkwell do istniejącego złożonego Widgetu z Pojemnikiem owijającym BoxDecoration kolorem. Dodając materiał i kałamarz w sposób sugerowany, kałamarz wciąż był zasłonięty dekoracją pudełka, więc po prostu sprawiłem, że kolor BoxDecoration był nieco nieprzejrzysty, co pozwoliło zobaczyć kałamarz


0

Rozwiązanie dla okrągłych widżetów wykonaj jak poniżej:

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

Dla mnie to był kolejny problem. InkWell nie pokazywał efektu tętnienia, gdy jako parametr mojego widżetu zdefiniowano poniżej funkcję onTap.

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

Nie wiem jaka jest różnica, ale następny kod działa dobrze.

onTap: (){ onTapItem(result); },
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.