美文网首页
Flutter表单及异步

Flutter表单及异步

作者: 落寞1990 | 来源:发表于2023-08-20 17:07 被阅读0次

1、Flutter 表单
Flutter中常见的表单有TextField单行文本框,TextField多行文本框、CheckBox、Radio、Switch
CheckboxListTile、RadioListTile、SwitchListTile、Slide。
TextField表单常见属性:


image.png

listview中常见TextField的边框设置无效,需要进行特别处理

class _HomePage extends State<HomePage> {
  late String username;
  late String password;
  late TextEditingController textEditingController;
  @override
  void initState() {
    super.initState();
    //TextEditingController 配置初始化值
    textEditingController =
        TextEditingController.fromValue(const TextEditingValue(text: "贾先生"));
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: ListView(children: <Widget>[
          TextField(
            controller: textEditingController,
            decoration: const InputDecoration(
                hintText: "用户名", border: OutlineInputBorder()),
            //获取输入框的值
            onChanged: (value) {
              setState(() {
                username = value;
              });
            },
          ),
          const SizedBox(height: 20),
          TextField(
              obscureText: true,
              //获取输入框的值
              onChanged: (value) {
                setState(() {
                  password = value;
                });
              },
              decoration: const InputDecoration(
                  hintText: "密码",
                  border: OutlineInputBorder(),
                  suffixIcon: Icon(Icons.visibility))),
          const SizedBox(height: 20),
          TextField(
              decoration: InputDecoration(
                  hintText: "搜索",
                  //常规边框做法
                  // border: OutlineInputBorder(
                  //     borderRadius: BorderRadius.circular(5),
                  // borderSide: const BorderSide(
                  //     width: 1,
                  //     color: Colors.red,
                  //     style: BorderStyle.solid)),
                  //列表中边框特别处理
                  enabledBorder: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10.0),
                      borderSide: const BorderSide(
                          color: Colors.red,
                          width: 0.5,
                          style: BorderStyle.solid)),
                  focusedBorder: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10.0),
                      borderSide: const BorderSide(
                          color: Colors.red,
                          width: 0.5,
                          style: BorderStyle.solid)),
                  suffixIcon: const Icon(Icons.close))),
          const SizedBox(height: 40),
          const TextField(
              decoration: InputDecoration(
                  icon: Icon(Icons.add),
                  prefixIcon: Icon(Icons.lock),
                  prefixText: "http://")),
        ]),
      ),
    );
  }

2、Radio单选按钮组及RadioListTile单选按钮组

class _RadioPagerState extends State<RadioPager> {
  int sex = 1;
  changeStatus(value) {
    setState(() {
      sex = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Row(
              children: [
                const Text( "男",style: TextStyle(fontSize: 19),),
                Radio(value: 1, groupValue: sex, onChanged: changeStatus),
                const SizedBox(width: 20,),
                const Text("女"),
                Radio(value: 2, groupValue: sex, onChanged: changeStatus),
              ],
            ),
            const SizedBox(height: 20,),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [Text(sex == 1 ? "男" : "女"),],
            ),
            const SizedBox(height: 20,),
            RadioListTile(
                title: const Text("男"),
                value: 1,
                groupValue: sex,
                onChanged: changeStatus),
            RadioListTile(
                title: const Text("女"),
                value: 2,
                groupValue: sex,
                onChanged: changeStatus),
          ]),
    );
  }
}

3、Radio单选按钮组及RadioListTile单选按钮组

\\Radio单选及switch
Checkbox(value: flag, onChanged: changeStatus),
                Switch(
                  value: flag,
                  onChanged: (v) {
                    setState(() {
                      flag = v;
                    });
                  },
                ),
\\RadioListTile单选按钮组
class _RadioPagerState extends State<RadioPager> {
  final List hobby = [
    {"checked": true, "title": "吃饭"},
    {"checked": false, "title": "睡觉"},
    {"checked": true, "title": "写代码"}
  ];

  List<Widget> getHobby() {
    List<Widget> tempList = [];
    for (var i = 0; i < hobby.length; i++) {
      tempList.add(CheckboxListTile(
          value: hobby[i]["checked"],
          title: Text(hobby[i]["title"]),
          onChanged: (value) {
            setState(() {
              hobby[i]["checked"] = value;
            });
          }));
    }
    return tempList;
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ListView(
        children: [
          Column(children: getHobby(),),
          ElevatedButton(
              onPressed: () {
                print(hobby);
              },
              child: const Text("获取数据"))
        ],
      ),
    );
  }
}

