Skip to content

[syncfusion_flutter_datagrid] [Android / IOS] Scroll does not apply all page and this behavior makes hard to scroll. #1620

Closed
@EBBozkurt

Description

Hello, Syncfusion Flutter Team,

I have a dashboard which are using 6 Datagrids. On web everything is fine with scrolling whole page. But in mobile Datagrid scrolling is litte bit unwanted. This makes the user's scrolling experience on mobile screens quite difficult. Without sharing my own codes, I leave here the codes and a screen recording of a work similar to the UI and code I made.

My problem is basically that whether I use Expanded or not, I cannot scroll the entire page while on the table. As you can see in the example, in the 1st and 2nd tables, although the table does not need to scroll itself, I cannot scroll up or down while on the table. I definitely have to scroll by touching outside the table. This prevents the user from using it properly.

Here is my code example:

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: false,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

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

class MyHomePageState extends State<MyHomePage> {
  late EmployeeDataSource _employeeDataSource;
  late EmployeeDataSource _employeeDataSourceTwo;
  late EmployeeDataSource _employeeDataSourceThree;
  List<Employee> _employees = [];

  @override
  void initState() {
    super.initState();
    _employees = populateData();
    _employeeDataSource = EmployeeDataSource(_employees.take(3).toList());
    _employeeDataSourceTwo = EmployeeDataSource(_employees.take(4).toList());
    _employeeDataSourceThree = EmployeeDataSource(_employees.take(4).toList());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion DataGrid Demo')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            SizedBox(
              height: 300,
              child: Column(
                children: [
                  const Text("DT1"),
                  Expanded(
                    child: Container(
                      decoration: BoxDecoration(
                        border: Border(
                          bottom:
                              BorderSide(width: 1, color: Colors.grey.shade300),
                          left:
                              BorderSide(width: 1, color: Colors.grey.shade300),
                          right:
                              BorderSide(width: 1, color: Colors.grey.shade300),
                        ),
                      ),
                      child: SfDataGrid(
                        source: _employeeDataSource,
                        columns: getColumns,
                        gridLinesVisibility: GridLinesVisibility.both,
                        headerGridLinesVisibility: GridLinesVisibility.both,
                        allowFiltering: true,
                        allowSorting: true,
                        showColumnHeaderIconOnHover: true,
                      ),
                    ),
                  ),
                ],
              ),
            ),
            const Divider(),
            SizedBox(
              height: 300,
              child: Column(
                children: [
                  const Text("DT2"),
                  Expanded(
                    child: Container(
                      decoration: BoxDecoration(
                        border: Border(
                          bottom:
                              BorderSide(width: 1, color: Colors.grey.shade300),
                          left:
                              BorderSide(width: 1, color: Colors.grey.shade300),
                          right:
                              BorderSide(width: 1, color: Colors.grey.shade300),
                        ),
                      ),
                      child: SfDataGrid(
                        source: _employeeDataSourceTwo,
                        columns: getColumns,
                        gridLinesVisibility: GridLinesVisibility.both,
                        headerGridLinesVisibility: GridLinesVisibility.both,
                        allowFiltering: true,
                        allowSorting: true,
                        showColumnHeaderIconOnHover: true,
                      ),
                    ),
                  ),
                ],
              ),
            ),
            const Divider(),
            SizedBox(
              height: 300,
              child: Container(
                decoration: BoxDecoration(
                  border: Border(
                    bottom: BorderSide(width: 1, color: Colors.grey.shade300),
                    left: BorderSide(width: 1, color: Colors.grey.shade300),
                    right: BorderSide(width: 1, color: Colors.grey.shade300),
                  ),
                ),
                child: SfDataGrid(
                  source: _employeeDataSourceThree,
                  columns: getColumns,
                  gridLinesVisibility: GridLinesVisibility.both,
                  headerGridLinesVisibility: GridLinesVisibility.both,
                  allowFiltering: true,
                  allowSorting: true,
                  showColumnHeaderIconOnHover: true,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  List<GridColumn> get getColumns {
    return <GridColumn>[
      gridColumn(columnName: 'ID', labelText: 'ID', width: 100),
      gridColumn(columnName: 'Name', labelText: 'Name', width: 150),
      gridColumn(
          columnName: 'Designation', labelText: 'Designation', width: 150),
      gridColumn(columnName: 'DOJ', labelText: 'DOJ', width: 150),
      gridColumn(columnName: 'Email', labelText: 'Email', width: 150),
      gridColumn(columnName: 'City', labelText: 'City', width: 150),
      gridColumn(columnName: 'Country', labelText: 'Country', width: 150),
      gridColumn(columnName: 'Salary', labelText: 'Salary', minimumWidth: 350),
    ];
  }

  GridColumn gridColumn({
    required String columnName,
    required String labelText,
    Alignment alignment = Alignment.centerLeft,
    ColumnWidthMode columnWidthMode = ColumnWidthMode.none,
    bool visible = true,
    bool allowSorting = true,
    ColumnHeaderIconPosition sortIconPosition = ColumnHeaderIconPosition.end,
    ColumnHeaderIconPosition filterIconPosition = ColumnHeaderIconPosition.end,
    EdgeInsets autoFitPadding = const EdgeInsets.all(16.0),
    double minimumWidth = double.nan,
    double maximumWidth = double.nan,
    double width = double.nan,
    bool allowEditing = true,
    bool allowFiltering = true,
    FilterPopupMenuOptions? filterPopupMenuOptions,
    EdgeInsetsGeometry filterIconPadding =
        const EdgeInsets.symmetric(horizontal: 8.0),
  }) {
    return GridColumn(
      columnName: columnName,
      label: Container(
        padding: const EdgeInsets.all(8.0),
        alignment: alignment,
        child: Text(
          labelText,
          overflow: TextOverflow.ellipsis,
          style: const TextStyle(fontWeight: FontWeight.bold),
        ),
      ),
      columnWidthMode: columnWidthMode,
      visible: visible,
      allowSorting: allowSorting,
      sortIconPosition: sortIconPosition,
      filterIconPosition: filterIconPosition,
      autoFitPadding: autoFitPadding,
      minimumWidth: minimumWidth,
      maximumWidth: maximumWidth,
      width: width,
      allowEditing: allowEditing,
      allowFiltering: allowFiltering,
      filterPopupMenuOptions: filterPopupMenuOptions,
      filterIconPadding: filterIconPadding,
    );
  }
}

class EmployeeDataSource extends DataGridSource {
  EmployeeDataSource(List<Employee> employees) {
    buildDataGridRows(employees);
  }

  List<DataGridRow> datagridRows = [];

  @override
  List<DataGridRow> get rows => datagridRows;

  void buildDataGridRows(List<Employee> employeesData) {
    datagridRows = employeesData
        .map<DataGridRow>((e) => DataGridRow(cells: [
              DataGridCell<int>(columnName: 'ID', value: e.id),
              DataGridCell<String>(columnName: 'Name', value: e.name),
              DataGridCell<String>(
                  columnName: 'Designation', value: e.designation),
              DataGridCell<String>(columnName: 'DOJ', value: e.doj),
              DataGridCell<String>(columnName: 'Email', value: e.email),
              DataGridCell<String>(columnName: 'City', value: e.city),
              DataGridCell<String>(columnName: 'Country', value: e.country),
              DataGridCell<int>(columnName: 'Salary', value: e.salary),
            ]))
        .toList();
  }

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((dataGridCell) {
      return Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.symmetric(horizontal: 8.0),
        child: Text(dataGridCell.value.toString()),
      );
    }).toList());
  }
}

