Flutter学习四:Flutter开发基础(一)Widget

这篇具有很好参考价值的文章主要介绍了Flutter学习四:Flutter开发基础(一)Widget。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

0 引言

1 Widget 简介

1.1 Widget 概念

1.2 Widget 接口

1.3 Flutter中的四棵树

1.4 StatelessWidget

1.4.1 简介

1.4.2 Context上下文

1.5 StatefulWidget

1.6  State

1.6.1 简介

1.6.2 State生命周期

1.7  在 widget 树中获取State对象

1.7.1 通过Context获取

1.7.2 通过GlobalKey获取

1.8 通过 RenderObject 自定义 Widget

1.9 Flutter SDK内置组件库介绍

1.9.1 基础组件

1.9.2 Material组件

1.9.3  Cupertino组件

1.10 总结


0 引言

本文是对第二版序 | 《Flutter实战·第二版》 (flutterchina.club)的学习和总结。

1 Widget 简介

1.1 Widget 概念

  • Widget 字面意思:控件、组件、部件、微件、插件、小工具
  • widget 的功能是“描述一个UI元素的配置信息”,所谓的配置信息就是 Widget 接收的参数
  • Widget 只是描述一个UI元素的配置信息,并不是表示最终绘制在设备屏幕上的显示元素

1.2 Widget 接口

  • @immutable 代表 Widget 是不可变的,即Widget 中定义的属性必须是 final。
  • widget类继承自DiagnosticableTree,即“诊断树”,主要作用是提供调试信息。
  • Key属性类似于 React/Vue 中的key,主要的作用是决定是否在下一次build时复用旧的 widget ,决定的条件在canUpdate()方法中。
  • createElement():一个 widget 可以对应多个Element,Flutter 框架在构建UI树时,会先调用此方法生成对应节点的Element对象。此方法是 Flutter 框架隐式调用的,在开发过程中基本不会调用到。
  • debugFillProperties(...) 复写父类的方法,主要是设置诊断树的一些特性。
  • canUpdate(...)是一个静态方法,只要newWidgetoldWidgetruntimeTypekey同时相等,就会用new widget去更新旧UI树上所对应的Element对象的配置,否则会创建新的Element对象
  • 在 Flutter 开发中,一般不用直接继承Widget类来实现一个新组件。通常会通过继承StatelessWidgetStatefulWidget来间接继承widget类来实现。
/*
Widget 类的声明:
*/
@immutable // 不可变的
abstract class Widget extends DiagnosticableTree {
  const Widget({ this.key });

  final Key? key;

  @protected
  @factory
  Element createElement();

  @override
  String toStringShort() {
    final String type = objectRuntimeType(this, 'Widget');
    return key == null ? type : '$type-$key';
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
  }

  @override
  @nonVirtual
  bool operator ==(Object other) => super == other;

  @override
  @nonVirtual
  int get hashCode => super.hashCode;

  static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
  }
  ...
}

1.3 Flutter中的四棵树

Flutter 框架的处理流程:(真正的布局、绘制是由谁来完成的)

  1. 根据 Widget 树生成一个 Element 树,Element 树中的节点都继承自 Element 类。
  2. 根据 Element 树生成 Render 树(渲染树),渲染树中的节点都继承自RenderObject 类。
  3. 根据渲染树生成 Layer 树,然后上屏显示,Layer 树中的节点都继承自 Layer 类。
  •  Flutter 真正的布局和渲染逻辑在 Render 树中
  • Element 是 Widget 和 RenderObject 的粘合剂,可以理解为一个中间代理。
/*假设有如下 Widget 树:
  Container 内部会创建一个新的 ColoredBox 来填充背景
  Image 内部会通过 RawImage 来渲染图片
  Text 内部会通过 RichText 来渲染文本
*/
Container( // 一个容器 widget
  color: Colors.blue, // 设置容器背景色
  child: Row( // 可以将子widget沿水平方向排列
    children: [
      Image.network('https://www.example.com/1.png'), // 显示图片的 widget
      const Text('A'),
    ],
  ),
);

 Widget树、Element 树、渲染树结构:

