繁体   English   中英

Flutter - 如何使用 BloC 实现下拉列表?

[英]Flutter - How to implement a Dropdown List using BloC?

我想在我的应用程序中添加一个包含“名称”的下拉列表,而不是像我在下面的代码中那样的 TextField。 我怎样才能使用 BloC 做到这一点?

class PersonPage extends StatefulWidget {

  PersonPage(this.person);
  final Person person;

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

class Names{
  const Item(this.name);
  final String name;
}

class _PersonPageState extends State<PersonPage> {
  Item selectedUser;
  List<Item> names = <Names>[
   const Item('Thomas'),
   const Item('John'),
   const Item('Mary'),
   const Item('Lukas'),
  ];
 TextEditingController _nameController;

 final _bloc = PersonBloc();

 @override
 void initState() {

  _bloc.setPerson(widget.person);
  _nameController = TextEditingController(text: widget.person.name);

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

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("MyApp"),
    ),
    body: Container(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: ListView(
          children: <Widget>[             
            Container(
              child: TextField(
                decoration: InputDecoration(labelText: "Name"),
                controller: _nameController,
                onChanged: _bloc.setName,
              ),
            ),
            Container(
              height: 20,
            ),              
            RaisedButton(
              child: Text("Save"),
              onPressed: () {
                if (_bloc.insertOrUpdate()) {
                  Navigator.pop(context);
                }
              },
            )
          ],
        ),
      ),
    ),
  );
}

谢谢。

我会给你一个例子,你尝试在你的代码中应用

class _PersonPageState extends State<PersonPage> {
  final _bloc = PersonBloc();

  @override
  void initState() {

    _bloc.setPerson(widget.person);
    _nameController = TextEditingController(text: widget.person.name);

   super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("MyApp"),
    ),
    body: Container(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: ListView(
          children: <Widget>[             
            StreamBuilder(
              stream: bloc.outName,
              builder: (context, snapshot) {
                if (!snapshot.hasData)
                  return Container();

                return DropdownButton(
                  hint: Text("Names"),
                  value: snapshot.data,
                  items: bloc.names.map((item) {
                    return DropdownMenuItem(
                      value: item,
                      child: Row(children: <Widget>[Text(item),]),
                    );
                  }).toList(),
                  onChanged: bloc.inName,
                );
              },
            ),
            Container(
              height: 20,
            ),              
            RaisedButton(
              child: Text("Save"),
              onPressed: () {
                if (_bloc.insertOrUpdate()) {
                  Navigator.pop(context);
                }
              },
            )
          ],
        ),
      ),
    ),
  );
}

将您的姓名列表更改为您的 BLoC,并创建名称BehaviorSubject

PersonBloc{

  List<String> names = ['Thomas', 'John', 'Mary', 'Lukas'];

  final _name = BehaviorSubject<String>.seeded("");
  Stream<String> get outName  => _name.stream;
  Function(String) get inName => _name.sink.add;
  //TODO - Don't forget to dispose this _name

}

现在您的_name具有选定的名称,要获取名称,您只需要执行

Person.name = _name.stream.value;

这个例子可以改进,只是草稿

这是 model 的空安全示例:

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const CountryPage(),
    );
  }
}

class CountryPage extends StatefulWidget {
  const CountryPage({Key? key}) : super(key: key);

  @override
  State<CountryPage> createState() => _CountryPageState();
}

class _CountryPageState extends State<CountryPage> {
  final _bloc = CountryBloc();

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("MyApp"),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Container(
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(8.0),
              border: Border.all(width: 1.2, color: Colors.grey)),
          child: CustomDropDown(bloc: _bloc),
        ),
      ),
    );
  }
}

class CustomDropDown extends StatelessWidget {
  const CustomDropDown({
    Key? key,
    required CountryBloc bloc,
  })  : _bloc = bloc,
        super(key: key);

  final CountryBloc _bloc;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: _bloc.streamReference,
      builder: (context, snapshot) {
        if (!snapshot.hasData) return Container();
        return DropdownButton(
          isExpanded: true,
          hint: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text("${_bloc.getCountry.name}"),
          ),
          underline: const SizedBox(),
          icon: const Icon(Icons.keyboard_arrow_down, size: 32.0),
          items: _bloc.countries.map((item) {
            return DropdownMenuItem(
              value: item,
              child: Directionality(
                textDirection: Directionality.of(context).index == 0
                    ? TextDirection.rtl
                    : TextDirection.ltr,
                child: Container(
                  margin: const EdgeInsets.only(bottom: 4.0),
                  decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(8.0),
                      border: Border.all(width: 1.2, color: Colors.grey)),
                  child: Align(
                      alignment: AlignmentDirectional.centerStart,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 4.0),
                        child: Text("${item.name}"),
                      )),
                ),
              ),
            );
          }).toList(),
          onChanged: (value) {
            _bloc.selectCountry(value as ObjectModel);
          },
        );
      },
    );
  }
}

class CountryBloc {
  List<ObjectModel> countries = [
    ObjectModel(id: "0", name: 'USA'),
    ObjectModel(id: "1", name: 'CHINA'),
    ObjectModel(id: "2", name: 'INDIA'),
    ObjectModel(id: "3", name: 'BRAZIL'),
  ];

  final _country = BehaviorSubject<ObjectModel>.seeded(
      ObjectModel(id: "-1", name: "Select Country Name.."));

  Stream<ObjectModel> get streamReference => _country.stream;

  Function(ObjectModel) get selectCountry => _country.sink.add;

  ObjectModel get getCountry => _country.value;

  void setCountry(ObjectModel country) {
    _country.value = country;
  }
}

class ObjectModel {
  String? id;
  String? name;

  ObjectModel({this.id, this.name});

  ObjectModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id'] = id;
    data['name'] = name;
    return data;
  }
}

将此依赖项添加到 pubspec.yaml 文件:

  flutter_bloc: ^7.1.0
  rxdart: ^0.27.5

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM