内容简介:如果你恰好是一名前端工程师,且对 Flutter 抱有兴趣,那么真的是太好了,这篇文章完全就是为你准备的。写惯了 HTML、CSS 与 JavaScript,要不要来是试试 Dart?如果你不熟悉 Flutter 但仍对其感兴趣,可以先看看「在接下来的章节中,我们仔细来对比下平时用 HTML/CSS 代码所实现的效果,如果替换为等价的 Flutter/Dart 代码,会是什么样子。本文结构如下:
如果你恰好是一名前端工程师,且对 Flutter 抱有兴趣,那么真的是太好了,这篇文章完全就是为你准备的。写惯了 HTML、CSS 与 JavaScript,要不要来是试试 Dart?如果你不熟悉 Flutter 但仍对其感兴趣,可以先看看「 让我们在2019年重新认识 Flutter 」一文了解些 Flutter 基础。
在接下来的章节中,我们仔细来对比下平时用 HTML/CSS 代码所实现的效果,如果替换为等价的 Flutter/Dart 代码,会是什么样子。
本文结构如下:
- 基础布局
- 位置与大小
- 图形/形状
- 文本
注:本文只摘录 Web 到 Flutter 中一些特性的转换介绍,详细及完整的使用方法与语法请查阅 Flutter/Dart 官网 https://flutter.io , https://flutter.cn 与 https://www.dartlang.org .
本文示例中默认已包含如下假设:
-
HTML 文件均会以
<!DOCTYPE html>
开头,且为了与 Flutter 模型保持一致,所有 HTML 元素的 CSS 盒模型被设置为border-box
。{ box-sizing: border-box; }
-
在 Flutter 中,为了保持语法简洁,示例中所用的 “Lorem ipsum” 文本的默认样式由如下
bold24Roboto
变量定义:TextStyle bold24Roboto = TextStyle( color: Colors.white, fontSize: 24.0, fontWeight: FontWeight.w900, );
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
<div class="greybox"> Lorem ipsum </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Georgia; }
- Dart
var container = Container( // grey box child: Text( "Lorem ipsum", style: TextStyle( fontSize: 24.0, fontWeight: FontWeight.w900, fontFamily: "Georgia", ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
1.2 背景颜色
在 Flutter 中,你可以通过 Container
的 decoration
属性来设置背景颜色。
CSS 示例中我们使用等价的十六进制颜色表示。
- Web
<div class="greybox"> Lorem ipsum </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; }
- Dart
var container = Container( // grey box child: Text( "Lorem ipsum", style: bold24Roboto, ), width: 320.0, height: 240.0, color: Colors.grey[300], );
1.3 居中元素
在 Flutter 中, Center widget 可以将它的子元素水平和垂直居中。
要用 CSS 实现相似的效果,其父元素则需要使用一个 flex 或者 table-cell 显示布局。本节示例使用的是 flex 布局。
- Web
<div class="greybox"> Lorem ipsum </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; }
- Dart
var container = Container( // grey box child: Center( child: Text( "Lorem ipsum", style: bold24Roboto, ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
1.4 设置容器宽度
Container
widget 的宽度可以用它的 width
属性指定,但需要注意的是,和 CSS 中的 max-width 属性用于指定容器可调整的最大宽度值不同的是,这里指定的是一个固定宽度。要在 Flutter 中模拟 max-width 的效果,可以使用 Container 的 constraints
属性。新建一个带有 minWidth
和 maxWidth
属性的 BoxConstraints
widget。
而对嵌套的 Container 来说,如果其父元素宽度小于子元素宽度,则子元素实际尺寸以父元素大小为准。
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; width: 100%; max-width: 240px; }
- Dart
var container = Container( // grey box child: Center( child: Container( // red box child: Text( "Lorem ipsum", style: bold24Roboto, ), decoration: BoxDecoration( color: Colors.red[400], ), padding: EdgeInsets.all(16.0), width: 240.0, //max-width is 240.0 ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
二、位置与大小
以下示例将展示如何对 widget 的位置、大小以及背景进行更复杂的操作。
2.1 绝对定位
默认情况下, widget 是相对于其父元素定位的。要通过 x-y 坐标指定一个 widget 的绝对位置,请把它嵌套在一个 Positioned widget 中,而该 widget 则需被嵌套在一个 Stack widget 中。
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; position: relative; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; position: absolute; top: 24px; left: 24px; }
- Dart
var container = Container( // grey box child: Stack( children: [ Positioned( // red box child: Container( child: Text( "Lorem ipsum", style: bold24Roboto, ), decoration: BoxDecoration( color: Colors.red[400], ), padding: EdgeInsets.all(16.0), ), left: 24.0, top: 24.0, ), ], ), width: 320.0, height: 240.0, color: Colors.grey[300], );
2.2 旋转
要旋转一个 widget,请将它嵌套在 Transform
widget 中。其中,使用 Transform widget 的 alignment
和 origin
属性分别来指定转换原点的具体位置信息。
对于简单的 2D 旋转,widget 是依据弧度在 Z 轴上旋转的。(角度 × π / 180)
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; transform: rotate(15deg); }
- Dart
var container = Container( // gray box child: Center( child: Transform( child: Container( // red box child: Text( "Lorem ipsum", style: bold24Roboto, textAlign: TextAlign.center, ), decoration: BoxDecoration( color: Colors.red[400], ), padding: EdgeInsets.all(16.0), ), alignment: Alignment.center, transform: Matrix4.identity() ..rotateZ(15 * 3.1415927 / 180), ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
2.3 缩放元素
将元素嵌套在一个 Transform
widget 中,可以实现缩放。使用 Transform widget 的 alignment
和 origin
属性分别来指定缩放原点的具体位置信息。
对于沿 x 轴的简单缩放操作,新建一个 Matrix4 标识对象并用它的 scale() 方法来指定缩放因系数。
当你缩放一个父 widget 时,它的子 widget 也会相应被缩放。
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; transform: scale(1.5); }
- Dart
var container = Container( // gray box child: Center( child: Transform( child: Container( // red box child: Text( "Lorem ipsum", style: bold24Roboto, textAlign: TextAlign.center, ), decoration: BoxDecoration( color: Colors.red[400], ), padding: EdgeInsets.all(16.0), ), alignment: Alignment.center, transform: Matrix4.identity() ..scale(1.5), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
2.4 线性变换
将元素嵌套在一个 Container
widget 中,可以将线性变换应用在 widget 的背景上。之后,再用 Container widget 的 decoration
属性生成一个 BoxDecoration
对象,然后使用 BoxDecoration 的 gradient
属性来变换背景填充内容。
变换“角度”基于 Alignment (x, y) 取值来定:
-
如果开始和结束的 x 值相同,变换将是垂直的(0° 180°)。 -
如果开始和结束的 y 值相同,变换将是水平的(90° 270°)。
这里,只展示垂直变换的代码差异:
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { padding: 16px; color: #ffffff; background: linear-gradient(180deg, #ef5350, rgba(0, 0, 0, 0) 80%); }
- Dart
var container = Container( // grey box child: Center( child: Container( // red box child: Text( "Lorem ipsum", style: bold24Roboto, ), decoration: BoxDecoration( gradient: LinearGradient( begin: const Alignment(0.0, -1.0), end: const Alignment(0.0, 0.6), colors: <Color>[ const Color(0xffef5350), const Color(0x00ef5350) ], ), ), padding: EdgeInsets.all(16.0), ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
三、图形/形状
以下示例将展示如何新建和自定义图形。
3.1 圆角
在矩形上实现圆角,可以用 BoxDecoration
对象的 borderRadius
属性。新建一个 BorderRadius
对象来指定每个圆角的半径大小。
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* gray 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; border-radius: 8px; }
- Dart
var container = Container( // grey box child: Center( child: Container( // red circle child: Text( "Lorem ipsum", style: bold24Roboto, ), decoration: BoxDecoration( color: Colors.red[400], borderRadius: BorderRadius.all( const Radius.circular(8.0), ), ), padding: EdgeInsets.all(16.0), ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
3.2 阴影
在 CSS 中你可以通过 box-shadow 属性快速指定阴影偏移与模糊范围。比如如下两个盒阴影的属性设置:
xOffset: 0px, yOffset: 2px, blur: 4px, color: black @80% alpha xOffset: 0px, yOffset: 06x, blur: 20px, color: black @50% alpha
在 Flutter 中,每个属性与其取值都是单独指定的。请使用 BoxDecoration 的 boxShadow
属性来生成一系列 BoxShadow
widget。你可以定义一个或多个 BoxShadow widget,这些 widget 共同用于设置阴影深度、颜色等等。
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.8), 0 6px 20px rgba(0, 0, 0, 0.5); }
- Dart
var container = Container( // grey box child: Center( child: Container( // red box child: Text( "Lorem ipsum", style: bold24Roboto, ), decoration: BoxDecoration( color: Colors.red[400], boxShadow: <BoxShadow>[ BoxShadow ( color: const Color(0xcc000000), offset: Offset(0.0, 2.0), blurRadius: 4.0, ), BoxShadow ( color: const Color(0x80000000), offset: Offset(0.0, 6.0), blurRadius: 20.0, ), ], ), padding: EdgeInsets.all(16.0), ), ), width: 320.0, height: 240.0, decoration: BoxDecoration( color: Colors.grey[300], ), margin: EdgeInsets.only(bottom: 16.0), );
3.3 圆与椭圆
尽管 CSS 中有 基础图形 ,CSS 中一个生成圆的变通方案是:将矩形的四边 border-radius 均设成50%。
虽然 BoxDecoration
的 borderRadius
属性支持这样设置,Flutter 为 BoxShape enum
提供一个 shape
属性也用于实现同样的目的。
- Web
<div class="greybox"> <div class="redcircle"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* gray 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redcircle { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; text-align: center; width: 160px; height: 160px; border-radius: 50%; }
- Dart
var container = Container( // grey box child: Center( child: Container( // red circle child: Text( "Lorem ipsum", style: bold24Roboto, textAlign: TextAlign.center, ), decoration: BoxDecoration( color: Colors.red[400], shape: BoxShape.circle, ), padding: EdgeInsets.all(16.0), width: 160.0, height: 160.0, ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
四、文本
以下示例展示了如何设置字体和其他文本属性,除此外还包括一些特性比如如何变换文本字符、自定义间距以及生成摘录。
4.1 文字间距
在 CSS 中你可以通过分别给 letter-spacing 和 word-spacing 属性的长度赋值来指定每个字母以及每个单词间的空白距离。距离的单位可以是 px, pt, cm, em 等等。
在 Flutter 中,你可以在 Text widget 子元素 TextStyle
的 letterSpacing
与 wordSpacing
属性中将间距设置为逻辑像素(允许负值)。
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; letter-spacing: 4px; }
- Dart
var container = Container( // grey box child: Center( child: Container( // red box child: Text( "Lorem ipsum", style: TextStyle( color: Colors.white, fontSize: 24.0, fontWeight: FontWeight.w900, letterSpacing: 4.0, ), ), decoration: BoxDecoration( color: Colors.red[400], ), padding: EdgeInsets.all(16.0), ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
4.2 内联样式
一个 Text
widget 可以展示同一类样式的文本。为了展现具有多种样式的文本,需要改用 RichText
widget。它的 text
属性可以指定一个或多个可以单独设置样式的 TextSpan
widget。
在下例中,”Lorem” 位于 TextSpan widget 中,具有默认(继承自其父元素)文本样式,”ipsum” 位于具有自定义样式、单独的一个 TextSpan 中。
- Web
<div class="greybox"> <div class="redbox"> Lorem <em>ipsum</em> </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; } .redbox em { font: 300 48px Roboto; font-style: italic; }
- Dart
var container = Container( // grey box child: Center( child: Container( // red box child: RichText( text: TextSpan( style: bold24Roboto, children: <TextSpan>[ TextSpan(text: "Lorem "), TextSpan( text: "ipsum", style: TextStyle( fontWeight: FontWeight.w300, fontStyle: FontStyle.italic, fontSize: 48.0, ), ), ], ), ), decoration: BoxDecoration( backgroundColor: Colors.red[400], ), padding: EdgeInsets.all(16.0), ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
4.3 文本摘要
在 Web 中,我们常用省略号处理溢出的文本内容,且在 HTML/CSS 中,摘要不能超过一行。 如果要在多行之后进行截断,那么就需要 JavaScript 的帮助了。
在 Flutter 中,使用 Text
widget 的 maxLines
属性来指定包含在摘要中的行数,以及 overflow
属性来处理溢出文本。
- Web
<div class="greybox"> <div class="redbox"> Lorem ipsum dolor sit amet, consec etur </div> </div> .greybox { background-color: #e0e0e0; /* grey 300 */ width: 320px; height: 240px; font: 900 24px Roboto; display: flex; align-items: center; justify-content: center; } .redbox { background-color: #ef5350; /* red 400 */ padding: 16px; color: #ffffff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
- Dart
var container = Container( // grey box child: Center( child: Container( // red box child: Text( "Lorem ipsum dolor sit amet, consec etur", style: bold24Roboto, overflow: TextOverflow.ellipsis, maxLines: 1, ), decoration: BoxDecoration( backgroundColor: Colors.red[400], ), padding: EdgeInsets.all(16.0), ), ), width: 320.0, height: 240.0, color: Colors.grey[300], );
Teaser 截图自 flutter.io 官网。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
正则表达式必知必会(修订版)
福达 (Ben Forta) / 杨涛 / 人民邮电出版社 / 2015-1-1 / 29.00元
《正则表达式必知必会》从简单的文本匹配开始,循序渐进地介绍了很多复杂内容,其中包括回溯引用、条件性求值和前后查找,等等。每章都为读者准备了许多简明又实用的示例,有助于全面、系统、快速掌握正则表达式,并运用它们去解决实际问题。正则表达式是一种威力无比强大的武器,几乎在所有的程序设计语言里和计算机平台上都可以用它来完成各种复杂的文本处理工作。而且书中的内容在保持语言和平台中立的同时,还兼顾了各种平台之......一起来看看 《正则表达式必知必会(修订版)》 这本书的介绍吧!