在flutter中的CustomScrollView中使用Dismissible Widget的正确方法是什么?

时间:2019-12-09 04:35:51

标签: flutter dart

我试图将基本的DismissibleWidget放入CustomScrollView中。这是代码

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

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool change = false;
  List<String> someList;

  @override
  void initState() {
    super.initState();
    someList = List.generate((20), (index) => 'Data $index');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          body: CustomScrollView(
            slivers: <Widget>[
              SliverAppBar(
                title: Text("Dismissible in Slivers"),
              ),
              SliverList(
                delegate: SliverChildBuilderDelegate(
                    (context, index) => Dismissible(
                          key: ValueKey<String>(someList[index]),
                          child: ListTile(
                            title: Text(someList[index]),
                            onTap: () {
                              Navigator.of(context).push(MaterialPageRoute(
                                  builder: (context) =>
                                      SecondPage(someList[index])));
                            },
                          ),
                          onDismissed: (dismissDirection) {
                            someList.remove(index);
                          },
                        ),
                    childCount: someList.length),
              )
            ],
          ),
        ));
  }
}

class SecondPage extends StatelessWidget {
  final String title;

  SecondPage(this.title);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(this.title),
      ),
    );
  }
}

但是当点击ListTile并将用户路由到SecondPage时;并且用户向后导航,它显示以下错误。

  

已关闭的“可关闭”小部件仍是树的一部分。触发该处理程序后,请确保立即从应用程序中删除Dismissible小部件。

通常,当不使用Slivers时,可以通过使用ListView.builder来解决此问题。

ListView.builder(
itemCount: someList.length,
itemBuilder: (context, index) => Dismissible(
  key: ValueKey<String>(someList[index]),
  child: ListTile(
    title: Text(someList[index]),
    onTap: () {
      Navigator.of(context).push(MaterialPageRoute(
          builder: (context) =>
              SecondPage(someList[index])));
    },
  ),
  onDismissed: (dissmissDirection) {
    setState(() {
      someList.removeAt(index);
    });
  },
))

但是我找不到使用CustomScrollView时摆脱此错误的方法。

1 个答案:

答案 0 :(得分:0)

您需要在removeAt内使用setState
您可以在
下面复制粘贴运行完整代码 代码段

 onDismissed: (dismissDirection) {
                        setState(() {
                          someList.removeAt(index);
                        });

                      }

工作演示

enter image description here

完整代码

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

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

    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }

    class _MyAppState extends State<MyApp> {
      bool change = false;
      List<String> someList;

      @override
      void initState() {
        super.initState();
        someList = List.generate((20), (index) => 'Data $index');
      }

      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: Scaffold(
              body: CustomScrollView(
                slivers: <Widget>[
                  SliverAppBar(
                    title: Text("Dismissible in Slivers"),
                  ),
                  SliverList(
                    delegate: SliverChildBuilderDelegate(
                            (context, index) => Dismissible(
                          key: ValueKey<String>(someList[index]),
                          child: ListTile(
                            title: Text(someList[index]),
                            onTap: () {
                              Navigator.of(context).push(MaterialPageRoute(
                                  builder: (context) =>
                                      SecondPage(someList[index])));
                            },
                          ),
                          onDismissed: (dismissDirection) {
                            setState(() {
                              someList.removeAt(index);
                            });

                          },
                        ),
                        childCount: someList.length),
                  )
                ],
              ),
            ));
      }
    }

    class SecondPage extends StatelessWidget {
      final String title;

      SecondPage(this.title);

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Text(this.title),
          ),
        );
      }
    }