Flutter学习四:Flutter开发基础(一)Widget,Flutter,flutter,学习

1.4 StatelessWidget

1.4.1 简介

  • 无状态的组件,用于不需要维护状态的场景
  • 继承自widget类,重写了createElement()方法
  • 通常在build方法中通过嵌套其他 widget 来构建UI,在构建过程中会递归的构建其嵌套的 widget
//main 函数为应用程序的入口
void main() {
  //runApp(Widget参数),它的功能是启动Flutter应用
  runApp(const MyApp()); 
}

//MyApp对象 
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // 应用的根组件
  @override
  Widget build(BuildContext context) {
      // 调用自定义的 widget 
      return Echo(text: "hello world");
  }
}

// 自定义 widget 
class Echo extends StatelessWidget  {
  //使用命名参数,定义 widget 的构造函数
  const Echo({
    Key? key, //在继承 widget 时,第一个参数通常应该是Key
    required this.text, //必需要传的参数要添加required关键字
    this.backgroundColor = Colors.grey, //默认为灰色
  }):super(key:key);
  
  // widget 的属性应尽可能的被声明为final,防止被意外改变
  final String text;
  final Color backgroundColor;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: backgroundColor,
        child: Text(text),  //child或children参数通常应被放在参数列表的最后
      ),
    );
  }

1.4.2 Context上下文

  •  build方法有一个context参数
  • 它是BuildContext类的一个实例,表示当前 widget 在 widget 树中的上下文
  • 每一个 widget 都会对应一个 context 对象
  • 它提供了从当前 widget 开始向上遍历 widget 树的方法
  • 它提供了按照 widget 类型查找父级 widget 的方法
class ContextRoute extends StatelessWidget  {
  @override
  Widget build(BuildContext context) {
    /*
      Scaffold 是 Material 库中提供的页面脚手架
      它提供了默认的导航栏、标题和包含主屏幕 widget 树的body属性
    */
    return Scaffold(
      appBar: AppBar(
        title: Text("Context测试"),
      ),
      body: Container( // 一个容器 widget
        child: Builder(builder: (context) {
          // 在 widget 树中向上查找最近的父级`Scaffold`  widget 
          Scaffold scaffold = context.findAncestorWidgetOfExactType<Scaffold>();
          // 直接返回 AppBar的title, 此处实际上是Text("Context测试")
          return (scaffold.appBar as AppBar).title;
        }),
      ),
    );
  }
}

1.5 StatefulWidget

  • 有状态的组件,用于需要维护状态的场景
  • 继承自widget类,重写了createElement()方法
  • 添加了一个新的接口createState()
  • State 对象和StatefulElement具有一一对应的关系
/*
StatefulWidget的类定义:
*/
abstract class StatefulWidget extends Widget {
  const StatefulWidget({ Key key }) : super(key: key);
    
  @override
  StatefulElement createElement() => StatefulElement(this); 

  /*
     用于创建和 StatefulWidget 相关的状态,
     在StatefulWidget 的生命周期中可能会被多次调用,
     一个StatefulElement对应一个State实例
  */
  @protected
  State createState(); 
}

1.6  State

1.6.1 简介

一个 StatefulWidget 类会对应一个 State 类,State表示与其对应的 StatefulWidget 要维护的状态,State 中保存的状态信息可以:

  1. 在 widget 构建时可以被同步读取。
  2. 在 widget 生命周期中可以被改变,当State被改变时,可以手动调用其setState()方法通知Flutter 框架状态发生改变,Flutter 框架在收到消息后,会重新调用其build方法重新构建 widget 树,从而达到更新UI的目的。

 State 中有两个常用属性:

  1. widget,它表示与该 State 实例关联的 widget 实例,由Flutter 框架动态设置。注意,这种关联并非永久的,因为在应用生命周期中,UI树上的某一个节点的 widget 实例在重新构建时可能会变化,但State实例只会在第一次插入到树中时被创建,当在重新构建时,如果 widget 被修改了,Flutter 框架会动态设置State. widget 为新的 widget 实例。
  2. context。StatefulWidget对应的 BuildContext,作用同StatelessWidget 的BuildContext。

