简体   繁体   中英

What is the correct way to use Dismissible Widget inside CustomScrollView in flutter?

I am trying to put basic DismissibleWidget inside CustomScrollView. Here is the code

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),
      ),
    );
  }
}

But when ListTile is tapped and user is routed to SecondPage; and user navigates back it shows following errors.

A dismissed Dismissible widget is still part of the tree. Make sure to immediately remove the Dismissible widget from the application once that handler has fired.

Normally this would be solved by using ListView.builder when not using Slivers as follow.

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);
    });
  },
))

But I cannot find way to get rid of this error while using CustomScrollView.

You need to use removeAt inside setState
You can copy paste run full code below
code snippet

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

                      }

working demo

在此处输入图片说明

full code

    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),
          ),
        );
      }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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