4、进度条

children: [
            CircularProgressIndicator(
              valueColor: AlwaysStoppedAnimation(Colors.red),
              backgroundColor: Colors.white,
              strokeWidth: 5,
            ),
            SizedBox( height: 20,),
            LinearProgressIndicator(
              valueColor: AlwaysStoppedAnimation(Colors.red),
              backgroundColor: Colors.white,
            ),
            SizedBox(height: 20,),
            LinearProgressIndicator(
              value: 0.9,
              valueColor: AlwaysStoppedAnimation(Colors.blue),
              backgroundColor: Colors.grey,
            ),
            SizedBox( height: 20,),
            CupertinoActivityIndicator(
              radius: 50,
            ),
          ]

5、Future
Future 是一个泛型,其中T代表的是我们耗时操作返回的具体值,如Future 表示一个未来的字符串,
Future表示一个未来的布尔值,如果不需要返回值,可以使用Future。

class _ProgressPagerState extends State<ProgressPager> {
  int number = 0;
  Future<int> getNetworkData() {
    // 返回一个指定值的Future
    // return Future.value("测试");
    // 返回一个延时执行的Future
    // return Future.delayed(const Duration(milliseconds: 2000), () {
    //   return "你好flutter";
    // });
    // 返回异步的function
    return Future(() {
      return 123;
    });
  }

  void incrementCounter() {
    getNetworkData()
        .then((value) {
          return value * 2;
        })
        .then((value) => print(value))
        .whenComplete(() => print("完成"));
    print("执行");
    setState(() {
      number++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("异步"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: incrementCounter,
        child: const Icon(Icons.add),
      ),
      body: Center(
        child: Text("$number"),
      ),
    );
  }
}

async和await关键字来处理future 异步变同步
作用:

  1. async:在方法体前面是使用,定义该方法为一个异步方法。
  2. await:等待并获得异步表达式的执行结果,并且给关键字只能在async修饰的方法中。
  void incrementCounter() async {
    var retult = await getNetworkData();
    print(retult);
    setState(() {
      number++;
    });
  }

6、FutureBuilder
FutureBuilder是一个可以自动追踪Future的状态并在其状态改变的时候自动重绘的组件。

class _ProgressPagerState extends State<ProgressPager> {
  Future<String> loadData() async {
    await Future.delayed(const Duration(milliseconds: 2000));
    // throw "404 data not found"; // 若需测试异常情况,可把注释去掉
    return "this is server data"; // 正常返回数据
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("异步"),
      ),
      body: FutureBuilder(
        future: loadData(),
        initialData: "我是一个初始值",
        builder: (context, snapshot) {
          // if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.hasError) {
            return Center(child: Text("Error:${snapshot.error}"));
          } else {
            return Center(child: Text("Data:${snapshot.data}"));
          }
          // } else {
          //   return const Center(
          //     child: CircularProgressIndicator(),
          //   );
          // }
        },
      ),
    );
  }
}

7、Stream 、StreamBuilder
Future在未来只会获取一个值。Stream的字面意思是水流,
Stream不像Future那样只会在未来获取一个值,它可以异步获取0个或者多个值。如果说Future是一个
异步版本的int或者String,Stream则更像是异步版本的列表,List,List,列表里面可能会有0个或者多个
元素。
StreamBuilder
在 Flutter 中,StreamBuilder 是一个将 Stream 流与 Widget结合到一起的组件,可实现组件的局部数
据更新 , StreamBuilder 组件和FutureBuilder组件比较相似,不同点在于它是一个可以自动跟踪
Stream(数据流或事件流)的状态,并在Stream有变化时自动重绘的组件。Stream不同于Future,可
能会在生命周期内释放出任意数量的数据值(正常)或者错误信息(异常),通常被用于读取文件或者
下载网络资源等操作,也有时候用于状态管理。
StreamBuilder主要功能:
1、实现局部刷新
2、读取流实现读取文件或者下载网络资源等操作
3、父子组件之间的数据广播

 Stream<int> counter() {
    return Stream.periodic(const Duration(milliseconds: 2000), (value) {
      return value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("异步"),
      ),
      body: StreamBuilder(
        stream: counter(),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
              return const Center(
                child: Text("NONE: 没有数据流"),
              );
            case ConnectionState.waiting:
              return const Center(child: Text("WAITING: 等待数据流"));
            case ConnectionState.active:
              if (snapshot.hasError) {
                return Center(
                    child: Text("ACTIVE: 数据流活跃,异常: ${snapshot.error}"));
              } else {
                return Center(
                    child: Text("ACTIVE: 数据流活跃,数据: ${snapshot.data}"));
              }
            case ConnectionState.done:
              return const Center(child: Text("DONE: 数据流关闭"));
            default:
              throw "ConnectionState没有别的状态";
          }
        },
      ),
    );
  }

StreamController
一般情况我们都是监听别人给我们的数据流,比如 File("").openRead() 读取文件, 刚才给大家讲了
Stream.periodic 可以创建数据流,如果我们想创建更精确的数据流的话也可以使用
StreamController
注意: import 'dart:async'; // 需要导入异步包

final StreamController streamController = StreamController.broadcast();
  @override
  void initState() {
    super.initState();
    streamController.stream.listen((event) {
      print(event);
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("异步"),
      ),
      body: Center(
        child: Column(children: [
          ElevatedButton(
// 按钮点击后Stream会释放出数字1
            child: const Text("Emit 1"),
            onPressed: () => streamController.add(1),
          ),
          ElevatedButton(
            child: const Text("Emit 2"),
            onPressed: () => streamController.add(2),
          ),
          ElevatedButton(
            child: const Text("Emit 3"),
            onPressed: () => streamController.add(3),
          ),
          ElevatedButton(
            child: const Text("Emit 4"),
            onPressed: () => streamController.add(4),
          ),
          ElevatedButton(
            child: const Text("Emit 5"),
            onPressed: () => streamController.add(5),
          ),
          ElevatedButton(
            child: const Text("Emit 6"),
            onPressed: () => streamController.add(6),
          ),
          ElevatedButton(
            child: const Text("Emit 6"),
            onPressed: () => streamController.add(6),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出一个错误
            child: const Text("Emit Error"),
            onPressed: () => streamController.addError("oops"),
          ),
          ElevatedButton(
            // 按钮点击后Stream会关闭
            child: const Text("Close"),
            onPressed: () => streamController.close(),
          ),
          StreamBuilder(
            stream: streamController.stream
                .where((event) => event > 3) //筛选大于3的
                .map((event) => event * 2) //第一步筛选大于3的,第二步得到的值再*2
                .distinct(), //去重
            builder: (context, snapshot) {
              print("正在重新绘制StreamBuilder组件…");
              if (snapshot.connectionState == ConnectionState.done) {
                return const Text("数据流已关闭");
              }
              if (snapshot.hasError) return Text("${snapshot.error}");
              if (snapshot.hasData) return Text("${snapshot.data}");
              return const Center(
                child: CircularProgressIndicator(),
              );
            },
          )
        ]),
      ),
    );
  }

8、Flutter StreamBuilder AnimatedBuilder 实现一个打字小游戏

class GamePager extends StatefulWidget {
  const GamePager({super.key});

  @override
  State<GamePager> createState() => _GamePagerState();
}

class _GamePagerState extends State<GamePager> {
  final StreamController<int> inputController = StreamController.broadcast();
  final StreamController<int> scoreController = StreamController.broadcast();
  int score = 0;
  @override
  void dispose() {
    super.dispose();
    inputController.close();
    scoreController.close();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: StreamBuilder(
            stream: scoreController.stream,
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                return Text("Error:${snapshot.error}");
              }
              if (snapshot.hasData) {
                score = score + (snapshot.data as int);
                return Text("得分:$score");
              }
              return const Text("等待输入");
            }),
      ),
      body: Stack(
        children: [
          ...List.generate(3, (index) {
            return Game(
                inputController: inputController,
                scoreController: scoreController);
          }),
          Align(
            alignment: Alignment.bottomCenter,
            child: KeyPad(inputController: inputController),
          )
        ],
      ),
    );
  }
}

//算数  游戏 子组件
class Game extends StatefulWidget {
  final StreamController<int> inputController;
  final StreamController<int> scoreController;

