flutter 英文官网学习笔记1

1.Flutter

1.Flutter是Google的UI工具包,用于从单个代码库构建漂亮的、本地编译的移动、web和桌面应用程序。

2.基本布局概念

欢迎来到Flutter布局代码实验室,在这里您可以学习如何在不下载和安装Flutter或Dart的情况下构建Flutter用户界面!

重要提示:这个代码实验室使用一个名为DartPad的实验性代码编辑器涵盖了基本的Fullter布局概念。DartPad还没有在所有浏览器上进行全面测试。如果在特定浏览器上使用DartPad时遇到任何困难,请创建一个DartPad问题,并在问题标题中指定要使用的浏览器。

Flutter不同于其他框架,因为它的UI是在代码中构建的,而不是(例如)在XML文件或类似文件中。Widget是Flutter用户界面的基本构建块。当你通过这个代码实验室,你会了解到几乎所有的Fullter都是一个Widget。Widget是一个不可变的对象,它描述了UI的特定部分。您还将了解Fullter Widget是可组合的,也就是说,可以组合现有的Widget来制作更复杂的Widget。在这个代码实验室的最后,您将能够将所学应用到构建一个显示名片的Flutter UI中。

估计完成此代码实验室的时间:45-60分钟。

Example: Creating a Column

test1.dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        BlueBox(),
        BlueBox(),
        BlueBox(),
      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

#########

Example: Modifying axis size

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.max,  //区别 增加了一个
      children: [
        BlueBox(),
        BlueBox(),
        BlueBox(),
      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

Example: Modifying main axis alignment

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.start, //区别 修改为
      children: [
        BlueBox(),
        BlueBox(),
        BlueBox(),
      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

Example: Modifying cross axis alignment

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      crossAxisAlignment: CrossAxisAlignment.center,

      children: [
        BlueBox(),
        BiggerBlueBox(),
        BlueBox(),
      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

class BiggerBlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 100,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

Example: Changing fit properties

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        BlueBox(),
        Flexible(
          fit: FlexFit.loose,
          flex: 1,
          child: BlueBox(),
        ),
        Flexible(
          fit: FlexFit.loose,
          flex: 1,
          child: BlueBox(),
        ),

      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

Example: Testing flex values

在下面的示例中,行包含一个BooBox Widget和两个灵活的Widget,它们封装两个Box Box控件。灵活的Widget包含Flex属性,Flex值设置为1(默认值)。

当Flex属性彼此比较时,它们的挠曲值之间的比率决定每个柔性 Widget接收的总剩余空间的分数。

内容复制

剩余空间*(flex/所有flexvalue的总和)

在这个示例中,Flex值的总和(2)确定两个灵活的Widget接收总剩余空间的一半。BlueBox Widget(或固定大小的Widget)保持相同的大小。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        BlueBox(),
        Flexible(
          fit: FlexFit.tight,
          flex: 1,
          child: BlueBox(),
        ),
        Flexible(
          fit: FlexFit.tight,
          flex: 1,
          child: BlueBox(),
        ),
      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

Example: Filling extra space

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        BlueBox(),
        BlueBox(),
        BlueBox(),

      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}
 

###2. Wrap the second BlueBox widget in an Expanded widget.

  Expanded(child: BlueBox(),),

Example: Resizing a widget

增加

Add a height property equal to 100 logical pixels inside the SizedBox widget, and run again.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.max,
      children: [
        BlueBox(),
        SizedBox(
          width: 100,
          child: BlueBox(),
        ),
        BlueBox(),

      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

Example: Creating space

Create more space by adding another SizedBox widget (25 logical pixels wide) between the second and third BlueBox widgets, and run again.

通过在第二个和第三个BlueBox Widget之间添加另一个SizedBox Widget(25个逻辑像素宽)来创建更多空间,然后再次运行。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        BlueBox(),
        SizedBox(width: 50),
        BlueBox(),
        BlueBox(),
      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

Example: Creating more space

Add another Spacer widget (also with a flex value of 1) between the second and third BlueBox widgets.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        BlueBox(),
        Spacer(flex: 1),
        BlueBox(),
        BlueBox(),
      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}

Example: Aligning text

Change CrossAxisAlignment.center to CrossAxisAlignment.baseline, and run again.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      textBaseline: TextBaseline.alphabetic,
      children: [
        Text(
          'Hey!',
          style: TextStyle(
            fontSize: 30,
            fontFamily: 'Futura',
            color: Colors.blue,
          ),
        ),
        Text(
          'Hey!',
          style: TextStyle(
            fontSize: 50,
            fontFamily: 'Futura',
            color: Colors.green,
          ),
        ),
        Text(
          'Hey!',
          style: TextStyle(
            fontSize: 40,
            fontFamily: 'Futura',
            color: Colors.red,
          ),
        ),
      ],
    );
  }
}

