滚动屏幕时 tabcontroller 不会改变(比如等待 1 秒)。标签文本正在改变

alt*_*ve4 2 dart flutter

我在下面有一个标签栏,如 Tab (text: '') 和 _tabcontroller,如果我使用 tab.text 作为正文其工作良好 (body:Text(tab.text)) 但如果我为索引创建一个列表并使用 exampleList[_tabcontroller .index] 它的速度很慢,就像我在刷屏一样,它等待 1 秒。我的代码比我发布的要大,但我认为这是我的核心问题。n:我想使用 Tab 之类的 Tab(child:Row()) 所以我不能使用 tab.text 如果它有其他选择我也可以(idk tab.listener 或 tab.id?)

    TabController _tabController;
    final List<Tab> tabs = <Tab>[
new Tab(text: "hello1",),
new Tab(text:"hello2"),

  ];
...
@override
void initState() {
super.initState();
_tabController = new TabController(
    vsync: this, length: tabs.length, initialIndex: cDate);
    _tabController.addListener(_handleSelected);

}
void _handleSelected() {
setState(() {
  _tabController.index;
});
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
 }
...
    body: new TabBarView(
    controller: _tabController,
    children: tabs.map((Tab tab) {
     //ITS FAST BUT I DONT WANNA USE LIKE THAT:
      return Center(Text(tab.text));
    //ITS SLOW BUT I WANNA USE LIKE THAT:
      return Center(Text(etcList[_tabcontroller.index] );
    }).toList(),
  ),
Run Code Online (Sandbox Code Playgroud)

试图解释,但我的英语不好抱歉

Aja*_*mar 25

之所以发生这种情况,TabBarView是因为在选项卡之间进行动画处理,并且_tabController.index仅在动画完成后才更改值。

在这里,我使用_tabController.indexvalue 来获取Choice表单列表的对象choices并将其显示为titlein AppBar

  appBar: AppBar(
          title: Text(choices[_tabController.index].title),
          centerTitle: true,
        ),
Run Code Online (Sandbox Code Playgroud)

问题

issue_gif

解决方案

在此处输入图片说明

就像TabBarView在选项卡之间设置动画一样,可以向_tabController的动画添加侦听器。

_tabController.animation
  ..addListener(() {
    setState(() {
      _currentIndex = (_tabController.animation.value).round(); //_tabController.animation.value returns double
      print('_tabController.animation.value: ${_tabController.animation.value}');
      print('_currentIndex: $_currentIndex');
    });
  });
Run Code Online (Sandbox Code Playgroud)

这是完整的代码:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SampleTabScreen(),
    );
  }
}

class SampleTabScreen extends StatefulWidget {
  @override
  _SampleTabScreenState createState() => _SampleTabScreenState();
}

class _SampleTabScreenState extends State<SampleTabScreen> with SingleTickerProviderStateMixin {
  TabController _tabController;
  int _currentIndex = 0;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(vsync: this, length: choices.length);
    _tabController.animation
      ..addListener(() {
        setState(() {
          _currentIndex = (_tabController.animation.value).round(); //_tabController.animation.value returns double
          print('_tabController.animation.value: ${_tabController.animation.value}');
          print('_currentIndex: $_currentIndex');
        });
      });
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text(choices[_currentIndex].title),
          centerTitle: true,
        ),
        body: TabBarView(
          controller: _tabController,
          children: choices.map((Choice choice) {
            return Padding(
              padding: const EdgeInsets.all(16.0),
              child: ChoiceCard(choice: choice),
            );
          }).toList(),
        ),
      ),
    );
  }
}

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

  final String title;
  final IconData icon;
}

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

class ChoiceCard extends StatelessWidget {
  const ChoiceCard({Key key, this.choice}) : super(key: key);

  final Choice choice;

  @override
  Widget build(BuildContext context) {
    final TextStyle textStyle = Theme.of(context).textTheme.display1;
    return Card(
      color: Colors.white,
      child: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Icon(choice.icon, size: 128.0, color: textStyle.color),
            Text(choice.title, style: textStyle),
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 最好使用 `value = _tabController.animation.value.round()` 和 `if (value != _currentIndex) setState(() =&gt; _currentIndex = value);` 来避免多次调用 `setState()`。 (4认同)