Flutter Tutorial – List Pull to Refresh and Swipe to Delete in Flutter

By | July 3, 2019

Let’s start with Swipe to Delete.

To Swipe and delete a row, each row in the list should be made up of Dismissible Widget. The Dismissible widget has inbuilt listeners for Swipe Gestures.


Swipe to delete & Pull to Refresh

Swipe to delete & Pull to Refresh


Watch Video Tutorial


Swipe to Delete

Here we will have a list of Strings which are a list of companies.
Each row in the List is a Dismissible widget. The onDismissed will be triggered
when the user swipes. We need to remove the corresponding row from the list data-source accordingly, otherwise it will result in the error being the Dismissible widget not removed from the tree when you manipulate the datasource again. So this is a very important step.

  List<String> companies;

  @override
  void initState() {
    super.initState();
    companies = List();
    addCompanies();
  }

  /* Initialize the list with Some company names */
  addCompanies() {
    companies.add("Google");
    companies.add("Apple");
    companies.add("Samsung");
    companies.add("Sony");
    companies.add("LG");
  }

  /* Remove the data from the List DataSource */
  removeCompany(index) {
    setState(() {
      companies.removeAt(index);
    });
  }

  /* Undo the Deleted row when user clicks on UNDO in the SnackBar message */
  undoDelete(index, company) {
    setState(() {
      companies.insert(index, company);
    });
  }

  /* Show Snackbar when Deleted with an action to Undo the delete */
  showSnackBar(context, company, index) {
    Scaffold.of(context).showSnackBar(SnackBar(
      content: Text('$company deleted'),
      action: SnackBarAction(
        label: "UNDO",
        onPressed: () {
          undoDelete(index, company);
        },
      ),
    ));
  }

  /* Give a background to the Swipe Delete as a indicator to Delete */
  Widget refreshBg() {
    return Container(
      alignment: Alignment.centerRight,
      padding: EdgeInsets.only(right: 20.0),
      color: Colors.red,
      child: const Icon(
        Icons.delete,
        color: Colors.white,
      ),
    );
  }

  Widget list() {
    return ListView.builder(
      padding: EdgeInsets.all(20.0),
      itemCount: companies.length,
      itemBuilder: (BuildContext context, int index) {
        return row(context, index);
      },
    );
  }

  Widget row(context, index) {
    return Dismissible(
      key: Key(companies[index]), // UniqueKey().toString()
      onDismissed: (direction) {
        var company = companies[index];
        showSnackBar(context, company, index);
        removeCompany(index);
      },
      background: refreshBg(),
      child: Card(
        child: ListTile(
          title: Text(companies[index]),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        child: list(),
      ),
    );
  }


Pull to Refresh

To add Pull to Refresh, Wrap the List with the RefreshIndicator Widget and implement the onRefresh callback.The code will change like this.

 
 /* Mimic a delay and add a random value to the list */
 Future<Null> refreshList() async {
    await Future.delayed(Duration(seconds: 10));
    addRandomCompany();
    return null;
  }

  ...
  RefreshIndicator(
    key: refreshKey,
    onRefresh: () async {
      await refreshList();
    },
    child: list(),
  )

Complete Code

The Complete source code will look like this.

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

class SwipeDeleteDemo extends StatefulWidget {
  SwipeDeleteDemo() : super();

  final String title = "Refresh/Swipe Delete Demo";

  @override
  SwipeDeleteDemoState createState() => SwipeDeleteDemoState();
}

class SwipeDeleteDemoState extends State<SwipeDeleteDemo> {
  //
  List<String> companies;
  GlobalKey<RefreshIndicatorState> refreshKey;
  Random r;

  @override
  void initState() {
    super.initState();
    refreshKey = GlobalKey<RefreshIndicatorState>();
    r = Random();
    companies = List();
    addCompanies();
  }

  addCompanies() {
    companies.add("Google");
    companies.add("Apple");
    companies.add("Samsung");
    companies.add("Sony");
    companies.add("LG");
  }

  addRandomCompany() {
    int nextCount = r.nextInt(100);
    setState(() {
      companies.add("Company $nextCount");
    });
  }

  removeCompany(index) {
    setState(() {
      companies.removeAt(index);
    });
  }

  undoDelete(index, company) {
    setState(() {
      companies.insert(index, company);
    });
  }

  Future<Null> refreshList() async {
    await Future.delayed(Duration(seconds: 10));
    addRandomCompany();
    return null;
  }

  showSnackBar(context, company, index) {
    Scaffold.of(context).showSnackBar(SnackBar(
      content: Text('$company deleted'),
      action: SnackBarAction(
        label: "UNDO",
        onPressed: () {
          undoDelete(index, company);
        },
      ),
    ));
  }

  Widget refreshBg() {
    return Container(
      alignment: Alignment.centerRight,
      padding: EdgeInsets.only(right: 20.0),
      color: Colors.red,
      child: const Icon(
        Icons.delete,
        color: Colors.white,
      ),
    );
  }

  Widget list() {
    return ListView.builder(
      padding: EdgeInsets.all(20.0),
      itemCount: companies.length,
      itemBuilder: (BuildContext context, int index) {
        return row(context, index);
      },
    );
  }

  Widget row(context, index) {
    return Dismissible(
      key: Key(companies[index]), // UniqueKey().toString()
      onDismissed: (direction) {
        var company = companies[index];
        showSnackBar(context, company, index);
        removeCompany(index);
      },
      background: refreshBg(),
      child: Card(
        child: ListTile(
          title: Text(companies[index]),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: RefreshIndicator(
        key: refreshKey,
        onRefresh: () async {
          await refreshList();
        },
        child: list(),
      ),
    );
  }
}

Thanks for reading.

Please leave your valuable comments below the post.

Watch the Youtube tutorial to see everything in action and Subscribe for more videos.

One thought on “Flutter Tutorial – List Pull to Refresh and Swipe to Delete in Flutter

  1. Pingback: Google's Flutter Tutorial - Pull to Refresh, Swipe to Delete in ListView - TutsFx

Leave a Reply

Your email address will not be published. Required fields are marked *