1.6.2 State生命周期

  • initState当 widget 第一次插入到 widget 树时会被调用,对于每一个State对象,Flutter 框架只会调用一次该回调。所以,通常在该回调中做一些一次性的操作,如状态初始化、订阅子树的事件通知等。
  • didChangeDependencies()当State对象的依赖发生变化时会被调用。组件第一次被创建后挂载的时候(包括重创建)对应的didChangeDependencies也会被调用。
  • build()用于构建 widget 子树的,会在如下场景被调用:

    1. 在调用initState()之后。
    2. 在调用didUpdateWidget()之后。
    3. 在调用setState()之后。
    4. 在调用didChangeDependencies()之后。
    5. 在State对象从树中一个位置移除后(会调用deactivate)又重新插入到树的其他位置之后。
  • reassemble()专门为了开发调试而提供的,在热重载(hot reload)时会被调用,在Release模式下永远不会被调用。

  • didUpdateWidget()在 widget 重新构建时,Flutter 框架会调用widget.canUpdate来检测 widget 树中同一位置的新旧节点,然后决定是否需要更新,如果widget.canUpdate返回true则会调用此回调。widget.canUpdate会在新旧 widget 的 key 和 runtimeType 同时相等时会返回true。

  • deactivate()当 State 对象从树中被移除时,会调用此回调。在一些场景下,Flutter 框架会将 State 对象重新插到树中,如包含此 State 对象的子树在树的一个位置移动到另一个位置时。如果移除后没有重新插入到树中则紧接着会调用dispose()方法。

  • dispose()当 State 对象从树中被永久移除时调用;通常在此回调中释放资源。

  • 注意:在继承StatefulWidget重写其方法时,对于包含@mustCallSuper标注的父类方法,都要在子类方法中调用父类方法。

/*
  实现一个计数器 CounterWidget 组件 ,点击它可以使计数器加1,
  由于要保存计数器的数值状态,所以应继承StatefulWidget
*/
class CounterWidget extends StatefulWidget {
  //构造函数
  const CounterWidget({Key? key, this.initValue = 0});

  //组件的参数
  final int initValue;

  //重写createState方法
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

/*
  createState方法
*/
class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  @override
  void initState() {
    super.initState();
    //初始化状态
    _counter = widget.initValue;
    print("initState");
  }

  @override
  Widget build(BuildContext context) {
    print("build");
    return Scaffold(
      body: Center(
        child: TextButton(
          child: Text('$_counter'),
          //点击后计数器自增
          onPressed: () => setState(
            () => ++_counter,
          ),
        ),
      ),
    );
  }

  @override
  void didUpdateWidget(CounterWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget ");
  }

  @override
  void deactivate() {
    super.deactivate();
    print("deactivate");
  }

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

  @override
  void reassemble() {
    super.reassemble();
    print("reassemble");
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("didChangeDependencies");
  }
}

/*
  调用自定义的CounterWidget
*/
class StateLifecycleTest extends StatelessWidget {
  const StateLifecycleTest({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CounterWidget();
  }
}

/*
 1.运行应用,屏幕中央就会出现一个数字0,然后控制台日志输出:
    I/flutter ( 5436): initState
    I/flutter ( 5436): didChangeDependencies
    I/flutter ( 5436): build
 2.热重载,控制台输出日志如下:
    I/flutter ( 5436): reassemble
    I/flutter ( 5436): didUpdateWidget 
    I/flutter ( 5436): build
 3.将return CounterWidget();改为 return Text("xxx");然后热重载,日志如下:
    I/flutter ( 5436): reassemble
    I/flutter ( 5436): deactive
    I/flutter ( 5436): dispose   
*/

