DataTable 中的 Flutter DropdownButton

Flutter DropdownButton in DataTable

我试图让 DataTable 的列之一成为 DropdownButton,用户可以从 DropdownButton select 更改单元格值(而不是任何其他单元格,所以根本不要更改第一列中的值)。

参见下面的示例代码(DropdownButton 不会更改单元格值),也在 DartPad.


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: DataTableDemo(),
    );
  }
}

class User {
  String firstName;
  String lastName;

  User({this.firstName, this.lastName});

  static List<User> getUsers() {
    return <User>[
      User(firstName: "Paul", lastName: "Rudd"),
      User(firstName: "Owen", lastName: "Wilson"),
      User(firstName: "Jonah", lastName: "Hill"),
    ];
  }
}

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

  final String title = "Data Table Flutter Demo";

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

class DataTableDemoState extends State<DataTableDemo> {
  List<User> users;
  

  @override
  void initState() {
    users = User.getUsers();
    super.initState();
  }

  List<String> lastNamesList = <String>[
    'Rudd',
    'Wilson',
    'Hill',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('DropdownButton in DataTable'),
        ),
        body: SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: DataTable(
            columns: [
              DataColumn(
                label: Text("FIRST NAME"),
                numeric: false,
                tooltip: "This is First Name",
              ),
              DataColumn(
                label: Text("LAST NAME"),
                numeric: false,
                tooltip: "This is Last Name",
              ),
            ],
            rows: users
                .map(
                  (user) => DataRow(cells: [
                    DataCell(
                      Text(user.firstName),
                      onTap: () {
                        print('Selected firstName: ${user.firstName}');
                      },
                    ),

                    DataCell(DropdownButton<String>(
                      value: user.lastName,
                      onChanged: (String newValue) {
                        setState(() {
                          //help! 
                        });
                      },
                      items: lastNamesList
                          .map<DropdownMenuItem<String>>((String value) {
                        return DropdownMenuItem<String>(
                          value: value,
                          child: Text(value),
                        );
                      }).toList(),
                    ))
                  ]),
                )
                .toList(),
          ),
        ));
  }
}

您可以复制粘贴 运行 下面的完整代码
第一步:可以用一个ListselectedUser来记录每个选择
第 2 步:使用 selectedUser.asMap().entries.map 得到 index
代码片段

List<User> selectedUser;
...
rows: selectedUser.asMap().entries.map((user) {
              int idx = user.key;
              print(idx);
              return DataRow(cells: [
                DataCell(
                  Text(selectedUser[idx].firstName),
                  onTap: () {
                    print('Selected firstName: ${selectedUser[idx].firstName}');
                  },
                ),
                DataCell(DropdownButton<User>(
                  value: selectedUser[idx],
                  onChanged: (User newUser) {
                    setState(() {
                      selectedUser[idx] = newUser;
                    });
                  },
                  items: users.map<DropdownMenuItem<User>>((User value) {
                    return DropdownMenuItem<User>(
                      value: value,
                      child: Text(value.lastName),
                    );
                  }).toList(),
                ))
              ]);
            }).toList(),

工作演示

完整代码

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: DataTableDemo(),
    );
  }
}

class User {
  String firstName;
  String lastName;

  User({this.firstName, this.lastName});

  static List<User> getUsers() {
    return <User>[
      User(firstName: "Paul", lastName: "Rudd"),
      User(firstName: "Owen", lastName: "Wilson"),
      User(firstName: "Jonah", lastName: "Hill"),
    ];
  }
}

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

  final String title = "Data Table Flutter Demo";

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

class DataTableDemoState extends State<DataTableDemo> {
  List<User> users;
  List<User> selectedUser;

  @override
  void initState() {
    users = User.getUsers();
    selectedUser = List.from(users);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('DropdownButton in DataTable'),
        ),
        body: SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: DataTable(
            columns: [
              DataColumn(
                label: Text("FIRST NAME"),
                numeric: false,
                tooltip: "This is First Name",
              ),
              DataColumn(
                label: Text("LAST NAME"),
                numeric: false,
                tooltip: "This is Last Name",
              ),
            ],
            rows: selectedUser.asMap().entries.map((user) {
              int idx = user.key;
              print(idx);
              return DataRow(cells: [
                DataCell(
                  Text(selectedUser[idx].firstName),
                  onTap: () {
                    print('Selected firstName: ${selectedUser[idx].firstName}');
                  },
                ),
                DataCell(DropdownButton<User>(
                  value: selectedUser[idx],
                  onChanged: (User newUser) {
                    setState(() {
                      selectedUser[idx] = newUser;
                    });
                  },
                  items: users.map<DropdownMenuItem<User>>((User value) {
                    return DropdownMenuItem<User>(
                      value: value,
                      child: Text(value.lastName),
                    );
                  }).toList(),
                ))
              ]);
            }).toList(),
          ),
        ));
  }
}

完整代码 2,第一列值不变

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: DataTableDemo(),
    );
  }
}

class User {
  String firstName;
  String lastName;

  User({this.firstName, this.lastName});

  static List<User> getUsers() {
    return <User>[
      User(firstName: "Paul", lastName: "Rudd"),
      User(firstName: "Owen", lastName: "Wilson"),
      User(firstName: "Jonah", lastName: "Hill"),
    ];
  }
}

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

  final String title = "Data Table Flutter Demo";

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

class DataTableDemoState extends State<DataTableDemo> {
  List<User> users;
  List<User> selectedUser;

  @override
  void initState() {
    users = User.getUsers();
    selectedUser = List.from(users);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('DropdownButton in DataTable'),
        ),
        body: SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: DataTable(
            columns: [
              DataColumn(
                label: Text("FIRST NAME"),
                numeric: false,
                tooltip: "This is First Name",
              ),
              DataColumn(
                label: Text("LAST NAME"),
                numeric: false,
                tooltip: "This is Last Name",
              ),
            ],
            rows: users.asMap().entries.map((user) {
              int idx = user.key;
              print(idx);
              return DataRow(cells: [
                /*DataCell(
                  Text(selectedUser[idx].firstName),
                  onTap: () {
                    print('Selected firstName: ${selectedUser[idx].firstName}');
                  },
                ),*/
                DataCell(
                  Text(user.value.firstName),
                  onTap: () {
                    print('Selected firstName: ${user.value.firstName}');
                  },
                ),
                DataCell(DropdownButton<User>(
                  value: selectedUser[idx],
                  onChanged: (User newUser) {
                    setState(() {
                      selectedUser[idx] = newUser;
                    });
                  },
                  items: users.map<DropdownMenuItem<User>>((User value) {
                    return DropdownMenuItem<User>(
                      value: value,
                      child: Text(value.lastName),
                    );
                  }).toList(),
                ))
              ]);
            }).toList(),
          ),
        ));
  }
}