如何在Flutter的选项卡栏中实现下拉刷新?

9
我有一个选项卡栏,其中有5个选项卡,每个选项卡包含一些数据。当用户下拉以进行刷新时,我希望显示一个刷新指示器,并通过API调用更新选项卡内的数据。以下是我到目前为止尝试过的代码。
请帮助我如何在下拉时显示刷新指示器,以及编写一个回调函数来执行某些操作。
import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    ));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {


  var refreshKey = GlobalKey<RefreshIndicatorState>();

  // @override
  // void initState() {
  //   super.initState();
  //   random = Random();
  //   refreshList();
  // }

  Future<Null> refreshList() async {
    refreshKey.currentState?.show(atTop: false);
    await Future.delayed(Duration(seconds: 2));

    setState(() {
     new HomePage();
    });

    return null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Pull to refresh"),
      ),
      body: RefreshIndicator(
        key: refreshKey,
        child: new DefaultTabController(
        length: 5,
        child: new Column(
          children: <Widget>[
            new Container(
              width: 1200.0,
              child: new Material(
                color: Colors.lightBlue,
                child: new TabBar(
                  isScrollable: true,
                  labelColor: Colors.white,
                  tabs: [
                    Tab(
                      child: new Text("All",
                      style: new TextStyle(fontSize: 20.0)
                      ),
                    ),
                    Tab(
                      child: new Text("Moving",
                      style: new TextStyle(fontSize: 20.0)), 
                    ),
                    Tab(
                      child: new Text("Idle",
                      style: new TextStyle(fontSize: 20.0)),
                    ),
                    Tab(
                      child: new Text("Parked",
                      style: new TextStyle(fontSize: 20.0)),
                    ),
                    Tab(
                      child: new Text("Inactive",
                      style: new TextStyle(fontSize: 20.0)),
                    ),
                  ],
                ),
              ),
            ),
            new Expanded(
              child: new TabBarView(
                children: [
                  Tab(
                      child: new Text("Demo",
                      style: new TextStyle(fontSize: 20.0)),
                    ),
                  Tab(
                      child: new Text("Demo",
                      style: new TextStyle(fontSize: 20.0)),
                    ),
                  Tab(
                      child: new Text("Demo",
                      style: new TextStyle(fontSize: 20.0)),
                    ),
                  Tab(
                      child: new Text("Demo",
                      style: new TextStyle(fontSize: 20.0)),
                    ),
                  Tab(
                      child: new Text("Demo",
                      style: new TextStyle(fontSize: 20.0)),
                    ),        
                ],
              ),
            ),
          ],
        ),
      ),
      onRefresh: refreshList,
      ),
    );
  }
}
2个回答

9

RefreshIndicator的子级应该是Scrollable,在上面的示例中它是DefaultTabController,这就是为什么您无法获得RefreshIndicator的原因。

我将RefreshIndicator移动到Tab视图中,并添加了一个Scrollable作为子级(ListView)。请参考下面的代码:

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