 StatefulWidget 生命周期如下图所示:

Flutter学习四:Flutter开发基础(一)Widget,Flutter,flutter,学习

1.7  在 widget 树中获取State对象

在子 widget 树中获取父级 StatefulWidget 的State 对象的两种方法:

  1. 通过Context获取:context对象有一个findAncestorStateOfType()方法,该方法可以从当前节点沿着 widget 树向上查找指定类型的 StatefulWidget 对应的 State 对象。
  2. 通过GlobalKey获取:GlobalKey 是 Flutter 提供的一种在整个 App 中引用 element 的机制。如果一个 widget 设置了GlobalKey,则可以通过globalKey.currentState来获得该 widget 对应的state对象。(开销大,不推荐这种方法)

1.7.1 通过Context获取

通过Context获取State 对象的两种方法:

  1. 通过 context.findAncestorStateOfType 获取 StatefulWidget 的状态的方法是通用的。
  2. 但如果 StatefulWidget 的状态是公共的(希望暴露出的),Flutter SDK默认在 StatefulWidget 中提供一个of 静态方法来供开发者获取其 State 对象。开发者在自定义StatefulWidget 时也应遵守这一规则。
//  Scaffold组件对应的状态类ScaffoldState中定义了打开 SnackBar(路由页底部提示条)的方法
//  下面是实现打开 SnackBar 的示例:

/*
   1.通过context.findAncestorStateOfType获取ScaffoldState
*/
class GetStateObjectRoute extends StatefulWidget {
  const GetStateObjectRoute({Key? key}) : super(key: key);

  @override
  State<GetStateObjectRoute> createState() => _GetStateObjectRouteState();
}

class _GetStateObjectRouteState extends State<GetStateObjectRoute> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("子树中获取State对象"),
      ),
      body: Center(
        child: Column(
          children: [
            Builder(builder: (context) {
              return ElevatedButton(
                onPressed: () {
                  // 查找父级最近的Scaffold对应的ScaffoldState对象
                  ScaffoldState _state = context.findAncestorStateOfType<ScaffoldState>()!;
                  // 打开抽屉菜单
                  _state.openDrawer();
                },
                child: Text('打开抽屉菜单1'),
              );
            }),
          ],
        ),
      ),
      drawer: Drawer(),
    );
  }
}


/*
  2.通过of静态方法来获取ScaffoldState
*/

Builder(builder: (context) {
  return ElevatedButton(
    onPressed: () {
      // 直接通过of静态方法来获取ScaffoldState
      ScaffoldState _state=Scaffold.of(context);
      // 打开抽屉菜单
      _state.openDrawer();
    },
    child: Text('打开抽屉菜单2'),
  );
}),


/*
  显示 snack bar 的代码
*/
Builder(builder: (context) {
  return ElevatedButton(
    onPressed: () {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("我是SnackBar")),
      );
    },
    child: Text('显示SnackBar'),
  );
}),

1.7.2 通过GlobalKey获取

如果一个 widget 设置了GlobalKey,则:

  • 可以通过globalKey.currentWidget获得该 widget 对象
  • 可以通过globalKey.currentElement来获得 widget 对应的element对象
  • 可以通过globalKey.currentState来获得该 widget 对应的state对象

注意事项:

  1. 使用 GlobalKey 开销较大,如果有其他可选方案,应尽量避免使用它。
  2. 同一个 GlobalKey 在整个 widget 树中必须是唯一的,不能重复。 
/*
  Flutter还有一种通用的获取State对象的方法——通过GlobalKey来获取! 步骤分两步:
*/

