InkWell не показує ефекту брижі


96

При натисканні на контейнер спрацьовує onTap()обробник, але ефект сплеску фарби не відображається.

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

Я намагався покласти InkWellвсередину всередину Container, а також марно.

Відповіді:


152

Я думаю, що додавання кольору в контейнер покриває ефект чорнила

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

Здається, цей код працює

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

просто клацніть середній квадрат.

Редагувати: я знайшов звіт про помилку. https://github.com/flutter/flutter/issues/3782

Це насправді, як очікувалось, хоча нам слід оновити документи, щоб зробити це зрозумілішим.

Те, що відбувається, це те, що специфікація Матеріал говорить, що бризки насправді є чорнилом на Матеріалі. Отже, коли ми плескаємось, ми робимо те, що буквально маємо віджет "Матеріал", який робить сплеск. Якщо у вас є щось поверх Матеріалу, ми виплескуємо під нього, і ви цього не бачите.

Я хотів додати віджет "MaterialImage", який також концептуально друкує своє зображення у Матеріал, щоб тоді бризки були над зображенням. Ми могли б мати MaterialDecoration, який робить щось подібне для прикраси. Або ми могли б мати сам матеріал взяти прикрасу. Зараз він приймає колір, але ми могли б поширити це на прийняття цілого прикраси. Незрозуміло, чи насправді сумісно зі специфікацією матеріалу мати матеріал з градієнтом, тому я не впевнений, чи варто це робити.

У короткій перспективі, якщо вам потрібен лише обхідний шлях, ви можете покласти Матеріал зверху на контейнер, при цьому матеріал має використовувати тип «прозорість», а потім добре вкласти туди чорнило.

--хіксі

Оновлення: Hixie об’єднала нове рішення Ink минулого року. Чорнило забезпечує зручний спосіб розбризкування зображень.

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

Зверніть увагу: Я не тестував новий віджет Ink. Я впорався з кодом ink_paint_test.dart та документами Ink class

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
Ви можете просто нанести колір на Materialсебе і залишити поза Container.
Herohtar

1
Я якось зрозумів, коли CopsOnRoad опублікував свою відповідь.
user1462442

1
@KoenVanLooveren Спробуйте відповідь CopsOnRoad. Я не редагував своє рішення, оскільки рішення CopsOnRoad досить елегантне
user1462442

Це те, що я використав після деякого рефакторингу: D, спасибі
Коен Ван Ловерен

у моєму випадку це була форма контейнера, дякую за рішення
Мохаммад Ерсан

106

Вихід:

введіть тут опис зображення


Просто використовуйте Inkвіджет, загорнутий у InkWell.

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

Джерело підтверджує крок 3: github.com/flutter/flutter/blob/ ... У кожному обробнику вони перевіряють, чи доступний зворотний дзвінок, інакше нічого не відбувається.
Nightking

@CopsOnRoad, чи можу я попросити вас задати тут питання, пов'язане з трепетом: stackoverflow.com/questions/60539378/… ?
Істіаке Ахмед

Якщо під повним кодом ви маєте на увазі приклад, який ви дали, тоді так. Я знайшов це рішення> stackoverflow.com/a/58556613/12140067
Кріс

Я думаю , @ Кріс Ви могли б бути з якими - то Theme«або Material» перешкодами s, тому що цей код працює весь день.
CopsOnRoad

1
це єдине рішення, яке спрацювало для мене
easazade

24

InkWell () ніколи не буде показувати ефект пульсації, поки ви не додасте

onTap : () {} 

або будь-який із зворотних викликів, таких як onDoubleTap, onLongPress тощо.

всередині InkWell, коли він починає слухати ваші крани лише тоді, коли ви вказуєте цей параметр.


Так, я зробив, і це правда. Перевірте джерело: github.com/flutter/flutter/blob/ ... У кожному обробнику вони перевіряють, чи доступний зворотний дзвінок, інакше нічого не відбувається.
Nightking

