我如何使用Hero拥有相同的页面目标

时间:2019-02-22 04:01:25

标签: dart flutter

我正在尝试制作一个扑朔迷离的应用程序。这是一个可以创建容器的应用程序。然后,当您按这些容器时,它将打开一个页面。因此,我尝试将Hero用于无限可创建的容器。这是我想出的:

import 'package:flutter/material.dart';

void main() => runApp(MainPage());

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            backgroundColor: Colors.white,
            body: Column(children: <Widget>[
              Body(),
            ])));
  }
}

class Body extends StatefulWidget {
  @override
  _BodyState createState() => _BodyState();
}

class _BodyState extends State<Body> {
  final String open1 = 'open';

  int count = 1;

  @override
  Widget build(BuildContext context) {
    List cards = List.generate(count, (int i) => RCard(count));

    return Expanded(
        child: Container(
            child: NotificationListener<OverscrollIndicatorNotification>(
                onNotification: (OverscrollIndicatorNotification overscroll) {
                  overscroll.disallowGlow();
                },
                child: PageView.builder(
                    reverse: true,
                    pageSnapping: false,
                    controller: PageController(viewportFraction: 0.85),
                    itemCount: count,
                    itemBuilder: (context, i) {
                      if (i == 0) {
                        return GestureDetector(
                            onTap: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) => Page(
                                          open: open1,
                                        )),
                              );
                              count++;
                            },
                            child: Hero(
                                tag: open1,
                                child: Padding(
                                    padding: EdgeInsets.only(
                                        left:
                                            MediaQuery.of(context).size.height *
                                                0.015,
                                        right:
                                            MediaQuery.of(context).size.height *
                                                0.015,
                                        top: MediaQuery.of(context).size.width *
                                            0.08,
                                        bottom:
                                            MediaQuery.of(context).size.width *
                                                0.15),
                                    child: Material(
                                        borderRadius:
                                            BorderRadius.circular(40.0),
                                        color: Colors.white,
                                        elevation: 8.0,
                                        child: InkWell(
                                          child: Column(
                                              mainAxisAlignment:
                                                  MainAxisAlignment.center,
                                              children: <Widget>[
                                                Icon(
                                                  Icons.add,
                                                  size: 30.0,
                                                  color: Colors.black,
                                                )
                                              ]),
                                        )))));
                      } else {
                        return cards[i];
                      }
                    }))));
  }
}

class RCard extends StatefulWidget {
  final int count;

  RCard(this.count);

  @override
  RCardState createState() => RCardState();
}

class RCardState extends State<RCard> {
  int count;
  String open2;
  @override
  void initState() {
    super.initState();
    open2 = 'open$count';
    count = widget.count;
  }

  @override
  Widget build(BuildContext context) {
    return Hero(
      tag: open2,
      child: GestureDetector(
          onTap: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) => Page(
                        open: open2,
                      )),
            );
          },
          child: Padding(
            padding: EdgeInsets.only(
                left: MediaQuery.of(context).size.height * 0.015,
                right: MediaQuery.of(context).size.height * 0.015,
                top: MediaQuery.of(context).size.width * 0.08,
                bottom: MediaQuery.of(context).size.width * 0.15),
            child: Material(
                borderRadius: BorderRadius.circular(40.0),
                color: Colors.white,
                elevation: 8.0,
                child: Padding(
                  padding:
                      EdgeInsets.all(MediaQuery.of(context).size.width * 0.15),
                )),
          )),
    );
  }
}

class Page extends StatelessWidget {
  final String open;

  Page({this.open});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Hero(tag: open, child: Material()),
      onTap: () {
        Navigator.pop(context);
      },
    );
  }
}

但是,此代码仅在创建1个容器时有效。当我创建2个容器并按在它上面时,它给了我黑屏。我该如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

我发现您所需要做的就是删除列表“ cards”,并将“ cards [i]”方法更改为“ RCard(i)”。

import 'package:flutter/material.dart';