/*
  1.给目标StatefulWidget添加GlobalKey。
*/
//定义一个globalKey, 由于GlobalKey要保持全局唯一性,我们使用静态变量存储
static GlobalKey<ScaffoldState> _globalKey= GlobalKey();
...
Scaffold(
    key: _globalKey , //设置key
    ...  
)

/*
  2.通过GlobalKey来获取State对象
*/
_globalKey.currentState.openDrawer()

1.8 通过 RenderObject 自定义 Widget

  • Flutter 最原始的定义组件的方式是通过定义RenderObject 来实现的。
  • StatelessWidget 和 StatefulWidget 本身没有对应的 RenderObject,它们是用于组合其他组件的,Flutter 组件库中的很多基础组件都不是通过它们来实现的。
  • 就好比搭积木,StatelessWidget 和 StatefulWidget 可以将积木搭成不同的样子,但前提是得有积木,而这些积木都是通过自定义 RenderObject 来实现的,比如 Text 、Column、Align等。

通过RenderObject定义组件的方式:

  • 如果自定义的 widget 不会包含子组件,可以直接继承LeafRenderObjectWidget
  • 如果自定义的 widget 可以包含子组件,则可以根据子组件的数量来选择继承SingleChildRenderObjectWidget 或 MultiChildRenderObjectWidget
  • 它们都继承自RenderObjectWidget
  • 它们都实现了createElement() 方法,返回不同类型的 Element 对象
  • createRenderObject 方法被组件对应的 Element 调用(构建渲染树时)用于生成渲染对象。
  • updateRenderObject 方法是用于在组件树状态发生变化但不需要重新创建 RenderObject 时用于更新组件渲染对象的回调。
/*
    自定义Widget 继承 叶渲染器Widget
*/
class CustomWidget extends LeafRenderObjectWidget{
  @override
  RenderObject createRenderObject(BuildContext context) {
    // 创建 RenderObject
    return RenderCustomObject();
  }
  @override
  void updateRenderObject(BuildContext context, RenderCustomObject  renderObject) {
    // 更新 RenderObject
    super.updateRenderObject(context, renderObject);
  }
}

/*
  自定义RenderObject,继承自 RenderBox,RenderBox 继承自 RenderObject,
  需要在 RenderCustomObject 中实现布局、绘制、事件响应等逻辑
*/
class RenderCustomObject extends RenderBox{

  @override
  void performLayout() {
    // 实现布局逻辑
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    // 实现绘制
  }
}

/*
  如果组件不会包含子组件,可以直接继承自 LeafRenderObjectWidget ,
  它是 RenderObjectWidget 的子类,而 RenderObjectWidget 继承自 Widget, 
  LeafRenderObjectWidget 的实现如下:
*/
abstract class LeafRenderObjectWidget extends RenderObjectWidget {
  const LeafRenderObjectWidget({ Key? key }) : super(key: key);

  @override
  LeafRenderObjectElement createElement() => LeafRenderObjectElement(this);
}

1.9 Flutter SDK内置组件库介绍

Flutter 提供了一套丰富、强大的基础组件库,在基础组件库之上 Flutter 又提供了:

  • 一套 Material 风格( Android 默认的视觉风格)的组件库
  • 一套 Cupertino 风格(iOS视觉风格)的组件库

1.9.1 基础组件

 要使用基础组件,需要先导入:

import 'package:flutter/widgets.dart';