17
  1. Віджет InkWell повинен мати віджет "Матеріал" як попередника, інакше він не може відображати ефекти. Наприклад:

    Material(
      child : InkWell(
        child : .....
    
  2. Вам потрібно додати onTapметод, щоб побачити фактичні ефекти як подібні

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

Давайте підійдемо до основних моментів, побачимо кілька прикладів нижче і спробуємо зрозуміти фактичні концепції InkWell.

  • У наведеному нижче прикладі Material є батьком InkWell з onTap, але він все ще не працює. Будь ласка, спробуйте зрозуміти концепцію цього. Ви повинні надати деяке поле для контейнера або іншого віджета, щоб показати ефекти. Насправді нижче код працює нормально, але ми не бачимо, оскільки ми не надали жодного поля або вирівнювання, тому в ньому немає місця для показу ефектів.

    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,
            ),  
          ),
        ),
      );
    }
    
  • Нижче приклад показує ефекти InkWell лише вгору, оскільки ми надаємо простір {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,
            ),
          ),
        ),
      );
    }
    
  • Нижче досвіду. показати ефекти на всій сторінці, тому що центр створює поля з усіх боків. Вирівняйте його дочірній віджет по центру зверху, ліворуч, праворуч і знизу.

    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

Кращий спосіб - використовувати Inkвіджет замість будь-якого іншого віджета.

Замість того, щоб визначати colorвнутрішній контейнер, ви можете визначити його у Inkсамому віджеті.

Нижче код буде працювати.

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

Не забудьте додати a onTap: () {}в InkWellіншому, це також не покаже ефекту пульсації.


4

Я знайшов це рішення для мене. Я думаю, це може вам допомогти:

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

Colorнадається віджету Material. Це колір вашого віджета за замовчуванням. Ви можете налаштувати колір ефекту брижі за допомогою splashColorвластивості Каламар.


3

Це найкращий спосіб, який я знайшов і використовую завжди. Ви можете спробувати.

  • оберніть WidgetзInkWell
  • обруч InkWellзMaterial
  • В будь-якому випадку встановіть непрозорість 0%. наприклад: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

Я зіткнувся з цією ж проблемою, намагаючись створити змінний колір InkWell's у ListView. У цьому конкретному випадку є просте рішення: загорніть альтернативи в контейнер, який використовує переважно прозорі зміни відтінку / яскравості - анімація дотику InkWell все одно буде видно під ним. Немає необхідного матеріалу. Зверніть увагу, що при спробі обійти це за допомогою Materal є інші проблеми - наприклад, він замінить DefaultTextStyle, який ви використовуєте за замовчуванням (він встановлює AnimatedDefaultTextStyle), що є великим болем.


2

Це працює для мене:

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

Спробувавши тут багато відповідей, це було поєднання:

  1. Налаштування splashColor
  2. обгортання InkWellвMaterial(color: Colors.white.withOpacity(0.0), ..)

Завдяки відповідям тут, які роблять ці 2 пункти


1

Після того, як ви додали onTap:(){}слухач, ефект пульсації повинен працювати нормально. Це не працює, якщо ви використовуєте BoxShadow()у InkWell()віджеті.


У цьому фокус. Ripple не працюватиме без onTap (). Дякую людино!
Хардік Джоші

0

Мене вразила подібна проблема із додаванням Чорнильниці до існуючого складного віджета з контейнером, який обертає BoxDecoration кольором. Додавши Матеріал та Чорнильницю так, як передбачалося, Чорнильниця все ще була затемнена BoxDecoration, тому я просто зробив колір BoxDecoration трохи непрозорим, що дозволило побачити Чорнильницю


0

Рішення кругових віджетів зробіть, як показано нижче:

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

Для мене це була інша проблема. InkWell не виявляв ефекту пульсації, коли у мене була функція onTap як параметр мого віджета, визначений, як показано нижче.

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

Я не знаю, в чому різниця, але наступний код працює добре.

onTap: (){ onTapItem(result); },
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.