边学边写搞flutter第二弹:基础结构与组件

这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战

我是谁?我在哪?我学会了什么?

跟着官网教程往下走,就莫名其妙的搞完了一个点击后自增的小demo,但是此刻不禁发出灵魂拷问。

image.png

那么今天它来了。

本文将带你重新理解flutter的基础结构,以及页面关系。

你是从Vue过来的?没关系,低门槛。

你是后端转行的?求你了,别卷前端了,后端安逸得很。(不是,欢迎.jpg)

文件与页面的关系

这里只是简单的,粗暴的是概括一下文件的关系,借此来表述是如何创建页面的。

ps: 这里说的不是路由,可以理解为用多个Widget拼成一个页面。

如果是已经入门了flutter开发,能用flutter独立布局页面的已经可以跳过这里了。

在使用Vue/React开发时,有一个词叫组件化,我是从Vue转过来的,所以借Vue的经验去理解flutter这一块的芝士点。

先简单看个代码

// home page
import 'package:flutter/material.dart';
import 'package:learn/widgets/demo.dart';

void main() => runApp(MyApp()); // 虽然这也是dart的语法, 但我就当JavaScript看了,减少接受成本。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(), // 这里相当于是确认主页的布局函数
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( // 创建一个AppBar, 即常见的顶部栏的部分
        title: Text('Flutter learn'),
        elevation: 10,
        centerTitle: true,
      ),
      body: ProcessDemo(), // ProcessDemo函数来自于顶部引入的demo.dart文件
      /*body: Column( // 引入多个Widget时的写法
        children: [
          ProcessDemo(),
          CheckDemo(),
        ],
      ),
      */
    );
  }
}

// demo.dart
import 'package:flutter/material.dart';
class ProcessDemo extends StatelessWidget {
  const ProcessDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(10),
      child: Column(
        children: [
          LinearProgressIndicator(
            value: .5,
            valueColor: AlwaysStoppedAnimation(Colors.red),
          ),
          SizedBox(height: 16),
          Container(
            width: 100,
            height: 100,
            child: CircularProgressIndicator(
              valueColor: AlwaysStoppedAnimation(Colors.red),
            ),
          ),
        ],
      ),
    );
  }
}
复制代码

ps: 因为组件都在官网教程里有,所以直接上链接。 >> 戳链接学习

开发与多选框组件

前面刚刚说完组件都在教程里,为什么作者又要开个段落呢? 作者是不是在水字数啊?

image.png

并不是,这里不确定是不是脸黑,碰上一个没见过的好问题。

先看代码

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

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

class _CheckDemoState extends State<CheckDemo> {
  bool _check = false;
  bool _switch = false;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Checkbox(
          value: _check,
          activeColor: Colors.red,
          onChanged: (v) {
            setState(() {
              _check = !_check;
            });
          },
        ),
        Switch(
          value: _switch,
          activeColor: Colors.red,
          onChanged: (v) {
            setState(() {
              _switch = v;
            });
          },
        ),
      ],
    );
  }
}
复制代码

请问,你看到了关于两个组件在修改状态的时候的不同了吗? 你肯定看到了对吧。

在我写多选框时,我乖巧的跟着教程写了_check = v;,于是我得到了一个报错。

image.png

翻译过来的白话就是:

image.png

image.png

搞咩啊,为什么bool无法赋值给bool啊。 来个大腿子解释下?

Checkbox(
  value: _check,
  activeColor: Colors.red,
  onChanged: (value) {
    setState(() {
      _check = value!;
    });
  },
)
复制代码

后面找到解决解决方法, 在布尔值后面加个!感叹号。

有一个可为空的值,所以在使用它时,必须执行value!

猜你喜欢

转载自juejin.im/post/7055073773656997918