void main() => runApp(MainPage());

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            backgroundColor: Colors.white,
            body: Column(children: <Widget>[
              Body(),
            ])));
  }
}

class Body extends StatefulWidget {
  @override
  _BodyState createState() => _BodyState();
}

class _BodyState extends State<Body> {
  final String open1 = 'open';

  int count = 1;

  @override
  Widget build(BuildContext context) {

    return Expanded(
        child: Container(
            child: NotificationListener<OverscrollIndicatorNotification>(
                onNotification: (OverscrollIndicatorNotification overscroll) {
                  overscroll.disallowGlow();
                },
                child: PageView.builder(
                    reverse: true,
                    pageSnapping: false,
                    controller: PageController(viewportFraction: 0.85),
                    itemCount: count,
                    itemBuilder: (context, i) {
                      if (i == 0) {
                        return GestureDetector(
                            onTap: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) => Page(
                                          open: open1,
                                        )),
                              );
                              count++;
                            },
                            child: Hero(
                                tag: open1,
                                child: Padding(
                                    padding: EdgeInsets.only(
                                        left:
                                            MediaQuery.of(context).size.height *
                                                0.015,
                                        right:
                                            MediaQuery.of(context).size.height *
                                                0.015,
                                        top: MediaQuery.of(context).size.width *
                                            0.08,
                                        bottom:
                                            MediaQuery.of(context).size.width *
                                                0.15),
                                    child: Material(
                                        borderRadius:
                                            BorderRadius.circular(40.0),
                                        color: Colors.white,
                                        elevation: 8.0,
                                        child: InkWell(
                                          child: Column(
                                              mainAxisAlignment:
                                                  MainAxisAlignment.center,
                                              children: <Widget>[
                                                Icon(
                                                  Icons.add,
                                                  size: 30.0,
                                                  color: Colors.black,
                                                )
                                              ]),
                                        )))));
                      } else {
                        return RCard(i);
                      }
                    }))));
  }
}

class RCard extends StatefulWidget {
  final int count;

  RCard(this.count);

  @override
  RCardState createState() => RCardState();
}

class RCardState extends State<RCard> {
  int count;
  String open2;
  @override
  void initState() {
    super.initState();
    open2 = 'open$count';
    count = widget.count;
  }

  @override
  Widget build(BuildContext context) {
    return Hero(
      tag: open2,
      child: GestureDetector(
          onTap: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) => Page(
                        open: open2,
                      )),
            );
          },
          child: Padding(
            padding: EdgeInsets.only(
                left: MediaQuery.of(context).size.height * 0.015,
                right: MediaQuery.of(context).size.height * 0.015,
                top: MediaQuery.of(context).size.width * 0.08,
                bottom: MediaQuery.of(context).size.width * 0.15),
            child: Material(
                borderRadius: BorderRadius.circular(40.0),
                color: Colors.white,
                elevation: 8.0,
                child: Padding(
                  padding:
                      EdgeInsets.all(MediaQuery.of(context).size.width * 0.15),
                )),
          )),
    );
  }
}

class Page extends StatelessWidget {
  final String open;

  Page({this.open});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Hero(tag: open, child: Material()),
      onTap: () {
        Navigator.pop(context);
      },
    );
  }
}

答案 1 :(得分:0)

在一个类中,只能有一个具有相同标签值的Hero小部件。如果要同时发生两个以上的Hero动画,则必须为每个Hero小部件提供不同的标签值。

答案 2 :(得分:0)

每次创建tag时,请尝试赋予唯一的Hero值。黑屏错误很可能是因为两个或多个Hero元素获得相同的tag值。

例如,在itemBuilder: (context, i)内,您将在变量i中获得当前索引。您可以使用该索引来使tag的值唯一。

child: Hero(
  tag: open1 + "$i",
  child: /*Rest of your code*/
)

您可以执行类似的操作以确保所有tag元素的值都是唯一的。让我知道是否有帮助!