void main() => runApp(MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    ));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {
  var refreshKey = GlobalKey<RefreshIndicatorState>();

  // @override
  // void initState() {
  //   super.initState();
  //   random = Random();
  //   refreshList();
  // }

  Future<Null> refreshList() async {
    refreshKey.currentState?.show(atTop: false);
    await Future.delayed(Duration(seconds: 2));

    setState(() {
      new HomePage();
    });

    return null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Pull to refresh"),
      ),
      body: new DefaultTabController(
        length: 5,
        child: new Column(
          children: <Widget>[
            new Container(
              width: 1200.0,
              child: new Material(
                color: Colors.lightBlue,
                child: new TabBar(
                  isScrollable: true,
                  labelColor: Colors.white,
                  tabs: [
                    Tab(
                      child: new Text("All",
                          style: new TextStyle(fontSize: 20.0)),
                    ),
                    Tab(
                      child: new Text("Moving",
                          style: new TextStyle(fontSize: 20.0)),
                    ),
                    Tab(
                      child: new Text("Idle",
                          style: new TextStyle(fontSize: 20.0)),
                    ),
                    Tab(
                      child: new Text("Parked",
                          style: new TextStyle(fontSize: 20.0)),
                    ),
                    Tab(
                      child: new Text("Inactive",
                          style: new TextStyle(fontSize: 20.0)),
                    ),
                  ],
                ),
              ),
            ),
            new Expanded(
              child: new TabBarView(
                children: [
                  Tab(
                    child: new RefreshIndicator(
                      child: new ListView(
                        children: <Widget>[
                          new Column(
                            children: <Widget>[
                              new Center(
                                child: new Text("Demo",
                                    style: new TextStyle(fontSize: 20.0)),
                              )
                            ],
                          )
                        ],
                      ),
                      onRefresh: refreshList,
                      key: refreshKey,
                    ),
                  ),
                  Tab(
                    child: new Text("Demo",
                        style: new TextStyle(fontSize: 20.0)),
                  ),
                  Tab(
                    child: new Text("Demo",
                        style: new TextStyle(fontSize: 20.0)),
                  ),
                  Tab(
                    child: new Text("Demo",
                        style: new TextStyle(fontSize: 20.0)),
                  ),
                  Tab(
                    child: new Text("Demo",
                        style: new TextStyle(fontSize: 20.0)),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

我测试了这段代码,它运行良好。如果您的要求得到满足,请告诉我。

上面的代码看起来分离了appBartabBar,所以我尝试修复它。如果您也想这样做,请参考下面的代码。

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    ));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {
  var refreshKey = GlobalKey<RefreshIndicatorState>();

  // @override
  // void initState() {
  //   super.initState();
  //   random = Random();
  //   refreshList();
  // }

  Future<Null> refreshList() async {
    refreshKey.currentState?.show(atTop: false);
    await Future.delayed(Duration(seconds: 2));

    //network call and setState so that view will render the new values
    print("refresh");
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: new DefaultTabController(
      length: 5,
      child: Scaffold(
        appBar: AppBar(
          title: Text("Pull to refresh"),
          bottom: new TabBar(
            isScrollable: true,
            labelColor: Colors.white,
            tabs: [
              Tab(
                child: new Text("All", style: new TextStyle(fontSize: 20.0)),
              ),
              Tab(
                child: new Text("Moving", style: new TextStyle(fontSize: 20.0)),
              ),
              Tab(
                child: new Text("Idle", style: new TextStyle(fontSize: 20.0)),
              ),
              Tab(
                child: new Text("Parked", style: new TextStyle(fontSize: 20.0)),
              ),
              Tab(
                child:
                    new Text("Inactive", style: new TextStyle(fontSize: 20.0)),
              ),
            ],
          ),
        ),
        body: new Column(
          children: <Widget>[
            new Expanded(
              child: new TabBarView(
                children: [
                  Tab(
                    child: new RefreshIndicator(
                      child: new ListView(
                        children: <Widget>[
                          new Column(
                            children: <Widget>[
                              new Center(
                                child: new Text("Demo",
                                    style: new TextStyle(fontSize: 20.0)),
                              )
                            ],
                          )
                        ],
                      ),
                      onRefresh: refreshList,
                      key: refreshKey,
                    ),
                  ),
                  Tab(
                    child:
                        new Text("Demo", style: new TextStyle(fontSize: 20.0)),
                  ),
                  Tab(
                    child:
                        new Text("Demo", style: new TextStyle(fontSize: 20.0)),
                  ),
                  Tab(
                    child:
                        new Text("Demo", style: new TextStyle(fontSize: 20.0)),
                  ),
                  Tab(
                    child:
                        new Text("Demo", style: new TextStyle(fontSize: 20.0)),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    ));
  }
}

2
RefreshIndicator 的子组件必须是可滚动的。 - moshfiqur
1
@moshfiqur,你解决了这个问题吗? - Sumit Kumawat

2

对于那些需要答案的人!尝试接受的答案,如果仍然不起作用?那么尝试添加physics: const AlwaysScrollableScrollPhysics(),这可能会有所帮助。

示例:

ListView(
physics: const AlwaysScrollableScrollPhysics(),
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接