常用的基础组件:

  • Text (opens new window):该组件可让您创建一个带格式的文本。
  • Row (opens new window)、 Column (opens new window): 这些具有弹性空间的布局类 widget 可让您在水平(Row)和垂直(Column)方向上创建灵活的布局。其设计是基于 Web 开发中的 Flexbox 布局模型。
  • Stack (opens new window): 取代线性布局 (和 Android 中的FrameLayout相似),[Stack](https://docs.flutter.dev/flutter/ widgets/Stack-class.html)允许子 widget 堆叠, 你可以使用 Positioned (opens new window)来定位他们相对于Stack的上下左右四条边的位置。Stacks是基于Web开发中的绝对定位(absolute positioning )布局模型设计的。
  • Container (opens new window): Container (opens new window)可让您创建矩形视觉元素。Container 可以装饰一个BoxDecoration (opens new window), 如 background、一个边框、或者一个阴影。 Container (opens new window)也可以具有边距(margins)、填充(padding)和应用于其大小的约束(constraints)。另外, Container (opens new window)可以使用矩阵在三维空间中对其进行变换。

1.9.2 Material组件

 要使用Material组件,需要先导入:

import 'package:flutter/material.dart';
  • Flutter 提供了一套丰富 的Material 组件,它可以帮助我们构建遵循 Material Design 设计规范的应用程序。
  • Material 应用程序以MaterialApp (opens new window) 组件开始, 该组件在应用程序的根部创建了一些必要的组件,比如Theme、ScaffoldAppBarTextButton等。
  • Material 组件库中有一些组件可以根据实际运行平台来切换表现风格,比如MaterialPageRoute,在路由切换时,如果是 Android 系统,它将会使用 Android 系统默认的页面切换动画(从底向上);如果是 iOS 系统,它会使用 iOS 系统默认的页面切换动画(从右向左)。

1.9.3  Cupertino组件

 要使用Cupertino组件,需要先导入:

import 'package:flutter/cupertino.dart';

Flutter 也提供了一套丰富的 Cupertino 风格的组件,尽管目前还没有 Material 组件那么丰富,但是它仍在不断的完善中。文章来源地址https://www.toymoban.com/news/detail-586928.html

/*
  一个简单的 Cupertino 组件风格的页面
*/

//导入cupertino  widget 库
import 'package:flutter/cupertino.dart';

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

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text("Cupertino Demo"),
      ),
      child: Center(
        child: CupertinoButton(
            color: CupertinoColors.activeBlue,
            child: const Text("Press"),
            onPressed: () {}
        ),
      ),
    );
  }
}

1.10 总结

  • Flutter 的 widget 类型分为StatefulWidget 和 StatelessWidget 两种,widget 是构建Flutter应用的基石。
  • Flutter 提供了丰富的组件,在实际的开发中可以根据需要随意使用它们,而不必担心引入过多组件库会让应用安装包变大,这不是 web 开发,dart 在编译时只会编译你使用了的代码。
  • 由于 Material 和 Cupertino 都是在基础组件库之上的,所以如果我们的应用中引入了这两者之一,则不需要再引入flutter/ widgets.dart了,因为它们内部已经引入过了。

