简体   繁体   English

在堆栈颤动中使页面下方可点击

[英]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?如何使页面下方可点击?

在此处输入图片说明

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(),
            ],
          ),
        ),
      ),
    );

What you're looking for is IgnorePointer .您正在寻找的是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.我建议将其作为堆栈中较低项目的一部分,然后在断头台关闭时设置 IgnorePointer 的 ignoring ignoring = true

Note that there might be a 'better' way of implementing the guillotine menu using PageRoutes.请注意,使用 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;
}

If you have a widget with no interaction and want to make it clickable use the GestureDetector widget as parent, you can see the example in the link.如果您有一个没有交互的小部件并希望使其可点击,请使用GestureDetector小部件作为父小部件,您可以在链接中查看示例。

--- edit - - 编辑

This answer helps you when you need to make a widget without interaction have some, not exactly what this question is talk about, honest mistake but i could help others..当你需要制作一个没有交互的小部件时,这个答案可以帮助你有一些,不完全是这个问题所谈论的,诚实的错误,但我可以帮助其他人..

这是一个堆栈,使用手势检测器的 onTapDown,它在浮动操作按钮中不可用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM