Reputation: 844
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.
Upvotes: 1
Views: 541
Reputation: 54367
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),
),
);
}
}
Upvotes: 1