Flutter как заставить этот класс возвращать OnChanged?

#class #flutter #listview #dart

#класс #flutter #listview #dart

Вопрос:

Я использовал некоторые классы онлайн, чтобы отредактировать их и создать то, что мне было нужно, вот что я получил, однако мне нужно получить данные с помощью функции onChange, чтобы я мог использовать их в разных формах в приложении.

Как бы я мог это сделать? Это код класса:

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

import 'flutter_search_pannel/flutter_search_panel.dart';
import 'flutter_search_pannel/search_item.dart';

class SuspendedListPicker extends StatefulWidget {
  SuspendedListPicker({
    this.data,
    this.onChanged,
  });

  List<SearchItem<int>> data = [];
  final Function onChanged;

  @override
  _MyAppState createState() => new _MyAppState(data);
}

class _MyAppState extends State<SuspendedListPicker> {
  _MyAppState(this.data);
  List<SearchItem<int>> data = [];
  var selected;
  @override
  Widget build(BuildContext context) {
    return Container(
        width: MediaQuery.of(context).size.width * 0.55,
        child: FlutterSearchPanel<int>(
          title: "Selecione",
          data: data,

          //padding: EdgeInsets.all(10.0),
          icon: Icon(Icons.label, color: Colors.blue[300]),
          color: Colors.white,

          textStyle: TextStyle(
            color: Colors.black,
            fontSize: 28.0,
            // onChanged: (value) {
            //   print(value);
            // },
          ),
        ));
  }
}
  

И вот ресурс Flutter_search_panel, который я также изменил (это импорт изhttps://pub.dev/packages/flutter_search_panel)

 import 'package:flutter/material.dart';
import 'search_page.dart';
import 'search_item.dart';

class FlutterSearchPanel<TValue> extends StatefulWidget {
  @required
  final Function onChanged;
  @required
  final List<SearchItem<TValue>> data;
  final String title;
  final Icon icon;
  final TextStyle textStyle;
  final Color color;
  final EdgeInsetsGeometry padding;
  final TValue selected;

  FlutterSearchPanel(
      {this.onChanged,
      this.title,
      this.data,
      this.icon,
      this.textStyle,
      this.selected,
      this.padding,
      this.color});

  @override
  State<StatefulWidget> createState() {
    return new _FlutterSearchPanelState<TValue>();
  }
}

class _FlutterSearchPanelState<TValue>
    extends State<FlutterSearchPanel<TValue>> {
  SearchItem<TValue> selection;
  final _defaultIcon = Icons.label;
  final TextStyle _defaultTextStyle =
      new TextStyle(color: Colors.red, fontSize: 22.0);
  final Color _defaultColor = Colors.red;
  final EdgeInsetsGeometry _defaultPadding = EdgeInsets.all(10.0);

  @override
  void initState() {
    super.initState();
    if (widget.selected != null) {
      selection = widget.data.firstWhere(
          (item) => item.value == widget.selected,
          orElse: () => selection = widget.data[0]);
    } else {
      selection = widget.data[0];
    }
  }

  @override
  void dispose() {
    super.dispose();
  }

  _openSearchPage() async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(
          builder: (context) => SearchPage(
              title: widget.title,
              data: widget.data,
              icon: widget.icon ?? _defaultIcon,
              padding: widget.padding ?? _defaultPadding,
              color: widget.color ?? _defaultColor,
              textStyle: widget.textStyle ?? _defaultTextStyle)),
    );

    if (result != null) {
      setState(() {
        selection = resu<
      });
      if (widget.onChanged != null) {
        widget.onChanged((result as SearchItem<TValue>).value);
      }
    }
  }

  @override
  Widget build(BuildContext context) => new InkWell(
    onTap: _openSearchPage,
    child: SizedBox(
    //height: MediaQuery.of(context).size.height,
    child: Container(
        decoration: BoxDecoration(
            border: Border.all(color: Colors.black)),
            child: Text(
                selection.text,

                textAlign: TextAlign.right,
                style: widget.textStyle ?? Theme.of(context).textTheme.button, 
            ),
        ),
    ),
);
}


// RaisedButton(
//         color: widget.color ?? Colors.blue,
//         child: Flex(
//           direction: Axis.horizontal,
//           mainAxisSize: MainAxisSize.min,
//           children: <Widget>[
//             Flexible(
//               child: Padding(
//                 padding: const EdgeInsets.all(10.0),
//                 child: Text(
//                   selection.text,
//                   style: widget.textStyle ?? Theme.of(context).textTheme.button, textAlign: TextAlign.right,
//                 ),
//               ),
//             ),
//           ],
//         ),
//         padding: widget.padding,
//         onPressed: _openSearchPage,
//       );
  