class Employee {
  Employee(this.id, this.name, this.designation, this.doj, this.email,
      this.city, this.country, this.salary);
  final int id;
  final String name;
  final String designation;
  final String doj;
  final String email;
  final String city;
  final String country;
  final int salary;
}

List<Employee> populateData() {
  return [
    Employee(10001, 'Jack', 'Manager', '01/01/2023', 'jack@email.com',
        'New York', 'USA', 150000),
    Employee(10002, 'Perry', 'Lead', '01/02/2023', 'perry@email.com', 'London',
        'UK', 80000),
    Employee(10003, 'James', 'Developer', '01/03/2023', 'james@email.com',
        'Tokyo', 'Japan', 55000),
    Employee(10004, 'Michael', 'Designer', '01/04/2023', 'michael@email.com',
        'Paris', 'France', 39000),
    Employee(10005, 'Maria', 'Developer', '01/05/2023', 'maria@email.com',
        'Sydney', 'Australia', 45000),
    Employee(10006, 'Edward', 'UI Designer', '01/06/2023', 'edward@email.com',
        'Berlin', 'Germany', 36000),
    Employee(10007, 'Adams', 'Developer', '01/07/2023', 'adams@email.com',
        'Toronto', 'Canada', 43000),
    Employee(10008, 'Grimes', 'QA Testing', '01/08/2023', 'grimes@email.com',
        'Rio de Janeiro', 'Brazil', 43000),
    Employee(10009, 'Francisco', 'Developer', '01/09/2023',
        'francisco@email.com', 'Madrid', 'Spain', 32000),
    Employee(10010, 'Yang', 'Developer', '01/10/2023', 'yang@email.com',
        'Beijing', 'China', 29000),
    Employee(10011, 'Peter', 'Developer', '01/11/2023', 'peter@email.com',
        'Moscow', 'Russia', 28000),
    Employee(10012, 'Carlos', 'Developer', '01/12/2023', 'carlos@email.com',
        'Mexico City', 'Mexico', 28000),
    Employee(10013, 'Pedro', 'Developer', '01/13/2023', 'pedro@email.com',
        'Lisbon', 'Portugal', 26000),
    Employee(10014, 'Sven', 'Developer', '01/14/2023', 'sven@email.com',
        'Stockholm', 'Sweden', 22000),
    Employee(10015, 'Janine', 'Developer', '01/15/2023', 'janine@email.com',
        'Geneva', 'Switzerland', 22000),
    Employee(10016, 'Ann', 'Developer', '01/16/2023', 'ann@email.com', 'Dublin',
        'Ireland', 22000),
    Employee(10017, 'Roland', 'Developer', '01/17/2023', 'roland@email.com',
        'Vienna', 'Austria', 22000),
    Employee(10018, 'Aria', 'Developer', '01/18/2023', 'aria@email.com',
        'Athens', 'Greece', 20000),
    Employee(10019, 'Martine', 'Developer', '01/19/2023', 'martine@email.com',
        'Oslo', 'Norway', 20000),
    Employee(10020, 'Maria', 'Developer', '01/20/2023', 'maria1@email.com',
        'Helsinki', 'Finland', 20000),
    Employee(10020, 'Maria', 'Developer', '01/20/2023', 'maria1@email.com',
        'Helsinki', 'Finland', 20000),
    Employee(10021, 'John', 'Developer', '01/21/2023', 'john@email.com',
        'Copenhagen', 'Denmark', 20000),
    Employee(10022, 'Anna', 'Developer', '01/22/2023', 'anna@email.com',
        'Amsterdam', 'Netherlands', 20000),
    Employee(10023, 'David', 'Developer', '01/23/2023', 'david@email.com',
        'Brussels', 'Belgium', 20000),
    Employee(10024, 'Luis', 'Developer', '01/24/2023', 'luis@email.com', 'Bern',
        'Switzerland', 20000),
    Employee(10025, 'Sophie', 'Developer', '01/25/2023', 'sophie@email.com',
        'Vienna', 'Austria', 20000),
    Employee(10026, 'Elena', 'Developer', '01/26/2023', 'elena@email.com',
        'Budapest', 'Hungary', 20000),
    Employee(10027, 'Thomas', 'Developer', '01/27/2023', 'thomas@email.com',
        'Prague', 'Czech Republic', 20000),
    Employee(10028, 'Lucas', 'Developer', '01/28/2023', 'lucas@email.com',
        'Warsaw', 'Poland', 20000),
    Employee(10029, 'Olivia', 'Developer', '01/29/2023', 'olivia@email.com',
        'Athens', 'Greece', 20000),
    Employee(10030, 'Daniel', 'Developer', '01/30/2023', 'daniel@email.com',
        'Rome', 'Italy', 20000),
  ];
}

And video:

Android.Emulator.-.Pixel_3a_API_33_5554.2024-01-09.16-06-07.mp4

Metadata

Assignees

No one assigned

    Labels

    data gridData grid component

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions