InkWell không hiển thị hiệu ứng gợn sóng


97

Nhấn vào hộp chứa sẽ kích hoạt trình onTap()xử lý nhưng không hiển thị bất kỳ hiệu ứng bắn mực nào.

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

Tôi đã thử đặt cả InkWellbên trong Containernhưng vô ích.

Câu trả lời:


154

Tôi nghĩ rằng việc thêm màu vào hộp chứa sẽ che phủ hiệu ứng mực

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

Mã này có vẻ hoạt động

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

chỉ cần nhấp vào hình vuông ở giữa.

Chỉnh sửa: Tôi đã tìm thấy báo cáo lỗi. https://github.com/flutter/flutter/issues/3782

Điều này thực sự như mong đợi, mặc dù chúng tôi nên cập nhật tài liệu để làm cho nó rõ ràng hơn.

Điều đang xảy ra là thông số Vật liệu nói rằng các tia nước thực sự là mực trên Vật liệu. Vì vậy, khi chúng tôi giật gân, những gì chúng tôi làm là chúng tôi thực sự có tiện ích Vật liệu thực hiện giật gân. Nếu bạn có thứ gì đó ở trên Vật liệu, chúng tôi sẽ bắn tung tóe bên dưới nó và bạn không thể nhìn thấy nó.

Tôi đã muốn thêm một widget "MaterialImage", nó cũng in hình ảnh của nó vào Material một cách khái niệm để sau đó các tia sáng sẽ tràn qua hình ảnh. Chúng ta có thể có một MaterialDecoration làm một cái gì đó tương tự cho một trang trí. Hoặc chúng ta có thể để Vật liệu tự trang trí. Ngay bây giờ nó cần một màu sắc, nhưng chúng tôi có thể mở rộng điều đó sang việc trang trí toàn bộ. Tuy nhiên, không rõ liệu có thực sự tương thích với vật liệu thông số kỹ thuật hay không, vì vậy tôi không chắc liệu chúng ta có nên làm điều đó hay không.

Trước mắt, nếu bạn chỉ cần một giải pháp khác, bạn có thể đặt Vật liệu lên trên hộp đựng, với vật liệu được đặt để sử dụng loại "trong suốt", sau đó đổ mực vào bên trong hộp đó.

--hixie

Cập nhật: Hixie đã hợp nhất một giải pháp Ink mới vào năm ngoái. Ink cung cấp một cách thuận tiện để hiển thị hình ảnh.

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

Xin lưu ý: Tôi đã không thử nghiệm tiện ích Ink mới. Tôi đã đối phó mã từ ink_paint_test.dart và tài liệu lớp 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
Bạn chỉ có thể đặt màu vào Materialchính nó và bỏ đi Container.
Herohtar

1
Tôi đã đoán được khi CopsOnRoad đăng câu trả lời của anh ấy.
user1462442

1
@KoenVanLooveren Hãy thử câu trả lời CopsOnRoad. Tôi không chỉnh sửa giải pháp của tôi bởi vì giải pháp CopsOnRoad là khá thanh lịch
user1462442

Đó là những gì tôi sử dụng sau khi một số refactoring: D thanks
Koen Van Looveren

trong trường hợp của tôi đó là hình dạng container, nhờ fo giải pháp
Mohammad Ersan

106

Đầu ra:

nhập mô tả hình ảnh ở đây


Đơn giản chỉ cần sử dụng Inkwidget được bao bọc trong một InkWell.

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

Nguồn xác nhận bước 3: github.com/flutter/flutter/blob/… Trong mỗi trình xử lý, họ kiểm tra xem lệnh gọi lại có khả dụng hay không, nếu không sẽ không có gì xảy ra.
Đi đêm

@CopsOnRoad, tôi có thể hỏi bạn một câu hỏi liên quan đến sự cố ở đây không: stackoverflow.com/questions/60539378/… ?
Istiaque Ahmed

Nếu theo mã đầy đủ, bạn có nghĩa là ví dụ bạn đã đưa ra thì có. Tôi thấy đây là giải pháp> stackoverflow.com/a/58556613/12140067
Chris

@ Chris Tôi nghĩ rằng bạn có thể gặp phải một số Theme'hay Material' sự can thiệp của, bởi vì mã này hoạt động suốt cả ngày.
CopsOnRoad

1
đây là giải pháp duy nhất làm việc cho tôi
easazade

24

InkWell () sẽ không bao giờ hiển thị hiệu ứng gợn sóng cho đến khi bạn thêm

onTap : () {} 

hoặc bất kỳ lệnh gọi lại nào như onDoubleTap, onLongPress, v.v.

bên trong InkWell vì nó chỉ bắt đầu nghe các vòi của bạn khi bạn chỉ định thông số này.


Vâng, tôi đã làm, và nó đúng. Kiểm tra nguồn: github.com/flutter/flutter/blob/… Trong mỗi trình xử lý, họ kiểm tra xem lệnh gọi lại có khả dụng hay không, nếu không sẽ không có gì xảy ra.
Đi đêm