Комментарии:

1. Этот список searchitem<int>, откуда он берется?

2. панель поиска flutter, разрешите обновить с помощью ресурса, который мне также пришлось изменить, но импорт оттуда

3. По сути, значением будет выбор, сделанный пользователем. Затем вы можете просто установить свойство onchanged для вашей функции onchanged, передающей значение. OnChanged: (значение) => OnChanged(значение). Убедитесь, что вы приняли значение в качестве типа в параметрах для вашего OnChanged souce. Кстати, ваше свойство data установлено как в вашем виджете, так и в классах состояний. Удалите тот, который находится в вашем классе состояния, поскольку он передается в вашем конструкторе виджетов.

Ответ №1:

Вы можете скопировать вставить запустить полный код ниже,
вы можете в onChanged вызове widget.onChanged(value)
И определите переменную currentValue для получения этого value
фрагмент кода

 class _SuspendedListPickerState extends State<SuspendedListPicker> {
  @override
  Widget build(BuildContext context) {
    return Container(
        width: MediaQuery.of(context).size.width * 0.55,
        child: FlutterSearchPanel<int>(
          title: "Selecione",
          data: widget.data,
          //padding: EdgeInsets.all(10.0),
          icon: Icon(Icons.label, color: Colors.blue[300]),
          color: Colors.white,
          textStyle: TextStyle(color: Colors.black, fontSize: 28.0),
          onChanged: (value) {
            widget.onChanged(value);
          },
        ));
  }
}
...
int currentValue;
...
SuspendedListPicker(
  data: data,
  onChanged: (value) {
    setState(() {
      currentValue = value;
    });
  },
),
Text('current value $currentValue'),
  

рабочая демонстрация

введите описание изображения здесь

полный код

 import 'package:flutter/material.dart';

class SearchItem<TValue> {
  /// Item value
  final TValue value;

  /// Item display text
  final String text;

  SearchItem(this.value, this.text);
}

class SearchPage extends StatefulWidget {
  final List<SearchItem> data;
  final Icon icon;
  final TextStyle textStyle;
  final Color color;
  final EdgeInsetsGeometry padding;
  final String title;

  SearchPage(
      {this.data,
      this.icon,
      this.textStyle,
      this.padding,
      this.color,
      this.title});

  @override
  State<StatefulWidget> createState() {
    return new _SearchPageState();
  }
}

class _SearchPageState extends State<SearchPage> {
  TextEditingController controller = new TextEditingController();
  List<SearchItem> _searchList = [];

  List<SearchItem> _dataList = [];
  @override
  void initState() {
    super.initState();
    _dataList = widget.data;
  }

  @override
  void dispose() {
    _searchList.clear();
    controller.dispose();
    super.dispose();
  }

  _onChange(SearchItem selection) {
    Navigator.pop(context, selection);
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        backgroundColor: widget.color,
        title: new Text(widget.title ?? 'Search Page'),
        elevation: 0.0,
      ),
      body: new Column(
        children: <Widget>[
          new Container(
            color: widget.color,
            child: new Padding(
              padding: widget.padding,
              child: new Card(
                child: new ListTile(
                  leading: new Icon(Icons.search),
                  title: new TextField(
                    controller: controller,
                    decoration: new InputDecoration(
                        hintText: 'Search', border: InputBorder.none),
                    onChanged: onSearchTextChanged,
                  ),
                  trailing: new IconButton(
                    icon: new Icon(Icons.cancel),
                    onPressed: () {
                      controller.clear();
                      onSearchTextChanged('');
                    },
                  ),
                ),
              ),
            ),
          ),
          new Expanded(
            child: _searchList.length != 0 || controller.text.isNotEmpty
                ? new ListView.builder(
                    itemCount: _searchList.length,
                    itemBuilder: (context, i) {
                      return new Card(
                        color: widget.color,
                        child: FlatButton(
                          onPressed: () {
                            Navigator.pop(context, _searchList[i]);
                          },
                          child: new ListTile(
                            leading: widget.icon,
                            title: new Text(_searchList[i].text,
                                style: widget.textStyle),
                          ),
                        ),
                        margin: const EdgeInsets.all(0.0),
                      );
                    },
                  )
                : new ListView.builder(
                    itemCount: _dataList.length,
                    itemBuilder: (context, index) {
                      return new Card(
                        color: widget.color,
                        child: FlatButton(
                            onPressed: () {
                              _onChange(_dataList[index]);
                            },
                            child: new ListTile(
                              leading: widget.icon,
                              title: new Text(
                                _dataList[index].text,
                                style: widget.textStyle,
                              ),
                            )),
                        margin: const EdgeInsets.all(0.0),
                      );
                    },
                  ),
          ),
        ],
      ),
    );
  }

  onSearchTextChanged(String text) async {
    _searchList.clear();
    if (text.isEmpty) {
      setState(() {});
      return;
    }

    _dataList.forEach((userDetail) {
      if (userDetail.text.startsWith(text.toLowerCase()) ||
          userDetail.text.toLowerCase().startsWith(
              text.toLowerCase())) if (_searchList.contains(userDetail) ==
          false) {
        _searchList.add(userDetail);
      }
    });

    setState(() {});
  }
}

