Flutter DataTable - Tap on row

2020-06-28 15:52发布

问题:

I am using Flutter DataTables to display list of items in cart. Now I want to edit the quantity of any selected row. Is there a way to get the information of the row user has tapped?

Following is complete code of my DataTable:

class _DataTableSampleState extends State<DataTableSample> {

  void _getSelectedRowInfo() {
    print('Selected Item Row Name Here...')
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('DataTable Sample'),
      ),
      body: Container(
        child: DataTable(
          onSelectAll: (b) {},
          sortAscending: true,
          columns: <DataColumn>[
            DataColumn(
              label: Text('Item'),
            ),
            DataColumn(
              label: Text('Price'),
            ),
          ],
          rows: items
              .map(
                (itemRow) => DataRow(
                      cells: [
                        DataCell(
                          Text(itemRow.itemName),
                          showEditIcon: false,
                          placeholder: false,
                        ),
                        DataCell(
                          Text(itemRow.itemPrice),
                          showEditIcon: true,
                          placeholder: false,
                          onTap: _getSelectedRowInfo,
                        ),
                      ],
                    ),
              )
              .toList(),
        ),
      ),
    );
  }
}

class ItemInfo {
  String itemName;
  String itemPrice;

  ItemInfo({
    this.itemName,
    this.itemPrice,
  });
}

var items = <ItemInfo>[
  ItemInfo(
    itemName: 'Item A',
    itemPrice: '250',
  ),
  ItemInfo(
    itemName: 'Item B',
    itemPrice: '100',
  ),
  ItemInfo(
    itemName: 'Item C',
    itemPrice: '150',
  ),
];

When edit icon is clicked "_getSelectedRowInfo" method is called. I want to get complete detail of selected/tapped row in this function.

回答1:

you can use onSelectChanged property from DataRow.

rows: items
    .map(
        (itemRow) => DataRow(
            onSelectChanged: (bool selected) {
                if (selected) {
                    log.add('row-selected: ${itemRow.index}');
                }
            },
            cells: [
                // ..
            ],
        ),


回答2:

To Add to the answer provided by @Samuel , There is a possibility to hide the checkboxes as well. You need to create your own copy of DataTable Widget. You can follow this procedure :

  1. create a new file in your project with name my_data_table.dart
  2. copy the source from https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/data_table.dart to the my_data_table.dart
  3. replace all DataTable with MyDataTable in the file.
  4. Replace all DataRow with MyDataRow in the file
  5. Replace all DataCell with MyDataCell in the file
  6. Replace all DataColumn with MyDataColumn in the file
  7. now locate build method in MyDataTable class and change file with text "final bool showCheckboxColumn = rows.any((MyDataRow row) => row.onSelectChanged != null);" to "final bool showCheckboxColumn = false;" and "final bool allChecked = showCheckboxColumn && !rows.any((MyDataRow row) => row.onSelectChanged != null && !row.selected);" to "final bool allChecked = false;"
  8. Now in your file, where you have used DataTable, import file my_data_table.dart and replace DataTable with MyDataTable, DataColumn with MyDataColumn, DataRow with MyDataRow and DataCell with MyDataCell. Your onSelectChanged shall still work without showing any checkboxes.


回答3:

You can get it done by using a closure , a function object that has access to variables in its lexical scope and basically 'remembers' them.

Change the 'onTap' property of your DataCell to :

onTap: (){_getSelectedRowInfo(itemRow.itemName,itemRow.itemPrice);},

and modify the _getSelectedRowInfo function to accommodate the following changes:

void _getSelectedRowInfo(dynamic name,dynamic price) {
    print('Name:$name  price: $price');
  }

Here's how the entire thing should look like:

class _DataTableSampleState extends State<DataTableSample> {

  void _getSelectedRowInfo(dynamic name,dynamic price) {
    print('Name:$name  price: $price');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('DataTable Sample'),
      ),
      body: Container(
        child: DataTable(
          onSelectAll: (b) {},
          sortAscending: true,
          columns: <DataColumn>[
            DataColumn(
              label: Text('Item'),
            ),
            DataColumn(
              label: Text('Price'),
            ),
          ],
          rows: items
              .map(
                (itemRow) => DataRow(
              cells: [
                DataCell(
                  Text(itemRow.itemName),
                  showEditIcon: false,
                  placeholder: false,
                ),
                DataCell(
                  Text(itemRow.itemPrice),
                  showEditIcon: true,
                  placeholder: false,
                  onTap: (){_getSelectedRowInfo(itemRow.itemName,itemRow.itemPrice);},
                ),
              ],
            ),
          )
              .toList(),
        ),
      ),
    );
  }
}

class ItemInfo {
  String itemName;
  String itemPrice;

  ItemInfo({
    this.itemName,
    this.itemPrice,
  });
}

var items = <ItemInfo>[
  ItemInfo(
    itemName: 'Item A',
    itemPrice: '250',
  ),
  ItemInfo(
    itemName: 'Item B',
    itemPrice: '100',
  ),
  ItemInfo(
    itemName: 'Item C',
    itemPrice: '150',
  ),
];


回答4:

Each DataCell has an onTap callback. You could use this without the unhideable checkbox appearing on your table rows. For example

DataCell(Text(itemrow.itemname),
      onTap: () {
// Your code here
})

This works for me. If you want the onTap to work for the entire DataRow instead of only a DataCell, you could just add the logic to the onTap of each DataCell and get the desired result.



回答5:

Try this :

DataTable(
    showCheckboxColumn: false, // <-- this is important
    columns: [
        DataColumn(label: Text('FirstName')),
         DataColumn(label: Text('LastName')),
    ],
     rows:[
        DataRow(
            cells: [
                DataCell(Text(obj['user1'])),
                DataCell(Text(obj['name-a'])),
            ],
            onSelectChanged: (newValue) {
                print('row 1 pressed');
            },
        ),
        DataRow(
            cells: [
                DataCell(Text(obj['user2'])),
                DataCell(Text(obj['name-b'])),
            ],
            onSelectChanged: (newValue) {
                print('row 2 pressed');
            },
        ),
    ]
),

Hope this helps. Thanks