Browse Source

实现多选框数据驱动

loki.wu 2 years ago
parent
commit
27c68cc438

+ 0 - 67
lib/pages/components/multi_select.dart

@@ -1,67 +0,0 @@
-// Multi Select widget
-// This widget is reusable
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-
-class MultiSelect extends StatefulWidget {
-  final List<String> items;
-  const MultiSelect({Key? key, required this.items}) : super(key: key);
-
-  @override
-  State<StatefulWidget> createState() => _MultiSelectState();
-}
-
-class _MultiSelectState extends State<MultiSelect> {
-  // this variable holds the selected items
-  final List<String> _selectedItems = [];
-
-// This function is triggered when a checkbox is checked or unchecked
-  void _itemChange(String itemValue, bool isSelected) {
-    setState(() {
-      if (isSelected) {
-        _selectedItems.add(itemValue);
-      } else {
-        _selectedItems.remove(itemValue);
-      }
-    });
-  }
-
-// this function is called when the Cancel button is pressed
-  void _cancel() {
-    Navigator.pop(context);
-  }
-
-// this function is called when the Submit button is tapped
-  void _submit() {
-    Navigator.pop(context, _selectedItems);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return AlertDialog(
-      title: const Text('Select Topics'),
-      content: SingleChildScrollView(
-        child: ListBody(
-          children: widget.items
-              .map((item) => CheckboxListTile(
-                    value: _selectedItems.contains(item),
-                    title: Text(item),
-                    controlAffinity: ListTileControlAffinity.leading,
-                    onChanged: (isChecked) => _itemChange(item, isChecked!),
-                  ))
-              .toList(),
-        ),
-      ),
-      actions: [
-        TextButton(
-          child: const Text('Cancel'),
-          onPressed: _cancel,
-        ),
-        ElevatedButton(
-          child: const Text('Submit'),
-          onPressed: _submit,
-        ),
-      ],
-    );
-  }
-}

+ 50 - 28
lib/pages/components/multi_selected.dart