class FlutterSearchPanel<TValue> extends StatefulWidget {
  @required
  final Function onChanged;
  @required
  final List<SearchItem<TValue>> data;
  final String title;
  final Icon icon;
  final TextStyle textStyle;
  final Color color;
  final EdgeInsetsGeometry padding;
  final TValue selected;

  FlutterSearchPanel(
      {this.onChanged,
      this.title,
      this.data,
      this.icon,
      this.textStyle,
      this.selected,
      this.padding,
      this.color});

  @override
  State<StatefulWidget> createState() {
    return new _FlutterSearchPanelState<TValue>();
  }
}

class _FlutterSearchPanelState<TValue>
    extends State<FlutterSearchPanel<TValue>> {
  SearchItem<TValue> selection;
  final _defaultIcon = Icons.label;
  final TextStyle _defaultTextStyle =
      new TextStyle(color: Colors.red, fontSize: 22.0);
  final Color _defaultColor = Colors.red;
  final EdgeInsetsGeometry _defaultPadding = EdgeInsets.all(10.0);

  @override
  void initState() {
    super.initState();
    if (widget.selected != null) {
      selection = widget.data.firstWhere(
          (item) => item.value == widget.selected,
          orElse: () => selection = widget.data[0]);
    } else {
      selection = widget.data[0];
    }
  }

  @override
  void dispose() {
    super.dispose();
  }

  _openSearchPage() async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(
          builder: (context) => SearchPage(
              title: widget.title,
              data: widget.data,
              icon: widget.icon ?? _defaultIcon,
              padding: widget.padding ?? _defaultPadding,
              color: widget.color ?? _defaultColor,
              textStyle: widget.textStyle ?? _defaultTextStyle)),
    );

    if (result != null) {
      setState(() {
        selection = resu<
      });
      if (widget.onChanged != null) {
        widget.onChanged((result as SearchItem<TValue>).value);
      }
    }
  }

  @override
  Widget build(BuildContext context) => new InkWell(
        onTap: _openSearchPage,
        child: SizedBox(
          //height: MediaQuery.of(context).size.height,
          child: Container(
            decoration: BoxDecoration(border: Border.all(color: Colors.black)),
            child: Text(
              selection.text,
              textAlign: TextAlign.right,
              style: widget.textStyle ?? Theme.of(context).textTheme.button,
            ),
          ),
        ),
      );
}

class SuspendedListPicker extends StatefulWidget {
  SuspendedListPicker({
    Key key,
    this.data,
    this.onChanged,
  }) : super(key: key);

  List<SearchItem<int>> data = [];
  final Function onChanged;

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

class _SuspendedListPickerState extends State<SuspendedListPicker> {
  @override
  Widget build(BuildContext context) {
    return Container(
        width: MediaQuery.of(context).size.width * 0.55,
        child: FlutterSearchPanel<int>(
          title: "Selecione",
          data: widget.data,
          //padding: EdgeInsets.all(10.0),
          icon: Icon(Icons.label, color: Colors.blue[300]),
          color: Colors.white,
          textStyle: TextStyle(color: Colors.black, fontSize: 28.0),
          onChanged: (value) {
            widget.onChanged(value);
          },
        ));
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int currentValue;
  List<SearchItem<int>> data = [
    SearchItem(0, 'This'),
    SearchItem(1, 'is'),
    SearchItem(2, 'a'),
    SearchItem(3, 'test'),
    SearchItem(4, '.'),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SuspendedListPicker(
              data: data,
              onChanged: (value) {
                setState(() {
                  currentValue = value;
                });
              },
            ),
            Text('current value $currentValue'),
          ],
        ),
      ),
    );
  }
}