简体   繁体   English

Flutter:Hero 小部件、Navigation 2.0 和 Provider 无法正常协同工作

[英]Flutter: Hero widget, Navigation 2.0 and Provider are not working properly together

I tried to use Hero widget with ChangeNotifierProvider and the new Navigation 2.0 system.我尝试将Hero小部件与ChangeNotifierProvider和新的 Navigation 2.0 系统一起使用。 But I am facing issues there.但我在那里面临问题。 The same code works when changeNotifier is not used.不使用changeNotifier时,相同的代码有效

The issue I am facing is, after popping the second page W2, the text (ie, hero's child) from the first page disappearing.我面临的问题是,在弹出第二页 W2 后,第一页的文本(即英雄的孩子)消失了。

Below is the complete code.下面是完整的代码。 runApp(HeroTestApp2()) is working as usual. runApp(HeroTestApp2())正常工作。 But I would love to make the first approach working.但我很想使第一种方法起作用。 Please help.请帮忙。

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

main(List<String> args) {
  runApp(HeroTestApp());
}

class MyModel extends ChangeNotifier {
  bool _go = false;
  bool get go => _go;
  set go(bool go) {
    _go = go;
    notifyListeners();
  }
}

class HeroTestApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyModel>(
      create: (context) => MyModel(),
      builder: (context, _) {
        final state = context.watch<MyModel>();
        return MaterialApp(
          home: Navigator(
            pages: [
              MaterialPage(child: W1(onTapped: null)),
              if (state.go) MaterialPage(child: W2()),
            ],
            onPopPage: (route, result) {
              if (!route.didPop(result)) return false;
              state.go = false;
              return true;
            },
            observers: [HeroController()],
          ),
        );
      },
    );
  }
}

class HeroTestApp2 extends StatefulWidget {
  @override
  _HeroTestApp2State createState() => _HeroTestApp2State();
}

class _HeroTestApp2State extends State<HeroTestApp2> {
  bool go = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Navigator(
        pages: [
          MaterialPage(
            child: W1(onTapped: () {
              setState(() {
                go = true;
              });
            }),
          ),
          if (go) MaterialPage(child: W2()),
        ],
        onPopPage: (route, result) {
          if (!route.didPop(result)) return false;
          go = false;
          return true;
        },
        observers: [HeroController()],
      ),
    );
  }
}

class W1 extends StatelessWidget {
  final void Function() onTapped;

  const W1({Key key, this.onTapped}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTapped ??
          () => context.read<MyModel>().go = true,
      child: Scaffold(
        appBar: AppBar(),
        body: Container(
          alignment: Alignment.topRight,
          child: Hero(
            tag: "topic",
            child: DefaultTextStyle(
              style: TextStyle(
                  fontSize: 40,
                  decoration: TextDecoration.none,
                  color: Colors.blue),
              child: Text(
                "data",
                style: TextStyle(fontSize: 40),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class W2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        alignment: Alignment.bottomLeft,
        child: Hero(
          tag: "topic",
          child: DefaultTextStyle(
            style: TextStyle(
                fontSize: 140,
                decoration: TextDecoration.none,
                color: Colors.blue),
            child: Text(
              "data",
            ),
          ),
        ),
      ),
    );
  }
}

Ok, I fount the answer.好的,我找到了答案。

It was the observers: [HeroController()],observers: [HeroController()],

Each time the state changes, the hole tree was rebuilding along with the HeroController.每次状态改变时,洞树都会与 HeroController 一起重建。 The solution is to define the HeroController above the changeNotifier:解决办法是在changeNotifier之上定义HeroController:

class HeroTestApp extends StatelessWidget {
  final heroC = HeroController();

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyModel>(
      create: (context) => MyModel(),
      builder: (context, _) {
        final state = context.watch<MyModel>();
        return MaterialApp(
          home: Navigator(
            pages: [
              MaterialPage(child: W1(onTapped: null)),
              if (state.go) MaterialPage(child: W2()),
            ],
            onPopPage: (route, result) {
              if (!route.didPop(result)) return false;
              state.go = false;
              return true;
            },
            observers: [heroC],
          ),
        );
      },
    );
  }
}

Thankyou.谢谢你。

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

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