Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make clickable below page in stack flutter

I have just a stack that contains a guillotine menu and a list. But below page (list and fab) isn't clickable! First code is Main page, second code is books (below page) and third code is guillotine menu.
How can I make clickable below page?

enter image description here

main page

import 'package:firebase_example/Ui/Books.dart';
import 'package:firebase_example/Ui/GuillotineMenu.dart';
import 'package:flutter/material.dart';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final GlobalKey<ScaffoldState> _drawerKey = new GlobalKey();

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        top: false,
        bottom: false,
        child: new Container(
          child: new Stack(
            alignment: Alignment.topLeft,
            children: <Widget>[
              Books(),
              GuillotineMenu(),
            ],
          ),
        ),
      ),
    );
like image 644
ali meshkani Avatar asked Sep 04 '18 21:09

ali meshkani


1 Answers

What you're looking for is IgnorePointer. By using it you should be able to exclude your widget from hit testing (and so allow things under it to be touched instead).

You're going to have to be careful about how you implement the button that makes the guillotine menu open/close though. I'd advise making it a part of the item lower in the stack, and then setting IgnorePointer's ignoring = true when the guillotine is closed.

Note that there might be a 'better' way of implementing the guillotine menu using PageRoutes. That way you'd just be pushing/popping a new route on top of the existing navigator rather than having to maintain your own stack.

Here's the code:

class GuillotinePageRoute<T> extends PageRoute<T> {
  GuillotinePageRoute({
    @required this.builder,
    RouteSettings settings: const RouteSettings(),
    this.maintainState: true,
    bool fullscreenDialog: false,
  })  : assert(builder != null),
        super(settings: settings, fullscreenDialog: fullscreenDialog);

  final WidgetBuilder builder;

  @override
  final bool maintainState;

  @override
  Duration get transitionDuration => const Duration(milliseconds: 500);

  @override
  Color get barrierColor => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    final Widget result = builder(context);
    assert(() {
      if (result == null) {
        throw new FlutterError('The builder for route "${settings.name}" returned null.\n'
            'Route builders must never be null.');
      }
      return true;
    }());
    return result;
  }

  @override
  Widget buildTransitions(
      BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    MediaQueryData queryData = MediaQuery.of(context);

    var topInset = queryData.padding.top;

    Offset origin = Offset((kToolbarHeight / 2.0), topInset + (kToolbarHeight / 2.0));

    Curve curve = animation.status == AnimationStatus.forward ? Curves.bounceOut : Curves.bounceIn;
    var rotateTween = new Tween(begin: -pi / 2.0, end: 0.0);

    Cubic opacityCurve = Cubic(0.0, 1.0, 0.0, 1.0);

    return new AnimatedBuilder(
      animation: animation,
      child: child,
      builder: (context, child) {
        return Opacity(
          opacity: opacityCurve.transform(animation.value),
          child: Transform(
            transform: Matrix4.identity()..rotateZ(rotateTween.lerp(curve.transform(animation.value))),
            origin: origin,
            child: child,
          ),
        );
      },
    );
  }

  @override
  String get barrierLabel => null;
}

And using it in an example:

import 'dart:math';

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MenuPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(children: [
      AppBar(
        leading: new IconButton(icon: Icon(Icons.menu), onPressed: () => Navigator.pop(context)),
        elevation: 0.0,
      ),
      Expanded(
        child: Container(
          child: Center(
            child: Text(
              "Menu page!",
              style: TextStyle(color: Colors.white, decoration: TextDecoration.none),
            ),
          ),
          color: Colors.blue,
        ),
      ),
    ]);
  }
}

class MyHomePage extends StatelessWidget {
  void pushGuillotine(BuildContext context, WidgetBuilder builder) {
    Navigator.push(context, new GuillotinePageRoute(builder: builder));
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("This is a title"),
        leading: new RotatedBox(
          quarterTurns: -1,
          child: IconButton(icon: Icon(Icons.menu), onPressed: () => pushGuillotine(context, (context) => MenuPage())),
        ),
      ),
      body: Container(
        color: Colors.blueGrey,
        child: Center(
          child: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new Text(
                'This is the home page.',
              ),
              new Text(
                'Hello world!',
                style: Theme.of(context).textTheme.display1,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class GuillotinePageRoute<T> extends PageRoute<T> {
  GuillotinePageRoute({
    @required this.builder,
    RouteSettings settings: const RouteSettings(),
    this.maintainState: true,
    bool fullscreenDialog: false,
  })  : assert(builder != null),
        super(settings: settings, fullscreenDialog: fullscreenDialog);

  final WidgetBuilder builder;

  @override
  final bool maintainState;

  @override
  Duration get transitionDuration => const Duration(milliseconds: 500);

  @override
  Color get barrierColor => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    final Widget result = builder(context);
    assert(() {
      if (result == null) {
        throw new FlutterError('The builder for route "${settings.name}" returned null.\n'
            'Route builders must never be null.');
      }
      return true;
    }());
    return result;
  }

  @override
  Widget buildTransitions(
      BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    MediaQueryData queryData = MediaQuery.of(context);

    var topInset = queryData.padding.top;

    Offset origin = Offset((kToolbarHeight / 2.0), topInset + (kToolbarHeight / 2.0));

    Curve curve = animation.status == AnimationStatus.forward ? Curves.bounceOut : Curves.bounceIn;
    var rotateTween = new Tween(begin: -pi / 2.0, end: 0.0);

    Cubic opacityCurve = Cubic(0.0, 1.0, 0.0, 1.0);

    return new AnimatedBuilder(
      animation: animation,
      child: child,
      builder: (context, child) {
        return Opacity(
          opacity: opacityCurve.transform(animation.value),
          child: Transform(
            transform: Matrix4.identity()..rotateZ(rotateTween.lerp(curve.transform(animation.value))),
            origin: origin,
            child: child,
          ),
        );
      },
    );
  }

  @override
  String get barrierLabel => null;
}
like image 133
rmtmckenzie Avatar answered Sep 19 '22 11:09

rmtmckenzie