skills/syncfusion-flutter-datagrid/references/swiping.md

6.0 KiB

Swiping — Flutter DataGrid

Overview

SfDataGrid supports left/right row swiping via allowSwiping = true. Use startSwipeActionsBuilder and endSwipeActionsBuilder to define the widgets revealed behind swiped rows. Swipe distance is controlled by swipeMaxOffset.


Basic Swiping

SfDataGrid(
  allowSwiping: true,
  swipeMaxOffset: 100.0,
  source: _employeeDataSource,
  startSwipeActionsBuilder:
      (BuildContext context, DataGridRow row, int rowIndex) {
    return GestureDetector(
        onTap: () {
          _employeeDataSource.dataGridRows.insert(
              rowIndex,
              DataGridRow(cells: [
                DataGridCell(value: 1011, columnName: 'id'),
                DataGridCell(value: 'Tom Bass', columnName: 'name'),
                DataGridCell(value: 'Developer', columnName: 'designation'),
                DataGridCell(value: 20000, columnName: 'salary')
              ]));
          _employeeDataSource.updateDataGridSource();
        },
        child: Container(
            color: Colors.greenAccent,
            child: Center(child: Icon(Icons.add))));
  },
  endSwipeActionsBuilder:
      (BuildContext context, DataGridRow row, int rowIndex) {
    return GestureDetector(
        onTap: () {
          _employeeDataSource.dataGridRows.removeAt(rowIndex);
          _employeeDataSource.updateDataGridSource();
        },
        child: Container(
            color: Colors.redAccent,
            child: Center(child: Icon(Icons.delete))));
  },
  columns: <GridColumn>[
    GridColumn(
        columnName: 'id',
        label: Container(
            padding: EdgeInsets.symmetric(horizontal: 16.0),
            alignment: Alignment.centerRight,
            child: Text('ID', overflow: TextOverflow.ellipsis))),
    GridColumn(
        columnName: 'name',
        label: Container(
            padding: EdgeInsets.symmetric(horizontal: 16.0),
            alignment: Alignment.centerLeft,
            child: Text('Name', overflow: TextOverflow.ellipsis))),
    GridColumn(
        columnName: 'designation',
        label: Container(
            padding: EdgeInsets.symmetric(horizontal: 16.0),
            alignment: Alignment.centerLeft,
            child: Text('Designation', overflow: TextOverflow.ellipsis))),
    GridColumn(
        columnName: 'salary',
        label: Container(
            padding: EdgeInsets.symmetric(horizontal: 16.0),
            alignment: Alignment.centerRight,
            child: Text('Salary', overflow: TextOverflow.ellipsis))),
  ],
)

The updateDataGridSource() helper on DataGridSource calls notifyListeners().

class EmployeeDataSource extends DataGridSource {
... 

void updateDataGridSource() {
    notifyListeners();
  }
}

Swipe Callbacks

Callback Parameters Description
onSwipeStart DataGridSwipeStartDetails Called when swipe offset changes from zero. Return false to cancel.
onSwipeUpdate DataGridSwipeUpdateDetails Called during active swiping. Return false to cancel.
onSwipeEnd DataGridSwipeEndDetails Called when swipe reaches swipeMaxOffset.

Callback detail properties:

Property Description
rowIndex Index of the swiped row
swipeDirection DataGridRowSwipeDirection.startToEnd or endToStart
swipeOffset Current swipe offset

Customized Swipe-to-Delete

Delete a row when swiped fully from one end to the other:

LayoutBuilder(builder: (context, constraints) {
  return SfDataGrid(
    allowSwiping: true,
    swipeMaxOffset: constraints.maxWidth,
    source: _employeeDataSource,
    startSwipeActionsBuilder:
        (BuildContext context, DataGridRow row, int rowIndex) {
      return GestureDetector(
          onTap: () {
            _employeeDataSource.dataGridRows.removeAt(rowIndex);
            _employeeDataSource.updateDataGridSource();
          },
          child: Container(
              color: Colors.green,
              padding: EdgeInsets.only(left: 30.0),
              alignment: Alignment.centerLeft,
              child: Text('Delete', style: TextStyle(color: Colors.white))));
    },
    onSwipeUpdate: (DataGridSwipeUpdateDetails details) {
      isReachedCenter =
          (details.swipeOffset >= constraints.maxWidth / 2) ? true : false;
      return true;
    },
    onSwipeEnd: (DataGridSwipeEndDetails details) async {
      if (isReachedCenter && _employeeDataSource.dataGridRows.isNotEmpty) {
        _employeeDataSource.dataGridRows.removeAt(details.rowIndex);
        _employeeDataSource.updateDataGridSource();
        isReachedCenter = false;
      }
    },
    columns: columns,
  );
})

Different Swipe Offsets Per Direction

Use onSwipeStart and details.setSwipeMaxOffset() to set different max offsets for left vs right swipe:

SfDataGrid(
  allowSwiping: true,
  source: employeeDataSource,
  onSwipeStart: (DataGridSwipeStartDetails details) {
    if (details.swipeDirection == DataGridRowSwipeDirection.startToEnd) {
      details.setSwipeMaxOffset(200);
    } else if (details.swipeDirection == DataGridRowSwipeDirection.endToStart) {
      details.setSwipeMaxOffset(100);
    }
    return true;
  },
  startSwipeActionsBuilder: ...,
  endSwipeActionsBuilder: ...,
  columns: columns,
)

Key Property Reference

Property Type Default Description
allowSwiping bool false Enable row swiping
swipeMaxOffset double 200.0 Maximum swipe distance in pixels
startSwipeActionsBuilder Widget? Function(context, row, rowIndex)? null Widget shown on left-to-right swipe
endSwipeActionsBuilder Widget? Function(context, row, rowIndex)? null Widget shown on right-to-left swipe
onSwipeStart bool? Function(DataGridSwipeStartDetails)? null Callback at swipe start; return false to cancel
onSwipeUpdate bool? Function(DataGridSwipeUpdateDetails)? null Callback during swipe; return false to cancel
onSwipeEnd void Function(DataGridSwipeEndDetails)? null Callback when swipe completes