为前端工程师准备的Flutter入门指南

如果你恰好是一名前端工程师,且对 Flutter 抱有兴趣,那么真的是太好了,这篇文章完全就是为你准备的。写惯了 HTML、CSS 与 JavaScript,要不要来是试试 Dart?如果你不熟悉 Flutter 但仍对其感兴趣,可以先看看「让我们在2019年重新认识 Flutter」一文了解些 Flutter 基础。

创新互联公司专注于新抚企业网站建设,成都响应式网站建设,商城网站建设。新抚网站建设公司,为新抚等地区提供建站服务。全流程按需网站建设,专业设计,全程项目跟踪,创新互联公司专业和态度为您提供的服务

在接下来的章节中,我们仔细来对比下平时用 HTML/CSS 代码所实现的效果,如果替换为等价的 Flutter/Dart 代码,会是什么样子。

本文结构如下:

  1. 基础布局
  2. 位置与大小
  3. 图形/形状
  4. 文本

注:本文只摘录 Web 到 Flutter 中一些特性的转换介绍,详细及完整的使用方法与语法请查阅 Flutter/Dart 官网 https://flutter.io, https://flutter.cn 与 https://www.dartlang.org.

本文示例中默认已包含如下假设:

HTML 文件均会以 开头,且为了与 Flutter 模型保持一致,所有 HTML 元素的 CSS 盒模型被设置为 border-box。 

 
 
 
 
  1.   box-sizing: border-box; 

在 Flutter 中,为了保持语法简洁,示例中所用的 “Lorem ipsum” 文本的默认样式由如下 bold24Roboto 变量定义: 

 
 
 
 
  1. TextStyle bold24Roboto = TextStyle( 
  2.   color: Colors.white, 
  3.   fontSize: 24.0, 
  4.   fontWeight: FontWeight.w900, 
  5. ); 

Flutter UI 采用声明式编程,欲了解其与传统命令式风格的不同,请查阅声明式 UI 介绍。

一、基础布局

先来看看最常见的一些 UI 布局操作。

1.1 文本样式与对齐

我们在 CSS 中设置的字体样式、大小以及其他文本属性,都是 Flutter 中一个 Text widget 子元素 TextStyle 中单独的属性。

In both HTML and Flutter, child elements or widgets are anchored at the top left, by default.

不论是 HTML 还是 Flutter,子元素或者 widget 都默认锚定在左上方。

