Jiehfeng
Jiehfeng

Reputation: 1027

Show InkWell Ripple with OpenContainer animation?

Working code here:

                  OpenContainer(
                    openBuilder: (context, action) => const SelectedProduct(),
                    closedBuilder: (context, action) => Card(),
                  ),
                  /*Positioned.fill(
                    child: Material(
                        color: Colors.transparent,
                        child: InkWell(
                          onTap: () {
                            context.read<DownloadImages>().currentProduct = i;
                            context.read<DownloadImages>().notifyListeners();
                            //Navigator.pushNamed(context, '/seven');
                          },
                          splashColor: Colors.transparent,
                        )
                    ),
                  ),*/

The commented out code is what I want to achieve. Ignore the other variables I set in onTap, that is not my focus, but my focus is to show this InkWell ripple when I click on the Card, or while holding it in place, and only then start the openBuilder.

What happens is when the InkWell is in place, the InkWell overtakes the OpenContainer builders and only its onTap gets used. How do I ignore InkWell's onTap for instance, and only get its animation to work along with OpenContainer?

Note: Both of these are within a Stack widget.


Complete code for testing:

import 'package:flutter/material.dart'
import 'package:animations/animations.dart';

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TestPage',
      home: const Products(),
    );
  }
}

class Products extends StatefulWidget {
  const Products({Key? key}) : super(key: key);

  @override
  State<Products> createState() => _ProductsState();
}

class _ProductsState extends State<Products> {

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {
        return Future.value(false);
      },
      child: Scaffold(
        body: Container(
          alignment: Alignment.center,
          child: SingleChildScrollView(
            padding:
            const EdgeInsets.only(top: 20, bottom: 20, left: 15, right: 15),
            child: Column(
            children: [
              Stack(
                children: [
                  OpenContainer(
                    openBuilder: (context, action) => const SelectedProduct(),
                    closedBuilder: (context, action) => Card(
                      child: Text('Test Card')
                    ),
                  ),
                  Positioned.fill(
                    child: Material(
                        color: Colors.transparent,
                        child: InkWell(
                          onTap: () {
                            //Navigator.pushNamed(context, '/seven');
                          },
                          splashColor: Colors.transparent,
                        )
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 10),
            ],
          )
          ),
        ),
      ),
    );
  }
}

Upvotes: 0

Views: 854

Answers (2)

iqfareez
iqfareez

Reputation: 887

Easy! Wrap the closedBuilder widget with InkWell and use the builder's action parameter as the onTap function to manually triggers the container open. Also, sets the tappable parameter to false.

Example code:

OpenContainer(
  tappable: false,
  openBuilder: (context, action) {
    return const Widget2();
  },
  closedBuilder: (context, action) {
    return InkWell(
      onTap: action, // this will open the container
      child: Widget1(),
    );
  },
);

Demo video:

enter image description here

Upvotes: 0

Md. Yeasin Sheikh
Md. Yeasin Sheikh

Reputation: 63604

The widget priority, bottom to top for tap event. Place tappable widget at bottom and background widgets at top.

If you swap the location, it will work.

Stack(
    children: [
      Positioned.fill(
        child: Material(
          color: Colors.transparent,
          child: InkWell(
            onTap: () {
              //Navigator.pushNamed(context, '/seven');
            },
            splashColor: Colors.transparent,
          ),
        ),
      ),
      OpenContainer(
        tappable: true,
        openBuilder: (context, action) => Container(
          color: Colors.green,
          height: 200,
          width: 200,
        ),
        closedBuilder: (context, action) => Card(
          child: Text('Test Card'),
        ),
      ),
    ],
  ),

Without Stack

Material(
    color: Colors.green,
    child: Ink(
      width: 200,
      height: 200,
      child: InkWell(
        onTap: () {},
        child: Center(
          child: OpenContainer(
            // closedColor: Colors.pink, or card color
            openBuilder: (context, action) =>
                const Text("Open card"),
            closedBuilder: (context, action) =>
                Card(child: Text('Test Card')),
            // ),
          ),
        ),
      ),
    ))

Upvotes: 1

Related Questions