@@ -25,8 +25,8 @@ class _RRMultiSelectedState extends State<RMultiSelected> {
   _RRMultiSelectedState();
   final String _value = '';
   String? _selectedItemView = '';
-  List<String>? _items = [];
-  final List<String>? _selectedItems = [];
+  List<String> _items = [];
+  List<String> _selectedItems = [];
   double _width = 0.0;
   MulitiSelectedInfo? _mulitiSelectedInfo;
 
@@ -66,7 +66,7 @@ class _RRMultiSelectedState extends State<RMultiSelected> {
   }
 
   List<DropdownMenuItem<String>> buildItems() {
-    return _items!.map((String e) {
+    return _items.map((String e) {
       final active = e == _value;
       return DropdownMenuItem<String>(
         child: _OptionRow(
@@ -76,41 +76,39 @@ class _RRMultiSelectedState extends State<RMultiSelected> {
           height: 22,
           onTap: () {
             setState(() {
-              if (_selectedItems!.contains(e)) {
-                _selectedItems!.remove(e);
-              } else {
-                _selectedItems!.add(e);
-              }
-              String text = '';
-              for (var element in _selectedItems!) {
-                final index = _selectedItems!.indexOf(element);
-                if (index > 0) {
-                  text = text + ',' + element;
-                } else if (index == 0) {
-                  text = element;
-                } else if (_selectedItems!.isEmpty) {
-                  text = '';
-                }
-              }
-              _selectedItemView = text;
-              final width = TextSizeConvert.getTextSize(text, _textStyle).width;
-              if (_width < width - 25) {
-                // _width = width - 25;
-              }
+              _onSelectedItem(e);
             });
             if (_mulitiSelectedInfo != null) {
               _mulitiSelectedInfo!.selectedItems = _selectedItems;
             }
           },
-          isSelected: _selectedItems!.contains(e),
+          isSelected: _selectedItems.contains(e),
         ),
         value: e,
       );
     }).toList();
   }
 
+  _onSelectedItem(String value) {
+    setState(() {
+      if (_selectedItems.contains(value)) {
+        _selectedItems.remove(value);
+      } else {
+        _selectedItems.add(value);
+      }
+      String text = '';
+      _getSelectedItems();
+      final width =
+          TextSizeConvert.getTextSize(_selectedItemView ?? '', _textStyle)
+              .width;
+      if (_width < width - 25) {
+        // _width = width - 25;
+      }
+    });
+  }
+
   Widget _buildDropdownButton() {
-    if (_items!.isEmpty) {
+    if (_items.isEmpty) {
       return const SizedBox();
     }
     var buttonDecoration = BoxDecoration(
@@ -140,7 +138,7 @@ class _RRMultiSelectedState extends State<RMultiSelected> {
           buttonDecoration: buttonDecoration,
           offset: const Offset(0, -4),
           selectedItemHighlightColor: Theme.of(context).secondaryHeaderColor,
-          selectedItemBuilder: (_) => _selectedItems!.map((e) {
+          selectedItemBuilder: (_) => _selectedItems.map((e) {
             return SizedBox(
               width: _width - 34,
               child: Text(
@@ -161,10 +159,19 @@ class _RRMultiSelectedState extends State<RMultiSelected> {
     final multiSelected = widget.multiSelected;
     final selectInfo = ReportInfo.instance.getElementInfo(multiSelected);
     if (selectInfo != null && _mulitiSelectedInfo != selectInfo) {
+      if (_mulitiSelectedInfo != null) {
+        _mulitiSelectedInfo!.onSelectedChange.dispose();
+      }
       _mulitiSelectedInfo = selectInfo as MulitiSelectedInfo;
+      _mulitiSelectedInfo!.onSelectedChange.addListener((sender, e) {
+        setState(() {
+          _selectedItems = e;
+          _getSelectedItems();
+        });
+      });
     }
     if (multiSelected.items!.isNotEmpty) {
-      _items = multiSelected.items;
+      _items = multiSelected.items!;
     }
     _width = PtToPxConverter.ptToPx(multiSelected.lineWidth);
     final fontColor = multiSelected.fontColor ?? RTColor.Black;
@@ -174,6 +181,21 @@ class _RRMultiSelectedState extends State<RMultiSelected> {
       fontSize: PtToPxConverter.ptToPx(multiSelected.fontSize),
     );
   }
+
+  void _getSelectedItems() {
+    String text = '';
+    for (var element in _selectedItems) {
+      final index = _selectedItems.indexOf(element);
+      if (index > 0) {
+        text = text + ',' + element;
+      } else if (index == 0) {
+        text = element;
+      } else if (_selectedItems.isEmpty) {
+        text = '';
+      }
+    }
+    _selectedItemView = text;
+  }
 }
 
 class _OptionRow extends StatefulWidget {

+ 0 - 16
lib/pages/paragraph_page.dart

@@ -3,7 +3,6 @@ import 'package:fis_lib_report/pages/components/datetime.dart';
 import 'package:fis_lib_report/pages/components/input_image.dart';
 import 'package:fis_lib_report/pages/components/input_text.dart';
 import 'package:fis_lib_report/pages/components/line.dart';
-import 'package:fis_lib_report/pages/components/multi_select.dart';
 import 'package:fis_lib_report/pages/components/multi_selected.dart';
 import 'package:fis_lib_report/pages/components/page_number.dart';
 import 'package:fis_lib_report/pages/components/single_select.dart';
@@ -163,19 +162,4 @@ class _ParagraphState extends State<ParagraphPage> {
       ),
     );
   }
-
-  void _showMultiSelect(List<String>? items) async {
-    // a list of selectable items
-    // these items can be hard-coded or dynamically fetched from a database/API
-    if (items!.isEmpty) {
-      return;
-    }
-
-    final List<String>? results = await showDialog(
-      context: context,
-      builder: (BuildContext context) {
-        return MultiSelect(items: items);
-      },
-    );
-  }
 }

+ 14 - 1
lib/report_info/multi_selected_info.dart

@@ -1,13 +1,26 @@
+import 'package:fis_lib_report/converts/event_type.dart';
 import 'package:fis_lib_report/report/interfaces/element.dart';
 import 'package:fis_lib_report/report/multiSelected.dart';
 import 'package:fis_lib_report/report_info/text_element_info.dart';
 
 class MulitiSelectedInfo extends TextElementInfo {
+  ///是否只读
   bool? isReadOnly = false;
 
+  ///所有待选项
   List<String>? items = [];
 
-  List<String>? selectedItems = [];
+  ///选中项集合
+  List<String> get selectedItems => _selectedItems;
+  set selectedItems(List<String> v) {
+    _selectedItems = v;
+    onSelectedChange.emit(this, v);
+  }
+
+  ///选中项改变通知UI变化
+  FEventHandler<List<String>> onSelectedChange = FEventHandler<List<String>>();
+
+  List<String> _selectedItems = [];
 
   MulitiSelectedInfo.fromElement(MultiSelected element)
       : super.fromElement(element) {

+ 12 - 0
lib/report_info/report_info.dart

@@ -7,6 +7,7 @@ import 'package:fis_lib_report/report_info/element_info.dart';
 import 'package:fis_lib_report/report_info/input_image_info.dart';
 import 'package:fis_lib_report/report_info/input_image_list_info.dart';
 import 'package:fis_lib_report/report_info/input_text_info.dart';
+import 'package:fis_lib_report/report_info/multi_selected_info.dart';
 import 'package:fis_lib_report/report_info/paragraph_info.dart';
 import 'package:fis_lib_report/report_info/report_base_info.dart';
 import 'package:fis_lib_report/report_info/report_event_args.dart';
@@ -176,6 +177,17 @@ class ReportInfo extends ReportBaseInfo {
           final inputInfo = info as SingleSelectedInfo;
           inputInfo.selectedItem = map['SelectedItem'];
         }
+      } else if (jsonType.name == ElementType.multiSelected.name) {
+        final info = getElementInfoById(id);
+        if (info != null) {
+          final inputInfo = info as MulitiSelectedInfo;
+          List<String> list = [];
+          final items = map['SelectedItems'];
+          for (var i in items) {
+            list.add(i.toString());
+          }
+          inputInfo.selectedItems = list;
+        }
       }
     }
   }