到了这里,关于Flutter学习四:Flutter开发基础(一)Widget的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • flutter开发实战-自定义Switch开关控件Widget

    flutter开发实战-自定义Switch开关控件 在flutter中实现自定义Switch,主要实现类似IOS的UISwitch样式的开关控件 实现自定义Switch的Widget,主要实现交织动画。 交织动画 有些时候我们可能会需要一些复杂的动画,这些动画可能由一个动画序列或重叠的动画组成。一个动画组合在不同

    2024年02月13日
    浏览(50)
  • flutter开发实战-BackdropFilter高斯模糊子Widget控件

    flutter开发实战-BackdropFilter高斯模糊子Widget。 最近开发过程中遇到需要将控件进行模糊,比如iOS的effect的模糊效果。那在flutter中就需要用到了BackdropFilter BackdropFilter属性定义 其中ImageFilter的filter是必须传的,child为子控件。 ImageFilter一下两种两种构造方法 设置背景高斯模糊

    2024年02月14日
    浏览(34)
  • Flutter学习四:Flutter开发基础(六)调试Flutter应用

    目录 0 引言 1 调试Flutter应用 1.1 日志与断点 1.1.1 debugger() 声明 1.1.2 print和debugPrint 1.1.3 调试模式、中间模式、发布模式 1.1.4 断点 1.2 调试应用程序层 1.2.1 转储Widgets树 1.2.2  转储渲染树 1.2.3 转储Layer树 1.2.4 转储语义树 1.2.5 调度(打印帧的开始和结束) 1.2.6 可视化调试

    2024年02月12日
    浏览(56)
  • Flutter学习四:Flutter开发基础(四)包管理

    目录 0 引言 1 包管理 1.1 简介 1.2 Pub仓库 1.3 依赖Pub仓库 1.3.1 查找包  1.3.2 添加包 1.3.3 下载包 1.3.4 引入包  1.3.5 使用包 1.4 其他依赖方式 1.4.1 依赖本地包 1.4.2 依赖git仓库 1.4.3 不常用的依赖方式 本文是对第二版序 | 《Flutter实战·第二版》 (flutterchina.club)的学习和总结。 在

    2024年02月12日
    浏览(61)
  • Flutter学习四:Flutter开发基础(三)路由管理

    目录 0 引言 1 路由管理  1.1 MaterialPageRoute 1.2 Navigator  1.2.1 Future push(BuildContext context, Route route) 1.2.2  bool pop(BuildContext context, [ result ]) 1.2.3  Future pushNamed(BuildContext context, String routeName,{Object arguments}) 1.3 非命名路由传值 1.4 命名路由  1.4.1 路由表 1.4.2 注册路由表 1.4.3 通过

    2024年02月09日
    浏览(42)
  • Flutter学习四:Flutter开发基础(五)资源管理

    目录 0 引言 1 资源管理 1.1 指定 assets 1.2 Asset 变体(variant) 1.3 加载 assets 1.3.1  加载文本 1.3.2 加载图片 1.3.2.1 声明分辨率相关的图片 1.3.2.2 加载图片 1.3.3 依赖包中的资源图片  1.3.4 打包包中的 assets 1.3.5  特定平台 assets  1.3.5.1 设置APP图标  1.3.5.2 更新启动页 1.4 平台

    2024年02月11日
    浏览(42)
  • flutter笔记-万物皆是widget

    这篇文章后就不见写了,学flutter主要是为了更好的使用 flutter-webrtc,所以到这里基本就了解了大部分的知识,后续边用边查; 在flutter中所有的view都叫widget,类似文本组件Text也是集成自widget; 创建第一个项目如下: runApp传入的参数就是一个Widget;所以我们可以传入Text,示例

    2024年04月28日
    浏览(45)
  • Flutter Widget 生命周期 & key探究

    在Flutter中,一切皆是Widget(组件),Widget的功能是“描述一个UI元素的配置数据”,它就是说,Widget其实并不是表示最终绘制在设备屏幕上的显示元素,它只是描述显示元素的一个配置数据。 实际上,Flutter中真正代表屏幕上显示元素的类是 Element,也就是说Widget 只是描述

    2024年02月08日
    浏览(54)
  • Flutter通过flutter_unity_widget嵌入Unity3D

    实现方案:采用flutter开源组件flutter_unity_widget 1、创建flutter项目flutter_unity_demo 2、在pubspec.paml文件dependencies添加flutter_unity_widget: ^2022.2.0,执行Pub get导入组件 3、在工程目录下创建unity文件夹 4、在unity目录下创建unity_demo的3D工程 5、下载flutter_unity_widget提供的unity插件 在unity_d

    2024年02月11日
    浏览(41)
  • 【Flutter 工程】005-代码分离实践:flutter_hooks & functional_widget

    在Flutter开发中,“嵌套地狱”(Nesting Hell)是指在构建复杂的UI布局时,由于多层嵌套的组件结构,代码变得冗长、难以维护和理解的情况。 Flutter使用组件树的方式来构建用户界面,每个UI元素都是一个组件,可以包含其他组件。在某些情况下,特别是当需要实现复杂的布局

    2024年02月06日
    浏览(97)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包