  const Game(
      {super.key,
      required this.inputController,
      required this.scoreController});

  @override
  State<Game> createState() => _GameState();
}

class _GameState extends State<Game> with SingleTickerProviderStateMixin {
  late int a, b;
  late double x;
  late AnimationController _animationController;
  late Color color;
  @override
  void reset() {
    a = Random().nextInt(5) + 1;
    b = Random().nextInt(5);
    x = Random().nextDouble() * 320;
    color = Colors.primaries[Random().nextInt(Colors.primaries.length)];
  }

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

    reset();
    _animationController = AnimationController(
        vsync: this,
        duration: Duration(milliseconds: Random().nextInt(5000) + 5000));

    _animationController.forward(); //执行一次动画

    _animationController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        //监听动画执行完成
        //生成随机数
        reset();
        widget.scoreController.add(-1); //最底部减去1分
        _animationController.forward(from: 0.0); //重新执行一次动画
      }
    });

    //监听键盘按键
    widget.inputController.stream.listen((event) {
      print(event);
      if (a + b == event) {
        reset();
        widget.scoreController.add(3); //打中加3分
        _animationController.forward(from: 0.0);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: _animationController,
        builder: (context, child) {
          return Positioned(
            top: Tween(begin: -50.0, end: 560.0)
                .animate(_animationController)
                .value,
            left: x,
            child: Container(
              padding: const EdgeInsets.fromLTRB(8, 5, 8, 5),
              decoration: BoxDecoration(
                  color: color, borderRadius: BorderRadius.circular(18)),
              child: Text("$a+$b=?", style: TextStyle(fontSize: 24)),
            ),
          );
        });
  }
}

//键盘 子组件
class KeyPad extends StatelessWidget {
  final StreamController<int> inputController;
  const KeyPad({super.key, required this.inputController});

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.bottomCenter,
      child: Container(
        color: Colors.red,
        child: GridView.count(
          shrinkWrap: true, //收缩
          crossAxisCount: 3,
          childAspectRatio: 5 / 2,
          children: List.generate(9, (index) {
            return TextButton(
                style: ButtonStyle(
                    shape: MaterialStateProperty.all(
                        const RoundedRectangleBorder()),
                    backgroundColor:
                        MaterialStateProperty.all(Colors.primaries[index][300]),
                    foregroundColor: MaterialStateProperty.all(Colors.black)),
                onPressed: () {
                  inputController.add(index + 1);
                },
                child: Text("${index + 1}",
                    style: Theme.of(context).textTheme.headline4));
          }),
        ),
      ),
    );
  }
}

相关文章

  • Flutter Form、TextFormField及表单验证、

    Flutter Form、TextFormField及表单验证、表单输入框聚焦http://www.ptbird....

  • Flutter 学习之路 - 异步任务

    实验 Flutter 的异步任务 --- 代码Github地址 Fultter 异步任务试验 Flutter 在很...

  • 401--Flutter for iOS 9--表单输入

    [TOC] 表单输入 1. Flutter 中表单怎么工作?我怎么拿到用户的输入? 我们已经提到 Flutter ...

  • 上传文件 upload file

    使用jQuery.form插件,实现完美的表单异步提交 表单的异步提交,现在不需要 jQuery插件之ajaxFi...

  • Flutter输入框及表单

    Material组件库中提供了输入框组件TextField和表单组件Form。下面我们分别介绍一下。 组件 - T...

  • XMLHttpRequest —— 文件上传

    包容万象,异步转运 前序: XMLHttpRequest 异步 form表单解析 multipart/form-d...

  • Flutter - Dart中的异步编程及多线程

    Flutter - Dart中的异步编程及多线程 前言 生命在于不断学习,探索未知的世界!!! 今天我们将从Fut...

  • flutter表单

    textField输入框 在textField中可以使用onChanged方法监听输入框文本的变化,也可以用Tex...

  • Flutter表单

    一、Form表单是一个包含表单元素的区域 。表单元素允许用户输入内容, 比如 : 文本域 、 下拉 列表、单选框、...

  • 表单异步提交

    好久没有写过前端页面了,以前都是前后端分离写后台接口,现在写页面,记录单纯的使用jquery异步提交表单 立即提交...

网友评论

      本文标题:Flutter表单及异步

      本文链接:https://www.haomeiwen.com/subject/ibhrmdtx.html