Web 

 
 
 
 
  1.  
  2.     Lorem ipsum 
 
  •  
  • .greybox { 
  •   background-color: #e0e0e0; /* grey 300 */ 
  •   width: 320px; 
  •   height: 240px; 
  •   font: 900 24px Georgia; 
  • Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Text( 
    3.     "Lorem ipsum", 
    4.     style: TextStyle( 
    5.       fontSize: 24.0, 
    6.       fontWeight: FontWeight.w900, 
    7.       fontFamily: "Georgia", 
    8.     ), 
    9.   ), 
    10.   width: 320.0, 
    11.   height: 240.0, 
    12.   color: Colors.grey[300], 
    13. ); 

    1.2 背景颜色

    在 Flutter 中,你可以通过 Container 的 decoration 属性来设置背景颜色。

    CSS 示例中我们使用等价的十六进制颜色表示。

    Web 

     
     
     
     
    1.  
    2.   Lorem ipsum 
     
  •  
  • .greybox { 
  •   background-color: #e0e0e0;  /* grey 300 */ 
  •   width: 320px; 
  •   height: 240px; 
  •   font: 900 24px Roboto; 
  • Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.     child: Text( 
    3.       "Lorem ipsum", 
    4.       style: bold24Roboto, 
    5.     ), 
    6.     width: 320.0, 
    7.     height: 240.0, 
    8.     color: Colors.grey[300], 
    9.   ); 

    1.3 居中元素

    在 Flutter 中,Center widget 可以将它的子元素水平和垂直居中。

    要用 CSS 实现相似的效果,其父元素则需要使用一个 flex 或者 table-cell 显示布局。本节示例使用的是 flex 布局。

    Web 

     
     
     
     
    1.  
    2.   Lorem ipsum 
     
  •  
  • .greybox { 
  •   background-color: #e0e0e0; /* grey 300 */ 
  •   width: 320px; 
  •   height: 240px; 
  •   font: 900 24px Roboto; 
  •   display: flex; 
  •   align-items: center; 
  •   justify-content: center;  
  • Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child:  Center( 
    3.     child:  Text( 
    4.       "Lorem ipsum", 
    5.       style: bold24Roboto, 
    6.     ), 
    7.   ), 
    8.   width: 320.0, 
    9.   height: 240.0, 
    10.   color: Colors.grey[300], 
    11. ); 

    1.4 设置容器宽度

    Container widget 的宽度可以用它的 width 属性指定,但需要注意的是,和 CSS 中的 max-width 属性用于指定容器可调整的***宽度值不同的是,这里指定的是一个固定宽度。要在 Flutter 中模拟 max-width 的效果,可以使用 Container 的 constraints 属性。新建一个带有 minWidth 和 maxWidth 属性的 BoxConstraints widget。 而对嵌套的 Container 来说,如果其父元素宽度小于子元素宽度,则子元素实际尺寸以父元素大小为准。

    Web 

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px;  
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.   width: 100%; 
    20.   max-width: 240px;  

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Center( 
    3.     child: Container( // red box 
    4.       child: Text( 
    5.         "Lorem ipsum", 
    6.         style: bold24Roboto, 
    7.       ), 
    8.       decoration: BoxDecoration( 
    9.         color: Colors.red[400], 
    10.       ), 
    11.       padding: EdgeInsets.all(16.0), 
    12.       width: 240.0, //max-width is 240.0 
    13.     ), 
    14.   ), 
    15.   width: 320.0,  
    16.   height: 240.0, 
    17.   color: Colors.grey[300], 
    18. ); 

    二、位置与大小

    以下示例将展示如何对 widget 的位置、大小以及背景进行更复杂的操作。

    2.1 绝对定位

    默认情况下, widget 是相对于其父元素定位的。要通过 x-y 坐标指定一个 widget 的绝对位置,请把它嵌套在一个 Positioned widget 中,而该 widget 则需被嵌套在一个 Stack widget 中。

    Web 

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   position: relative;  
    13. .redbox { 
    14.   background-color: #ef5350; /* red 400 */ 
    15.   padding: 16px; 
    16.   color: #ffffff; 
    17.   position: absolute; 
    18.   top: 24px; 
    19.   left: 24px;  

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Stack( 
    3.     children: [ 
    4.       Positioned( // red box 
    5.         child:  Container( 
    6.           child: Text( 
    7.             "Lorem ipsum", 
    8.             style: bold24Roboto, 
    9.           ), 
    10.           decoration: BoxDecoration( 
    11.             color: Colors.red[400], 
    12.           ), 
    13.           padding: EdgeInsets.all(16.0), 
    14.         ), 
    15.         left: 24.0, 
    16.         top: 24.0, 
    17.       ), 
    18.     ], 
    19.   ),  
    20.   width: 320.0, 
    21.   height: 240.0, 
    22.   color: Colors.grey[300], 
    23. ); 

    2.2 旋转

    要旋转一个 widget,请将它嵌套在 Transform widget 中。其中,使用 Transform widget 的 alignment 和 origin 属性分别来指定转换原点的具体位置信息。

    对于简单的 2D 旋转,widget 是依据弧度在 Z 轴上旋转的。(角度 × π / 180)

    Web  

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.   transform: rotate(15deg);  

    Dart 

     
     
     
     
    1. var container = Container( // gray box 
    2.   child: Center( 
    3.     child:  Transform( 
    4.       child:  Container( // red box 
    5.         child: Text( 
    6.           "Lorem ipsum", 
    7.           style: bold24Roboto, 
    8.           textAlign: TextAlign.center, 
    9.         ), 
    10.         decoration: BoxDecoration( 
    11.           color: Colors.red[400], 
    12.         ), 
    13.         padding: EdgeInsets.all(16.0), 
    14.       ), 
    15.       alignment: Alignment.center, 
    16.       transform: Matrix4.identity() 
    17.         ..rotateZ(15 * 3.1415927 / 180), 
    18.     ),  
    19.   ), 
    20.   width: 320.0, 
    21.   height: 240.0, 
    22.   color: Colors.grey[300], 
    23. ); 

    2.3 缩放元素

    将元素嵌套在一个 Transform widget 中,可以实现缩放。使用 Transform widget 的 alignment 和 origin 属性分别来指定缩放原点的具体位置信息。

    对于沿 x 轴的简单缩放操作,新建一个 Matrix4 标识对象并用它的 scale() 方法来指定缩放因系数。

    当你缩放一个父 widget 时,它的子 widget 也会相应被缩放。

    Web 

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.   transform: scale(1.5);  

    Dart 

     
     
     
     
    1. var container = Container( // gray box 
    2.   child: Center( 
    3.     child:  Transform( 
    4.       child:  Container( // red box 
    5.         child: Text( 
    6.           "Lorem ipsum", 
    7.           style: bold24Roboto, 
    8.           textAlign: TextAlign.center, 
    9.         ), 
    10.         decoration: BoxDecoration( 
    11.           color: Colors.red[400], 
    12.         ), 
    13.         padding: EdgeInsets.all(16.0), 
    14.       ), 
    15.       alignment: Alignment.center, 
    16.       transform: Matrix4.identity() 
    17.         ..scale(1.5), 
    18.      ),  
    19.   width: 320.0, 
    20.   height: 240.0, 
    21.   color: Colors.grey[300], 
    22. ); 

    2.4 线性变换

    将元素嵌套在一个 Container widget 中,可以将线性变换应用在 widget 的背景上。之后,再用 Container widget 的 decoration 属性生成一个 BoxDecoration 对象,然后使用 BoxDecoration 的 gradient 属性来变换背景填充内容。

    变换“角度”基于 Alignment (x, y) 取值来定:

    这里,只展示垂直变换的代码差异:

    Web  

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   padding: 16px; 
    17.   color: #ffffff; 
    18.   background: linear-gradient(180deg, #ef5350, rgba(0, 0, 0, 0) 80%);  

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Center( 
    3.     child: Container( // red box 
    4.       child: Text( 
    5.         "Lorem ipsum", 
    6.         style: bold24Roboto, 
    7.       ), 
    8.       decoration: BoxDecoration( 
    9.         gradient: LinearGradient( 
    10.           begin: const Alignment(0.0, -1.0), 
    11.           end: const Alignment(0.0, 0.6), 
    12.           colors: 
    13.             const Color(0xffef5350), 
    14.             const Color(0x00ef5350) 
    15.           ], 
    16.         ), 
    17.       ),  
    18.       padding: EdgeInsets.all(16.0), 
    19.     ), 
    20.   ), 
    21.   width: 320.0, 
    22.   height: 240.0, 
    23.   color: Colors.grey[300], 
    24. ); 

    三、图形/形状

    以下示例将展示如何新建和自定义图形。

    3.1 圆角

    在矩形上实现圆角,可以用 BoxDecoration 对象的 borderRadius 属性。新建一个 BorderRadius 对象来指定每个圆角的半径大小。

    Web 

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* gray 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.   border-radius: 8px;  

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Center( 
    3.     child: Container( // red circle 
    4.       child: Text( 
    5.         "Lorem ipsum", 
    6.         style: bold24Roboto, 
    7.       ), 
    8.       decoration: BoxDecoration( 
    9.         color: Colors.red[400], 
    10.         borderRadius: BorderRadius.all( 
    11.           const Radius.circular(8.0), 
    12.         ),  
    13.       ), 
    14.       padding: EdgeInsets.all(16.0), 
    15.     ), 
    16.   ), 
    17.   width: 320.0, 
    18.   height: 240.0, 
    19.   color: Colors.grey[300], 
    20. ); 

    3.2 阴影

    在 CSS 中你可以通过 box-shadow 属性快速指定阴影偏移与模糊范围。比如如下两个盒阴影的属性设置:

    在 Flutter 中,每个属性与其取值都是单独指定的。请使用 BoxDecoration 的 boxShadow 属性来生成一系列 BoxShadow widget。你可以定义一个或多个 BoxShadow widget,这些 widget 共同用于设置阴影深度、颜色等等。

    Web 

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.8), 
    20.               0 6px 20px rgba(0, 0, 0, 0.5); 

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Center( 
    3.     child: Container( // red box 
    4.       child: Text( 
    5.         "Lorem ipsum", 
    6.         style: bold24Roboto, 
    7.       ), 
    8.       decoration: BoxDecoration( 
    9.         color: Colors.red[400], 
    10.         boxShadow: 
    11.           BoxShadow ( 
    12.             color: const Color(0xcc000000), 
    13.             offset: Offset(0.0, 2.0), 
    14.             blurRadius: 4.0, 
    15.           ), 
    16.           BoxShadow ( 
    17.             color: const Color(0x80000000), 
    18.             offset: Offset(0.0, 6.0), 
    19.             blurRadius: 20.0, 
    20.           ), 
    21.         ],  
    22.       ), 
    23.       padding: EdgeInsets.all(16.0), 
    24.     ), 
    25.   ), 
    26.   width: 320.0, 
    27.   height: 240.0, 
    28.   decoration: BoxDecoration( 
    29.     color: Colors.grey[300], 
    30.   ), 
    31.   margin: EdgeInsets.only(bottom: 16.0), 
    32. ); 

    3.3 圆与椭圆

    尽管 CSS 中有基础图形,CSS 中一个生成圆的变通方案是:将矩形的四边 border-radius 均设成50%。

    虽然 BoxDecoration 的 borderRadius 属性支持这样设置,Flutter 为 BoxShape enum 提供一个 shape 属性也用于实现同样的目的。

    Web  

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* gray 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redcircle { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.   text-align: center; 
    20.   width: 160px; 
    21.   height: 160px; 
    22.   border-radius: 50%;  

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Center( 
    3.     child: Container( // red circle 
    4.       child: Text( 
    5.         "Lorem ipsum", 
    6.         style: bold24Roboto, 
    7.         textAlign: TextAlign.center,  
    8.       ), 
    9.       decoration: BoxDecoration( 
    10.         color: Colors.red[400], 
    11.         shape: BoxShape.circle,  
    12.       ), 
    13.       padding: EdgeInsets.all(16.0), 
    14.       width: 160.0, 
    15.       height: 160.0,  
    16.     ), 
    17.   ), 
    18.   width: 320.0, 
    19.   height: 240.0, 
    20.   color: Colors.grey[300], 
    21. ); 

    四、文本

    以下示例展示了如何设置字体和其他文本属性,除此外还包括一些特性比如如何变换文本字符、自定义间距以及生成摘录。

    4.1 文字间距

    在 CSS 中你可以通过分别给 letter-spacing 和 word-spacing 属性的长度赋值来指定每个字母以及每个单词间的空白距离。距离的单位可以是 px, pt, cm, em 等等。

    在 Flutter 中,你可以在 Text widget 子元素 TextStyle 的 letterSpacing 与 wordSpacing 属性中将间距设置为逻辑像素(允许负值)。

    Web  

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.   letter-spacing: 4px;  

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Center( 
    3.     child: Container( // red box 
    4.       child: Text( 
    5.         "Lorem ipsum", 
    6.         style: TextStyle( 
    7.           color: Colors.white, 
    8.           fontSize: 24.0, 
    9.           fontWeight: FontWeight.w900, 
    10.           letterSpacing: 4.0,  
    11.         ), 
    12.       ), 
    13.       decoration: BoxDecoration( 
    14.         color: Colors.red[400], 
    15.       ), 
    16.       padding: EdgeInsets.all(16.0), 
    17.     ), 
    18.   ), 
    19.   width: 320.0, 
    20.   height: 240.0, 
    21.   color: Colors.grey[300], 
    22. ); 

    4.2 内联样式

    一个 Text widget 可以展示同一类样式的文本。为了展现具有多种样式的文本,需要改用 RichText widget。它的 text 属性可以指定一个或多个可以单独设置样式的 TextSpan widget。

    在下例中,”Lorem” 位于 TextSpan widget 中,具有默认(继承自其父元素)文本样式,”ipsum” 位于具有自定义样式、单独的一个 TextSpan 中。

    Web  

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum  
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto;  
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.  .redbox em { 
    20.   font: 300 48px Roboto; 
    21.   font-style: italic; 
    22. }  

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Center( 
    3.     child: Container( // red box 
    4.       child:  RichText( 
    5.         text: TextSpan( 
    6.           style: bold24Roboto, 
    7.           children: 
    8.             TextSpan(text: "Lorem "), 
    9.             TextSpan( 
    10.               text: "ipsum", 
    11.               style: TextStyle( 
    12.                 fontWeight: FontWeight.w300, 
    13.                 fontStyle: FontStyle.italic, 
    14.                 fontSize: 48.0, 
    15.               ), 
    16.             ), 
    17.           ], 
    18.         ), 
    19.       ),  
    20.       decoration: BoxDecoration( 
    21.         backgroundColor: Colors.red[400], 
    22.       ), 
    23.       padding: EdgeInsets.all(16.0), 
    24.     ), 
    25.   ), 
    26.   width: 320.0, 
    27.   height: 240.0, 
    28.   color: Colors.grey[300], 
    29. ); 

    4.3 文本摘要

    在 Web 中,我们常用省略号处理溢出的文本内容,且在 HTML/CSS 中,摘要不能超过一行。 如果要在多行之后进行截断,那么就需要 JavaScript 的帮助了。

    在 Flutter 中,使用 Text widget 的 maxLines 属性来指定包含在摘要中的行数,以及 overflow 属性来处理溢出文本。

    Web  

     
     
     
     
    1.  
    2.    
    3.     Lorem ipsum dolor sit amet, consec etur 
    4.    
    5.  
    6.  
    7. .greybox { 
    8.   background-color: #e0e0e0; /* grey 300 */ 
    9.   width: 320px; 
    10.   height: 240px; 
    11.   font: 900 24px Roboto; 
    12.   display: flex; 
    13.   align-items: center; 
    14.   justify-content: center; 
    15. .redbox { 
    16.   background-color: #ef5350; /* red 400 */ 
    17.   padding: 16px; 
    18.   color: #ffffff; 
    19.   overflow: hidden; 
    20.   text-overflow: ellipsis; 
    21.   white-space: nowrap;  

    Dart 

     
     
     
     
    1. var container = Container( // grey box 
    2.   child: Center( 
    3.     child: Container( // red box 
    4.       child: Text( 
    5.         "Lorem ipsum dolor sit amet, consec etur", 
    6.         style: bold24Roboto, 
    7.         overflow: TextOverflow.ellipsis, 
    8.         maxLines: 1,  
    9.       ), 
    10.       decoration: BoxDecoration( 
    11.         backgroundColor: Colors.red[400], 
    12.       ), 
    13.       padding: EdgeInsets.all(16.0), 
    14.     ), 
    15.   ), 
    16.   width: 320.0, 
    17.   height: 240.0, 
    18.   color: Colors.grey[300], 
    19. ); 

    Teaser 截图自 flutter.io 官网。

    分享文章:为前端工程师准备的Flutter入门指南
    路径分享:http://www.gawzjz.com/qtweb/news17/183217.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

    猜你还喜欢下面的内容

    网站维护知识

    行业网站建设