Example: Creating an Icon

Add another Icon from the Material Icon library with a size of 50.

Give the Icon a color of Colors.amber from the Material Color palette,

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      textBaseline: TextBaseline.alphabetic,
      children: [
        Icon(
          Icons.widgets,
          size: 50,
          color: Colors.blue,
        ),
        Icon(
          Icons.widgets,
          size: 50,
          color: Colors.red,
        ),

      ],
    );
  }
}

Example: Displaying an image

  • Change the short URL to the actual URL:
  • https://github.com/flutter/website/blob/master/examples/layout/sizing/images/pic3.jpg?raw=true
  • Then change pic3.jpg to pic1.jpg or pic2.jpg

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Image.network('https://urlzs.com/RsqCz'),
      ],
    );
  }
}

学习Widget

你将学到什么

如何回应轻拍。

如何创建自定义Widget。无状态和有状态Widget之间的区别。

如何修改应用程序使其对用户输入做出反应?在本教程中,您将向只包含非交互式Widget的应用程序添加交互性。具体地说,您将修改一个图标,通过创建一个自定义的有状态Widget来管理两个无状态Widget,使其可点击。

布局教程向您展示了如何为下面的屏幕快照创建布局。布局教程应用程序

布局教程应用程序

当这个应用程序第一次启动时,它的星星是红色的,这表明这个湖以前很受欢迎。星星旁边的数字表明有41个人喜欢这个湖。完成本教程后,轻敲星号将删除其收藏状态,用轮廓替换实心星号并减少计数。再次点击最喜欢的湖,画一个固体恒星和增加计数。

将创建的自定义Widget,为了实现这一点,您将创建一个单独的自定义Widget,其中包括star和count,它们本身就是Widget。点击两个Widget的星型改变状态,所以同一个Widget应该同时管理这两个。您可以在步骤2中直接接触代码:子类StatefulWidget。如果要尝试不同的状态管理方式,请跳到管理状态。

有状态和无状态Widget

Widget是有状态的或无状态的。如果Widget可以在用户与它交互时更改,例如它是有状态的。

无状态的Widget永远不会改变。

图标、图标按钮和文本是无状态Widget的示例。无状态Widget子类 无状态Widget。有状态的Widget是动态的:

例如,它可以根据用户交互触发的事件或在接收数据时更改其外观。Checkbox、Radio、Slider、InkWell、Form和TextField是有状态Widget的示例。StatefulWidget子类StatefulWidget。

Widget的状态存储在状态对象中,将Widget的状态与其外观分离。状态由可以更改的值组成,如滑块的当前值或是否选中复选框。当Widget的状态改变时,state对象调用setState(),告诉框架重新绘制Widget。

创建状态Widget,有什么意义?

有状态Widget由两个类实现:stateful widget的子类和State的子类。

state类包含Widget的可变状态和Widget的build()方法。当Widget的状态改变时,state对象调用setState(),告诉框架重新绘制Widget。

在本节中,您将创建一个自定义的有状态Widget。您将用一个单独的自定义有状态Widget来替换两个无状态Widget(实心红星和旁边的数字计数),该有状态Widget管理具有两个子部件(IconButton和Text)。

实现自定义状态Widget需要创建两个类:StatefulWidget的一个子类,用于定义Widget。State的一个子类,包含该Widget的状态并定义Widget的build()方法。本节向您展示如何为lakes应用程序构建一个名为FavoriteWidget的有状态Widget。设置之后,第一步是选择如何管理FavoriteWidget的状态。

第0步:准备

如果您已经在布局教程中构建了应用程序(步骤6),请跳到下一节。确保你已经设置好你的环境。

创建一个基本的“你好世界Fullter应用程序。

将lib/main.dart文件替换为main.dart。

将pubspec.yaml文件替换为pubspec.yaml。

在项目中创建一个images目录,并添加lake.jpg。

一旦你有了一个连接并启用的设备,或者你已经启动了iOS模拟器(Flutter安装的一部分),你就可以开始了!


步骤1:决定哪个对象管理Widget的状态

Widget的状态可以通过多种方式管理,但在我们的示例中,Widget本身FavoriteWidget将管理自己的状态。在本例中,切换star是一个独立的操作,不会影响父Widget或UI的其他部分,因此Widget可以在内部处理其状态。

在管理状态中,进一步了解Widget和状态的分离,以及如何管理状态。


第2步:StatefulWidget子类

