【问题标题】:Tabbar flutter error switching between page标签栏颤动错误在页面之间切换
【发布时间】:2020-02-18 22:06:12
【问题描述】:

在颤振创建标签栏并使用作为参考传递的列表浏览各个页面时,页面不再报告正确的数据

每个选项卡包含一个标题和一个字符串列表,这个列表显示在每个 TabView 中,但是浏览页面并不会显示正确的列表。

class _TabsFabDemoState extends State<TabsFabDemo>  with SingleTickerProviderStateMixin {

  @override
  Widget build(BuildContext context) {
  return MaterialApp(
    home: DefaultTabController(
      length: choices.length,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Tabbed AppBar'),
          bottom: TabBar(
            isScrollable: true,
            tabs: choices.map((Choice choice) {
              return Tab(
                text: choice.title,
                icon: Icon(choice.icon),
              );
            }).toList(),
          ),
        ),
        body: Column(
          children: <Widget>[
            GestureDetector(
              onTap: (){
                choices.add(Choice(title: 'CAR', icon: Icons.directions_car));
                setState(() {});
              },
              child: Container(
                height: 100.0,
                color: Colors.red,
              ),
            ),
            Expanded(
              child: TabBarView(
                children: choices.map((Choice choice) {
                  return Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Center(child: ListaLinkWidget(tab: choice)),
                  );
                }).toList(),
              ),
            ),
          ],
        ),
      ),
     ),
    );
  }
}

class Choice {
  Choice({this.title, this.icon});

  final String title;
  final IconData icon;
  List<String> liststring = new List();
}

List<Choice> choices = <Choice>[
  Choice(title: 'CAR', icon: Icons.directions_car),
  Choice(title: 'BICYCLE', icon: Icons.directions_bike),
  Choice(title: 'BOAT', icon: Icons.directions_boat),
  Choice(title: 'BUS', icon: Icons.directions_bus),
  Choice(title: 'TRAIN', icon: Icons.directions_railway),
  Choice(title: 'WALK', icon: Icons.directions_walk),
];



class ListaLinkWidget extends StatefulWidget{

  Choice tab;

  ListaLinkWidget({Key key, this.tab}) : super(key: key);

  @override
  ListaLinkWidgetState createState() => ListaLinkWidgetState();

}

class ListaLinkWidgetState extends State<ListaLinkWidget> {


  @override
  void initState() {
    super.initState();
    widget.tab.liststring.add("a");
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      child: Text(
        widget.tab.liststring.toString()
      ),
    );
  }
}

我希望每个页面都有自己的列表,并且不会干扰其他页面的列表,我错了什么?

widget的init块被调用了这么多次,怎么让它只被调用一次呢?

谢谢

【问题讨论】:

  • 您正在使用:widget.tab.liststring.add("a"); 和内部 Choice 您有 List liststring = new List(); ,所以它是空的,每个标签都有相同的“a”
  • 当然可以,但是通过更改页面,init 方法会被多次调用,整个事情不会保留在单个字符串“a”中

标签: flutter flutter-layout tabbar


【解决方案1】:

第1步:更改Choice类,添加this.liststring,删除= new List()

class Choice {
  Choice({this.title, this.icon, this.liststring});

  final String title;
  final IconData icon;
  List<String> liststring; //= new List();
}    

第2步:选择添加你需要的liststring字符串

List<Choice> choices = <Choice>[
Choice(title: 'CAR', icon: Icons.directions_car, liststring: ["car"]),
Choice(title: 'BICYCLE', icon: Icons.directions_bike, liststring: ["bike"]),

第三步:删除widget.tab.liststring.add("a");

第四步:OnTap 需要用 liststring 改变choices.add

GestureDetector(
                onTap: () {
                  _counter = _counter + 1;
                  choices.add(Choice(
                      title: 'New ${_counter}',
                      icon: Icons.directions_car,
                      liststring: ['List ${_counter}']));
                  setState(() {});
                },

完整代码

    import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: tabDemo(),
    );
  }
}

class tabDemo extends StatefulWidget {
  @override
  _tabDemoState createState() => _tabDemoState();
}

class _tabDemoState extends State<tabDemo> with SingleTickerProviderStateMixin {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: choices.length,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Tabbed AppBar'),
            bottom: TabBar(
              isScrollable: true,
              tabs: choices.map((Choice choice) {
                return Tab(
                  text: choice.title,
                  icon: Icon(choice.icon),
                );
              }).toList(),
            ),
          ),
          body: Column(
            children: <Widget>[
              GestureDetector(
                onTap: () {
                  _counter = _counter + 1;
                  choices.add(Choice(
                      title: 'New ${_counter}',
                      icon: Icons.directions_car,
                      liststring: ['List ${_counter}']));
                  setState(() {});
                },
                child: Container(
                  height: 100.0,
                  color: Colors.red,
                ),
              ),
              Expanded(
                child: TabBarView(
                  children: choices.map((Choice choice) {
                    return Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Center(child: ListaLinkWidget(tab: choice)),
                    );
                  }).toList(),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class Choice {
  Choice({this.title, this.icon, this.liststring});

  final String title;
  final IconData icon;
  List<String> liststring; //= new List();
}

List<Choice> choices = <Choice>[
  Choice(title: 'CAR', icon: Icons.directions_car, liststring: ["car"]),
  Choice(title: 'BICYCLE', icon: Icons.directions_bike, liststring: ["bike"]),
  /* Choice(title: 'BOAT', icon: Icons.directions_boat),
  Choice(title: 'BUS', icon: Icons.directions_bus),
  Choice(title: 'TRAIN', icon: Icons.directions_railway),
  Choice(title: 'WALK', icon: Icons.directions_walk),*/
];

class ListaLinkWidget extends StatefulWidget {
  Choice tab;

  ListaLinkWidget({Key key, this.tab}) : super(key: key);

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

class ListaLinkWidgetState extends State<ListaLinkWidget>
    with AutomaticKeepAliveClientMixin<ListaLinkWidget> {
  @override
  void initState() {
    super.initState();
    //widget.tab.liststring.add("a");
    print("created");
  }

  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      child: Text(widget.tab.liststring.toString()),
    );
  }
}

【讨论】:

  • 谢谢,但对我有用的是确保在小部件中将 ListaLinkWidgetState 添加到 init 方法中,将元素添加到列表中( widget.tab.liststring.add(" a");)
  • widget的init块被调用了这么多次,怎么让它只被调用一次呢?
  • 我已经更新了我的答案。您可以使用 AutomaticKeepAliveClientMixin 来完成。我已经测试过了。工作正常。每个标签打印只创建一次。
  • 尝试删除 //widget.tab.liststring.add("a");有时初始化块被调用两次
  • 我发现调用了两次原因stackoverflow.com/questions/56145378/…
猜你喜欢
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 2022-11-29
  • 1970-01-01
相关资源
最近更新 更多