18
  1. Tiện ích InkWell phải có tiện ích Material làm tổ tiên nếu không nó không thể hiển thị các hiệu ứng. Ví dụ:

    Material(
      child : InkWell(
        child : .....
    
  2. bạn phải thêm onTapphương pháp để xem các hiệu ứng thực tế như

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

Hãy cùng đến với những điểm chính, xem một số ví dụ dưới đây và cố gắng hiểu các khái niệm thực tế của InkWell.

  • Trong ví dụ dưới đây, Material là cha của InkWell với onTap nhưng nó vẫn không hoạt động. Hãy cố gắng hiểu khái niệm của nó. Bạn nên cung cấp một số lợi nhuận cho vùng chứa hoặc tiện ích con khác để hiển thị các hiệu ứng. Trên thực tế, mã bên dưới hoạt động tốt nhưng chúng tôi không thể nhìn thấy vì chúng tôi không cung cấp bất kỳ lề hoặc căn chỉnh nào nên nó không có không gian để hiển thị các hiệu ứng.

    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,
            ),  
          ),
        ),
      );
    }
    
  • Ví dụ dưới đây chỉ hiển thị các hiệu ứng InkWell trở lên vì chúng tôi cung cấp khoảng trắng {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,
            ),
          ),
        ),
      );
    }
    
  • Dưới điểm kinh nghiệm. hiển thị các hiệu ứng trong tất cả các trang vì tâm tạo lề từ tất cả các bên. Căn giữa tiện ích con từ trên, trái, phải và dưới cùng.

    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

Một cách tốt hơn là sử dụng Inkwidget này thay vì bất kỳ widget nào khác.

Thay vì xác định vùng colorchứa bên trong, bạn có thể xác định nó trong Inkchính widget.

Mã dưới đây sẽ hoạt động.

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

Đừng quên thêm một onTap: () {}trong InkWellkhác nó sẽ không hiển thị hiệu ứng gợn sóng.


4

Tôi đã tìm thấy giải pháp này cho tôi. Tôi nghĩ nó có thể giúp bạn:

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

Colorđược trao cho tiện ích Vật liệu. Nó là màu mặc định của widget của bạn. Bạn có thể điều chỉnh màu sắc của hiệu ứng gợn sóng bằng cách sử dụng splashColorthuộc tính của Inkwell.


3

Đây là cách tốt nhất mà tôi tìm ra và sử dụng nó luôn luôn. Bạn có thể thử nó.

  • Bọc của bạn WidgetvớiInkWell
  • Bọc InkWellbằngMaterial
  • Đặt opacity 0% bằng mọi cách. ví dụ: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");},
      ),
    )
    

3

Điều này đang làm việc cho tôi:

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

Sau khi thử nhiều câu trả lời ở đây, nó là sự kết hợp của:

  1. Cài đặt splashColor
  2. Gói InkWelltrongMaterial(color: Colors.white.withOpacity(0.0), ..)

Nhờ câu trả lời ở đây mà tạo nên 2 điểm đó


2

Tôi đã gặp phải vấn đề tương tự này khi cố gắng tạo màu xen kẽ của InkWell trong ListView. Trong trường hợp cụ thể đó, có một giải pháp đơn giản: bọc các vật liệu thay thế trong Hộp chứa sử dụng sự thay đổi độ sáng / màu chủ yếu trong suốt - hoạt ảnh cảm ứng InkWell sẽ vẫn hiển thị bên dưới nó. Không cần vật liệu. Lưu ý rằng có những vấn đề khác khi cố gắng giải quyết vấn đề này với Materal - ví dụ: nó sẽ ghi đè DefaultTextStyle mà bạn đang sử dụng bằng mặc định (nó cài đặt AnimatedDefaultTextStyle).


1

Sau khi bạn thêm trình onTap:(){}nghe, hiệu ứng gợn sóng sẽ hoạt động tốt. Nó không hoạt động nếu bạn sử dụng BoxShadow()với trong InkWell()widget.


Đó là thủ thuật. Ripple sẽ không hoạt động nếu không có onTap (). Cảm ơn anh bạn!
Hardik Joshi

0

Tôi đã gặp phải một vấn đề tương tự khi thêm Inkwell vào một Widget phức tạp hiện có với Container bao bọc BoxDecoration bằng màu sắc. Bằng cách thêm Material và Inkwell theo cách gợi ý, Inkwell vẫn bị BoxDecoration che khuất, vì vậy tôi chỉ làm cho màu của BoxDecoration hơi mờ đục để có thể nhìn thấy Inkwell


0

Giải pháp cho các widget tròn, làm như sau:

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

Đối với tôi đó là một vấn đề khác. InkWell không hiển thị hiệu ứng gợn sóng khi tôi có chức năng onTap làm thông số của tiện ích con của tôi được xác định như bên dưới.

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

Tôi không biết sự khác biệt là gì, nhưng mã tiếp theo đang hoạt động tốt.

onTap: (){ onTapItem(result); },
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.