FavoriteWidget类管理自己的状态,因此它重写createState()以创建状态对象。当框架想要构建Widget时,它会调用createState()。在本例中,createState()返回一个FavoriteWidgetState实例,您将在下一步中实现该实例。

lib/main.dart(FavoriteWidget)

内容复制

类FavoriteWidget扩展StatefulWidget{

@覆盖

_FavoriteWidgetState createState()=>FavoriteWidgetState();

}

注意:以下划线(\u)开头的成员或类是私有的。有关详细信息,请参见Dart语言教程中的库和可见性部分。


步骤3:子类状态

FavoriteWidgetState类存储可变数据

简单的应用程序状态管理

provider_shopper

为了说明这一点,请考虑以下简单的应用程序。

应用程序有两个独立的屏幕:目录和购物车(分别由MyCatalog和MyCart Widget表示)。它可能是一个购物应用程序,但你可以想象在一个简单的社交网络应用程序中有相同的结构(将catalog替换为wall,cart替换为favorites)。

目录屏幕包括一个自定义应用程序栏(MyAppBar)和许多列表项(MyListItems)的滚动视图。

这里的应用程序可视化为一个Widget树。

访问状态

一个简单的选项是提供一个回调,单击MyListItem时可以调用它。Dart的函数是一级对象,因此可以按任何方式传递它们。因此,在MyCatalog中可以有以下内容:

这可以正常工作,但是对于一个需要从许多不同地方修改的应用程序状态,您必须传递很多回调,这些回调很快就会变老。

幸运的是,Flutter有Widget向其后代提供数据和服务的机制(换句话说,不只是他们的孩子,而是他们下面的任何Widget)。正如您在Flutter中所期望的那样,在Flutter中,所有东西都是Widget™,这些机制只是特殊类型的widgets InheritedWidget、InheritedNotifier、InheritedModel等等。我们不会在这里报道这些,因为它们对于我们正在努力做的事情来说有点低级。

相反,我们将使用一个与低级Widget一起工作但简单易用的包。它被称为提供者。

使用provider,您不需要担心回调或继承的Widget。

但你需要明白3概念:

  • 变更通知程序
  • 更改通知提供程序
  • 消费者

ChangeNotifier

changennotifier是flutrsdk中包含的一个简单类,它向监听器提供更改通知。换言之,如果某物是变更通知程序,则可以订阅其变更。(对于熟悉这个术语的人来说,这是一种可观察的形式。)

在provider中,ChangeNotifier是封装应用程序状态的一种方法。对于非常简单的应用程序,您只需使用一个ChangeNotifier。在复杂的模型中,您将有几个模型,因此有几个变更通知程序。(您根本不需要将ChangeNotifier与provider一起使用,但它是一个易于使用的类。)

在我们的购物应用程序示例中,我们希望在ChangeNotifier中管理购物车的状态。我们创建了一个扩展类,如下所示:

ChangeNotifierProvider

ChangeNotifierProvider是向其后代提供ChangeNotifier实例的Widget。它来自提供者包。

我们已经知道将ChangeNotifierProvider:放在需要访问它的Widget上方的位置。在CartModel的例子中,这意味着在MyCart和MyCatalog之上。

您不想将ChangeNotifierProvider放置得高于需要的位置(因为您不想污染作用域)。但在我们的例子中,MyCart和MyCatalog上唯一的Widget是MyApp。

void main() {
  runApp(
    ChangeNotifierProvider(
      builder: (context) => CartModel(),
      child: MyApp(),
    ),
  );
}

Consumer

现在CartModel通过顶部的ChangeNotifierProvider声明提供给我们应用程序中的Widget,我们可以开始使用它了。

return Consumer<CartModel>(
  builder: (context, cart, child) {
    return Text("Total price: ${cart.totalPrice}");
  },
);

我们必须指定要访问的模型的类型。在这种情况下,我们需要CartModel,所以我们编写Consumer<CartModel>。如果不指定泛型(<CartModel>),提供程序包将无法帮助您。

Consumer Widget唯一需要的参数是builder。Builder是一个函数,每当change通知程序更改时都会调用它。(换句话说,在模型中调用notifyListeners()时,将调用所有相应使用者小部件的所有生成器方法。)

调用生成器时有三个参数。context, cart, child 。

builder函数的第二个参数是ChangeNotifier的实例。这是我们最初的要求。您可以使用模型中的数据来定义UI在任何给定点的外观。

第三个参数是child,用于优化。如果您的使用者下面有一个大的widget子树,当模型改变时它不会改变,那么您可以构造它一次并通过构建器获得它。

发布了134 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/keny88888/article/details/103898571