整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          一個(gè)月帶你入門Flutter:UI篇(4)-一文搞定Flutter中的交互

          Flutter系列的文章我會(huì)持續(xù)更新一個(gè)月左右,力求利用1個(gè)月帶大家入門Flutter,抓住這波技術(shù)風(fēng)口,歡迎大家關(guān)注。同時(shí)如果覺得這里代碼排版不是很舒服的讀者可以關(guān)注我的微信公眾號(hào)“IT工匠”,我會(huì)同步更新,另外微信公眾號(hào)上還有很多互聯(lián)網(wǎng)必備資源(涉及算法、數(shù)據(jù)結(jié)構(gòu)、java、深度學(xué)習(xí)、計(jì)算機(jī)網(wǎng)絡(luò)、python、Android等互聯(lián)網(wǎng)技術(shù)資料),歡迎大家關(guān)注、交流。
          

          文的主要內(nèi)容:

          • 如何響應(yīng)點(diǎn)擊事件
          • 如何自定義Widget
          • Stateless Widget和Stateful Widget的不同

          Flutter中按照是否自身可直接響應(yīng)用戶交互可以將Widget分為兩類:

          • 第一類:自身可直接響應(yīng)用戶交互,指的是Widget自身具有如onTap這類的屬性,可以通過這類屬性直接監(jiān)聽用戶的點(diǎn)擊等事件,典型的比如FlatButton等
          • 第二類:自身不能直接響應(yīng)用戶交互,指的是Widget自身沒有入onTap這類屬性,不能直接監(jiān)聽用戶的點(diǎn)擊等事件,典型的比如Icon等

          由于第一類比較簡(jiǎn)單,本文重點(diǎn)介紹一下第二類,即如何為非交互性(不能直接響應(yīng)用戶交互)的Widget添加交互性, 具體來說,我們將通過創(chuàng)建一個(gè)自定義的Statful Widget來讓Icon具有交互性。

          在上一篇文章中我們介紹了如何構(gòu)建一個(gè)下面這樣的UI頁面:

          當(dāng)這個(gè)app第一次運(yùn)行的時(shí)候那個(gè)星星是紅色的,代表這個(gè)屏幕中展示的那個(gè)圖片被用戶點(diǎn)擊了喜歡,星星后面的數(shù)字47代表一共有47個(gè)用戶點(diǎn)擊了喜歡。本文將實(shí)現(xiàn),點(diǎn)擊星星后移除喜歡狀態(tài),用空心星星替換實(shí)心星星并減少星星后面的計(jì)數(shù)。 再次點(diǎn)擊空心星星代表添加喜歡,會(huì)繪制一顆實(shí)心的星星并增加星星后的數(shù)字。

          要實(shí)現(xiàn)此功能,您將創(chuàng)建一個(gè)包含星星和計(jì)數(shù)的自定義Widget, 點(diǎn)擊星星會(huì)更改兩個(gè)子Widget的狀態(tài),因此自定義的Widget應(yīng)該同時(shí)管理這兩個(gè)子Widget(星星和計(jì)數(shù))。

          首先我將會(huì)介紹一點(diǎn)前備知識(shí),如果你只對(duì)最終的代碼實(shí)現(xiàn)感興趣,你可以直接跳到第2步:創(chuàng)建StatefulWidget的子類,如果你想嘗試其他的管理狀態(tài)的方法,可以直接跳到管理狀態(tài)一節(jié)。

          Stateful Widget和Stateless Widget

          一個(gè)Widget要么是有狀態(tài)(stateful)的,要么是無狀態(tài)(stateless)的,如果一個(gè)Widget是可改變的,比如當(dāng)用戶與其交互的時(shí)候其會(huì)產(chǎn)生變化,這個(gè)Widget就是有狀態(tài)的(stateful)。

          一個(gè)無狀態(tài)(stateless)的Widget是永遠(yuǎn)不會(huì)發(fā)生改變的,Icon、IconButton、Text都是典型的無狀態(tài)的Widget,無狀態(tài)(stateless)的Widget都是StatelessWidget的子類。

          一個(gè)有狀態(tài)(stateful)的Widget是動(dòng)態(tài)的,比如它可以更改其外觀以響應(yīng)用戶交互或接收數(shù)據(jù)時(shí)觸發(fā)的事件。CheckBox、Radio、Slider、InkWell、Form、TextField都是典型的有狀態(tài)的Widget,有狀態(tài)(stateful)的Widget都是StatefulWidget的子類。

          Widget的狀態(tài)都是保存在State對(duì)象中的,從外觀上分析小部件的狀態(tài)。 狀態(tài)由可以更改的值組成,例如滑塊(slider)的當(dāng)前值、是否選中復(fù)選框(CheckBox)。 當(dāng)Widget的狀態(tài)發(fā)生變化時(shí),State對(duì)象調(diào)用會(huì)setState()方法來告訴框架重繪該Widget。

          創(chuàng)建一個(gè)有狀態(tài)的(stateful)Widget

          明確幾點(diǎn)概念:

          • 一個(gè)有狀態(tài)的Widget一定實(shí)現(xiàn)了2個(gè)類:StatefulWidget、State
          • State類包含Widget的可變狀態(tài)以及build()方法
          • 當(dāng)Widget的狀態(tài)(state)發(fā)生了改變,State對(duì)象將會(huì)調(diào)用setState()方法高速Flutter框架需要重繪當(dāng)前Widget

          本節(jié)將創(chuàng)建一個(gè)自定義的有狀態(tài)(Stateful)的Widget,我們將用我們自定義的包含一個(gè)IconButton和一個(gè)Text的Widget來替代原有的紅色星星Widget和計(jì)數(shù)Widget。

          實(shí)現(xiàn)一個(gè)自定義的Widget需要?jiǎng)?chuàng)建2個(gè)類:

          • 一個(gè)StatefulWidget類的子類,用于定義Widget
          • 一個(gè)State類的子類,包含了State對(duì)象,并且定義build()方法

          我們通過簡(jiǎn)單的幾步來構(gòu)建一個(gè)名為FavoriteWidget的自定義Widget:

          第1步:決定由那個(gè)對(duì)象來管理Widget的狀態(tài)(State)

          Widget的狀態(tài)(State)可以有多種管理方式,在此處由于切換星星的狀態(tài)(實(shí)心還是空心)是一個(gè)獨(dú)立的操作,不會(huì)影響父Widget或UI的其余部分,所以我們讓W(xué)idget自己管理自己的狀態(tài)(State)。

          關(guān)于詳細(xì)的狀態(tài)管理的內(nèi)容,我會(huì)在后面的管理狀態(tài)一節(jié)介紹。

          <span id="subclass-statefulWidget">第2步:創(chuàng)建StatefulWidget的子類</span>

          由于第1步我們已經(jīng)決定了FavoriteWidget自己管理自己的狀態(tài)(State),所以我們應(yīng)該重寫createState()方法來創(chuàng)建一個(gè)State對(duì)象。Flutter框架會(huì)在構(gòu)建Widget的時(shí)候調(diào)用對(duì)應(yīng)Widget的createState()方法。在這個(gè)例子中,我們應(yīng)該在createState()方法中返回一個(gè)我們將在下一步定義的_FavoriteWidgetState類的實(shí)例對(duì)象:

          class FavoriteWidget extends StatefulWidget {
           @override
           _FavoriteWidgetState createState() => _FavoriteWidgetState();
          }
          

          注意:這里的_開頭指的是定義的對(duì)應(yīng)類是私有的。

          第3步:創(chuàng)建State類的子類

          我們定義一個(gè)_FavoriteWidgetState類來存儲(chǔ)會(huì)在Widget不同生命周期變化的數(shù)據(jù),當(dāng)app第一次運(yùn)行的時(shí)候,UI界面應(yīng)該展示紅色的實(shí)心星星,代表當(dāng)前已經(jīng)選擇了”喜歡”狀態(tài),并且傍邊展示的文字為”41”,我們本別使用bool _isFavorited和int _favoriteCount變量來存儲(chǔ)這兩個(gè)狀態(tài):

          class _FavoriteWidgetState extends State<FavoriteWidget> {
           bool _isFavorited = true;
           int _favoriteCount = 41;
           // ···
          }
          

          _FavoriteWidgetState類同樣也定義了一個(gè)build()方法,在該方法中創(chuàng)建一個(gè)Row(行),Row中包含有一個(gè)Iconbutton和一個(gè)Text,我們使用Iconbutton而不是Icon的原因是IconButton有onPressed屬性,我們可以通過這個(gè)onPressed屬性定義處理點(diǎn)擊事件的回調(diào)函數(shù)(_toggleFavorite),我們將在后面具體定義這個(gè)_toggleFavorite函數(shù):

          class _FavoriteWidgetState extends State<FavoriteWidget> {
           // ···
           @override
           Widget build(BuildContext context) {
           return Row(
           mainAxisSize: MainAxisSize.min,
           children: [
           Container(
           padding: EdgeInsets.all(0),
           child: IconButton(
           icon: (_isFavorited ? Icon(Icons.star) : Icon(Icons.star_border)),
           color: Colors.red[500],
           onPressed: _toggleFavorite,
           ),
           ),
           SizedBox(
           width: 18,
           child: Container(
           child: Text('$_favoriteCount'),
           ),
           ),
           ],
           );
           }
          }
          

          注意:我們這里將Text作為子Widget放置在了SizedBox中,并且設(shè)置了SizedBox的寬度,這樣做的作用是固定Text的寬度,設(shè)想一下,當(dāng)Text中只顯示1位數(shù)字的時(shí)候Text的寬度和顯示2位數(shù)字的寬度一定是不一樣的,如果不固定Text的寬度,當(dāng)數(shù)字變化的時(shí)候就會(huì)出現(xiàn)Text寬度發(fā)生跳變的情況,導(dǎo)致視覺效果很不好。

          當(dāng)IconButton被點(diǎn)擊的時(shí)候?qū)?huì)調(diào)用_toggleFavorite()方法,我們?cè)赺toggleFavorite()方法中調(diào)用setstate()方法并更新狀態(tài),這樣Flutter框架就會(huì)知道需要重新繪制當(dāng)前Widget了,從而達(dá)到更新界面的效果:

          void _toggleFavorite() {
           setState(() {
           if (_isFavorited) {
           _favoriteCount -= 1;
           _isFavorited = false;
           } else {
           _favoriteCount += 1;
           _isFavorited = true;
           }
           });
          }
          

          setState()方法中的代碼邏輯很簡(jiǎn)單,首先判斷當(dāng)前_isFavorited的狀態(tài),然后對(duì)_isFavorited和_isFavorited的值進(jìn)行更新。

          第4步:將我們自定義的Stateful Widget加入到Widget樹中

          我們應(yīng)該在app的build()方法中將我們自定義的Stateful Widget加入到Widget 樹中,首先找到原先Icon和Text的位置,然后刪除原來的代碼,加入新的我們創(chuàng)建的Stateful Widget:

           Widget titleSection = Container(
           padding: const EdgeInsets.all(32),
           child: Row(
           children: [
           Expanded(
           /*1*/
           child: Column(
           crossAxisAlignment: CrossAxisAlignment.start,
           children: [
           /*2*/
           Container(
           padding: const EdgeInsets.only(bottom: 8),
           child: Text(
           'Oeschinen Lake Campground',
           style: TextStyle(
           fontWeight: FontWeight.bold,
           ),
           ),
           ),
           Text(
           'Kandersteg, Switzerland',
           style: TextStyle(
           color: Colors.grey[500],
           ),
           ),
           ],
           ),
           ),
           FavoriteWidget(),
           ],
           ),
           );
          

          然后運(yùn)行代碼(推薦使用熱更新),可以看到效果圖:

          管理狀態(tài)

          在我們的設(shè)計(jì)中,到底應(yīng)該由誰來管理Widget的狀態(tài)(State)?是Widget本身?是Widget的父Widget?還是二者共同管理?還是另一個(gè)對(duì)象來管理? 事實(shí)上有不止一種有效的方法可以使你的Widget小部件具有交互性, 作為Widget的設(shè)計(jì)者,你可以根據(jù)預(yù)期的Widget的使用方式做出決策。 以下是幾種最常用的管理狀態(tài)的方法:

          • 第一種:Widget自己管理自己本身的State
          • 第二種:Widget的父級(jí)Widget管理其State
          • 第三種:混合使用前兩種方法

          你可能會(huì)有疑問,你應(yīng)該如何決定具體使用哪一種狀態(tài)管理方法?這里提供幾個(gè)原則供你參考:

          • 如果狀態(tài)代表的是用戶數(shù)據(jù),比如CheckBox是否被選中,或者Slider(進(jìn)度條)的當(dāng)前進(jìn)度,這種情況下最好讓W(xué)idget的父級(jí)Widget去管理其狀態(tài)
          • 如果狀態(tài)代表的是界面展示方面的,比如動(dòng)畫,這種情況最好由Widget自己來管理自己的狀態(tài)

          如果你不太確定自己的場(chǎng)景屬于以上哪種,可以直接使用父級(jí)Widget管理的方法,因?yàn)檫@個(gè)方法是通用的。

          接下來我將通過創(chuàng)建三個(gè)簡(jiǎn)單示例(TapboxA,TapboxB和TapboxC)來舉例說明管理狀態(tài)的不同方法。 這幾個(gè)示例的工作方式類似: 每個(gè)都創(chuàng)建了一個(gè)Container,當(dāng)點(diǎn)擊時(shí),可以在綠色或灰色框之間切換, _active布爾值確定顏色:true代表綠色,false代表灰色。

          Widget自己管理自己本身的State

          有時(shí),由Widget自己管理自己的狀態(tài)可以產(chǎn)生很強(qiáng)大的功能。例如,ListView在其內(nèi)容的總尺寸超出其最大渲染框的尺寸時(shí)會(huì)自動(dòng)進(jìn)行滾動(dòng),這個(gè)滾動(dòng)的狀態(tài)是由ListView自己管理的,不需要我們開發(fā)人員去手動(dòng)設(shè)置它什么時(shí)候應(yīng)該開始滾動(dòng)、什么時(shí)候應(yīng)該停止?jié)L動(dòng)。

          我們通過一個(gè)示例來進(jìn)行說明,我們創(chuàng)建一個(gè)_TapboxAState類:

          • 管理TapboxA的狀態(tài)
          • 定義布爾值_activity,代表當(dāng)前Widget的顏色
          • 定義_handleTap()方法,當(dāng)Widget被點(diǎn)擊時(shí)在該方法中調(diào)用setState()并更新 _activity的值從而達(dá)到更新UI的目的
          • 實(shí)現(xiàn)Widget的所有交互行為

          代碼如下:

          // TapboxA 自己管理自己的狀態(tài)
          //------------------------- TapboxA ----------------------------------
          class TapboxA extends StatefulWidget {
           TapboxA({Key key}) : super(key: key);
           @override
           _TapboxAState createState() => _TapboxAState();
          }
          class _TapboxAState extends State<TapboxA> {
           bool _active = false;
           void _handleTap() {
           setState(() {
           _active = !_active;
           });
           }
           Widget build(BuildContext context) {
           return GestureDetector(
           onTap: _handleTap,
           child: Container(
           child: Center(
           child: Text(
           _active ? 'Active' : 'Inactive',
           style: TextStyle(fontSize: 32.0, color: Colors.white),
           ),
           ),
           width: 200.0,
           height: 200.0,
           decoration: BoxDecoration(
           color: _active ? Colors.lightGreen[700] : Colors.grey[600],
           ),
           ),
           );
           }
          }
          //------------------------- MyApp ----------------------------------
          class MyApp extends StatelessWidget {
           @override
           Widget build(BuildContext context) {
           return MaterialApp(
           title: 'Flutter Demo',
           home: Scaffold(
           appBar: AppBar(
           title: Text('Flutter Demo'),
           ),
           body: Center(
           child: TapboxA(),
           ),
           ),
           );
           }
          }
          

          運(yùn)行效果如下圖所示:

          Widget的父級(jí)Widget管理其State

          父Widget管理子Widget狀態(tài)的最大用處是在合適的時(shí)機(jī)通知子Widget進(jìn)行UI更新。 例如,IconButton允許你將Icon視為可點(diǎn)擊的按鈕, IconButton是一個(gè)無狀態(tài)的Widget,所以我們應(yīng)該通過父Widget來確定Iconutton是否已被點(diǎn)擊。

          在以下例子中,TapboxB將其狀態(tài)回調(diào)給父Widget,因?yàn)門apboxB不管理任何狀態(tài),所以它是StatelessWidget的子類。

          在這個(gè)示例中我們應(yīng)該實(shí)現(xiàn)2個(gè)類:ParentWidgetState(代表父Widget)、TapboxB(代表子Widget)

          ParentWidgetState的主要功能:

          • 為TapboxB管理_activity狀態(tài)
          • 實(shí)現(xiàn) _handleTapboxChanged()方法,該方法會(huì)在TapboxB被點(diǎn)擊時(shí)調(diào)用
          • 當(dāng)狀態(tài)發(fā)生改變時(shí)調(diào)用setState()來更新UI

          TapboxB的主要功能:

          • 繼承StatelessWidget類,因?yàn)門apboxB不用管理自己的狀態(tài)
          • 當(dāng)點(diǎn)擊事件(tap)被觸發(fā)的時(shí)候通知父Widget

          代碼實(shí)現(xiàn)如下:

          // ParentWidget為TapboxB管理狀態(tài).
          //------------------------ ParentWidget --------------------------------
          class ParentWidget extends StatefulWidget {
           @override
           _ParentWidgetState createState() => _ParentWidgetState();
          }
          class _ParentWidgetState extends State<ParentWidget> {
           bool _active = false;
           void _handleTapboxChanged(bool newValue) {
           setState(() {
           _active = newValue;
           });
           }
           @override
           Widget build(BuildContext context) {
           return Container(
           child: TapboxB(
           active: _active,
           onChanged: _handleTapboxChanged,
           ),
           );
           }
          }
          //------------------------- TapboxB ----------------------------------
          class TapboxB extends StatelessWidget {
           TapboxB({Key key, this.active: false, @required this.onChanged})
           : super(key: key);
           final bool active;
           final ValueChanged<bool> onChanged;
           void _handleTap() {
           onChanged(!active);
           }
           Widget build(BuildContext context) {
           return GestureDetector(
           onTap: _handleTap,
           child: Container(
           child: Center(
           child: Text(
           active ? 'Active' : 'Inactive',
           style: TextStyle(fontSize: 32.0, color: Colors.white),
           ),
           ),
           width: 200.0,
           height: 200.0,
           decoration: BoxDecoration(
           color: active ? Colors.lightGreen[700] : Colors.grey[600],
           ),
           ),
           );
           }
          }
          

          代碼的運(yùn)行效果如下:

          混合使用前兩種管理方法

          對(duì)于某些Widget,使用混合的方法管理其狀態(tài)很有有意義。 在這種情況下,有狀態(tài)(stateful)的Widget和其父Widget分別管理其一部分狀態(tài)(State)。

          在TapboxC示例中,在點(diǎn)擊時(shí),框周圍會(huì)出現(xiàn)深綠色邊框,點(diǎn)擊后,邊框消失,框的顏色也會(huì)改變。 TapboxC將其 _active狀態(tài)導(dǎo)出到其父Widget,在內(nèi)部管理只其 _highlight狀態(tài),所以 此示例有兩個(gè)State對(duì)象,_ParentWidgetState和_TapboxCState:

          _ParentWidgetState的功能:

          • 管理_activity狀態(tài)
          • 實(shí)現(xiàn)_handleTapboxChanged()方法,該方法會(huì)在方框被點(diǎn)擊后調(diào)用
          • 當(dāng)點(diǎn)擊事件發(fā)生后調(diào)用setState()并改變_activity的值以更新UI

          _TapboxCState的功能:

          • 管理_highlight狀態(tài)
          • GestureDetector監(jiān)聽所有的點(diǎn)擊事件,當(dāng)用戶手指點(diǎn)下的時(shí)候添加高亮邊框,當(dāng)用戶手指抬起的時(shí)候取消高亮邊框
          • 當(dāng)點(diǎn)擊事件發(fā)生時(shí),根據(jù)父Widget傳遞的狀態(tài)進(jìn)行相應(yīng)操作
          //---------------------------- ParentWidget ----------------------------
          class ParentWidget extends StatefulWidget {
           @override
           _ParentWidgetState createState() => _ParentWidgetState();
          }
          class _ParentWidgetState extends State<ParentWidget> {
           bool _active = false;
           void _handleTapboxChanged(bool newValue) {
           setState(() {
           _active = newValue;
           });
           }
           @override
           Widget build(BuildContext context) {
           return Container(
           child: TapboxC(
           active: _active,
           onChanged: _handleTapboxChanged,
           ),
           );
           }
          }
          //----------------------------- TapboxC ------------------------------
          class TapboxC extends StatefulWidget {
           TapboxC({Key key, this.active: false, @required this.onChanged})
           : super(key: key);
           final bool active;
           final ValueChanged<bool> onChanged;
           _TapboxCState createState() => _TapboxCState();
          }
          class _TapboxCState extends State<TapboxC> {
           bool _highlight = false;
           void _handleTapDown(TapDownDetails details) {
           setState(() {
           _highlight = true;
           });
           }
           void _handleTapUp(TapUpDetails details) {
           setState(() {
           _highlight = false;
           });
           }
           void _handleTapCancel() {
           setState(() {
           _highlight = false;
           });
           }
           void _handleTap() {
           widget.onChanged(!widget.active);
           }
           Widget build(BuildContext context) {
           // This example adds a green border on tap down.
           // On tap up, the square changes to the opposite state.
           return GestureDetector(
           onTapDown: _handleTapDown, // Handle the tap events in the order that
           onTapUp: _handleTapUp, // they occur: down, up, tap, cancel
           onTap: _handleTap,
           onTapCancel: _handleTapCancel,
           child: Container(
           child: Center(
           child: Text(widget.active ? 'Active' : 'Inactive',
           style: TextStyle(fontSize: 32.0, color: Colors.white)),
           ),
           width: 200.0,
           height: 200.0,
           decoration: BoxDecoration(
           color:
           widget.active ? Colors.lightGreen[700] : Colors.grey[600],
           border: _highlight
           ? Border.all(
           color: Colors.teal[700],
           width: 10.0,
           )
           : null,
           ),
           ),
           );
           }
          }
          

          運(yùn)行效果如下所示:

          替代實(shí)現(xiàn)可能已將高亮狀態(tài)導(dǎo)出到父級(jí),同時(shí)保持活動(dòng)狀態(tài)為內(nèi)部,但如果您要求某人使用該分接框,他們可能會(huì)抱怨它沒有多大意義。 開發(fā)人員關(guān)心該框是否處于活動(dòng)狀態(tài)。 開發(fā)人員可能并不關(guān)心如何管理突出顯示,并且更喜歡點(diǎn)按框處理這些細(xì)節(jié)。

          其他的交互式Widget

          Flutter提供了很多按鈕和類似的交互式Widget。 這些Widget中的大多數(shù)都實(shí)現(xiàn)了Material Design準(zhǔn)則,該準(zhǔn)則定義了一組具有固定用戶界面的組件。

          如果您愿意,可以使用GestureDetector在任何自定義的Widget中構(gòu)建交互性。 您可以在管理狀態(tài)一節(jié)中找到GestureDetector的使用示例。

          提示:Flutter還提供了一些IOS風(fēng)格的Widget,稱之為Cupertino,具體地址:https://api.flutter.dev/flutter/cupertino/cupertino-library.html

          當(dāng)您需要交互性時(shí),最簡(jiǎn)單的方法是使用Flutter已經(jīng)給我提供好的Widget,下面是一個(gè)部分列表:

          標(biāo)準(zhǔn)庫中的Widget

          • Form,地址:https://api.flutter.dev/flutter/widgets/Form-class.html
          • FormField,地址:https://api.flutter.dev/flutter/widgets/FormField-class.html

          Material庫中的Widget

          • Checkbox 地址:https://api.flutter.dev/flutter/material/Checkbox-class.html
          • DropdownButton ,地址:https://api.flutter.dev/flutter/material/DropdownButton-class.html
          • FlatButton , 地址:https://api.flutter.dev/flutter/material/FlatButton-class.html
          • FloatingActionButton , 地址:https://api.flutter.dev/flutter/material/FloatingActionButton-class.html
          • IconButton ,地址:https://api.flutter.dev/flutter/material/IconButton-class.html
          • Radio ,地址:https://api.flutter.dev/flutter/material/Radio-class.html
          • RaisedButton ,地址:https://api.flutter.dev/flutter/material/RaisedButton-class.html
          • Slider ,地址:https://api.flutter.dev/flutter/material/Slider-class.html
          • Switch ,地址:https://api.flutter.dev/flutter/material/Switch-class.html
          • TextField ,地址:https://api.flutter.dev/flutter/material/TextField-class.html

          好了,本文的全部?jī)?nèi)容到這里就結(jié)束了,總結(jié)一下,本文我們主要介紹了如何給Flutter中的Widget添加交互性,下一篇文章我們將介紹如何油壓地給Flutter項(xiàng)目中添加并引用資源和圖片,歡迎大家關(guān)注。

          單標(biāo)簽

          網(wǎng)頁(程序)如果要和用戶產(chǎn)生互動(dòng),則必須借助一定的中介,這個(gè)中介一般是:文本輸入框、按鈕、多選框、單選框。而表單則是這些中介和放置這些中介的空間(<form action=”” methon=””></form>)。

          在網(wǎng)頁中,這些文本輸入框、按鈕等等必須放置在由<form></form>這個(gè)標(biāo)簽所定義的空間中,否則沒有實(shí)際意義。所以,由<form></form>標(biāo)簽所定義的空間就是表單存在的空間。


          【各種輸入類型】

          1. 文字輸入框:每個(gè)表單之所以會(huì)有不同的類型,原因就在于type="表單類型"設(shè)定的不同而已,我們就先來看看第一個(gè)類型:文字輸入列。文字輸入列的形態(tài)就是type="text,其使用方法如下:

          呈現(xiàn)結(jié)果

          姓名:

          原始碼

          <form action=http://www.baidu.com/nameproject.aspmethon=”post”>

          姓名:<input type="text" name="name" size="20">

          </form>

          它有下列可設(shè)定之屬性:

          • name="名稱",是設(shè)定此一欄位的名稱,程式中常會(huì)用到。
          • size="數(shù)值",是設(shè)定此一欄位顯現(xiàn)的寬度。
          • value="預(yù)設(shè)內(nèi)容",是設(shè)定此一欄位的預(yù)設(shè)內(nèi)容。
          • align="對(duì)齊方式",是設(shè)定此一欄位的對(duì)齊方式,其值有:top(向上對(duì)齊)、middle(向中對(duì)齊)、bottom(向下對(duì)齊)、right(向右對(duì)齊)、left(向左對(duì)齊)、texttop(向文字頂部對(duì)齊)、baseline(向文字底部對(duì)齊)、absmiddle(絕對(duì)置中)、absbottom(絕對(duì)置下)等。
          • maxlength="數(shù)值",是設(shè)定此一欄位可設(shè)定輸入的最大長(zhǎng)度。


          1. 單選框:利用type="radio"就會(huì)產(chǎn)生單選核取表單,單選核取表單通常是好幾個(gè)選項(xiàng)一起擺出來供使用者點(diǎn)選,一次只能從中選一個(gè),故為單選核取表單。

          呈現(xiàn)結(jié)果

          性別:男 女

          原始碼

          <form>

          性別:

          男 <input type="radio" name="sex" value="boy">

          女 <input type="radio" name="sex" value="girl">

          </form>

          它有下列可設(shè)定之屬性:

          • name="名稱",是設(shè)定此一欄位的名稱,程式中常會(huì)用到。
          • value="內(nèi)容",是設(shè)定此一欄位的內(nèi)容、值或是意義。
          • align="對(duì)齊方式",是設(shè)定此一欄位的對(duì)齊方式,其值有:top(向上對(duì)齊)、middle(向中對(duì)齊)、bottom(向下對(duì)齊)、right(向右對(duì)齊)、left(向左對(duì)齊)、texttop(向文字頂部對(duì)齊)、baseline(向文字底部對(duì)齊)、absmiddle(絕對(duì)置中)、absbottom(絕對(duì)置下)等。
          • checked,是設(shè)定此一欄位為預(yù)設(shè)選取值。


          1. 復(fù)選框:利用type=" checkbox "就會(huì)產(chǎn)生復(fù)選核取表單,復(fù)選核取表單通常是好幾個(gè)選項(xiàng)一起擺出來供使用者點(diǎn)選,一次可以同時(shí)選好幾個(gè),故為復(fù)選核取表單。

          呈現(xiàn)結(jié)果

          喜好: 電影 看書

          原始碼

          <form>

          喜好:

          <input type="checkbox" name="sex" value="movie">電影

          <input type="checkbox" name="sex" value="book">看書

          </form>

          它有下列可設(shè)定之屬性:

          • name="名稱",是設(shè)定此一欄位的名稱,程式中常會(huì)用到。
          • value="內(nèi)容",是設(shè)定此一欄位的內(nèi)容、值或是意義。
          • align="對(duì)齊方式",是設(shè)定此一欄位的對(duì)齊方式,其值有:top(向上對(duì)齊)、middle(向中對(duì)齊)、bottom(向下對(duì)齊)、right(向右對(duì)齊)、left(向左對(duì)齊)、texttop(向文字頂部對(duì)齊)、baseline(向文字底部對(duì)齊)、absmiddle(絕對(duì)置中)、absbottom(絕對(duì)置下)等。
          • checked,是設(shè)定此一欄位為預(yù)設(shè)選取值。


          1. 密碼表單:利用type=" password "就會(huì)產(chǎn)生一個(gè)密碼表單,密碼表單和文字輸入表單長(zhǎng)得幾乎一樣,差別就在于密碼表單在輸入時(shí)全部會(huì)以星號(hào)來取代輸入的文字,以防他人偷窺。

          呈現(xiàn)結(jié)果

          請(qǐng)輸入密碼:

          原始碼

          <form>

          請(qǐng)輸入密碼:<input type="password" name="input">

          </form>

          它有下列可設(shè)定之屬性:

          • name="名稱",是設(shè)定此一欄位的名稱,程式中常會(huì)用到。
          • size="數(shù)值",是設(shè)定此一欄位顯現(xiàn)的寬度。
          • value="預(yù)設(shè)內(nèi)容",是設(shè)定此一欄位的預(yù)設(shè)內(nèi)容,不過呈現(xiàn)出來仍是星號(hào)。
          • align="對(duì)齊方式",是設(shè)定此一欄位的對(duì)齊方式,其值有:top(向上對(duì)齊)、middle(向中對(duì)齊)、bottom(向下對(duì)齊)、right(向右對(duì)齊)、left(向左對(duì)齊)、texttop(向文字頂部對(duì)齊)、baseline(向文字底部對(duì)齊)、absmiddle(絕對(duì)置中)、absbottom(絕對(duì)置下)等。
          • maxlength="數(shù)值",是設(shè)定此一欄位可設(shè)定輸入的最大長(zhǎng)度。


          1. 送出按鈕:通常我們表單填完之后,都會(huì)有一個(gè)送出按鈕以及清除重寫的按鈕,分別是利用type=" submit "及type=" reset "來產(chǎn)生,相當(dāng)?shù)暮?jiǎn)單易用。

          呈現(xiàn)結(jié)果

          原始碼

          <form>

          <input type="submit" value="送出資料">

          <input type="reset" value="重新填寫">

          </form>

          它有下列可設(shè)定之屬性:

          • name="名稱",是設(shè)定此一按鈕的名稱。
          • value="文字",是設(shè)定此一按鈕上要呈現(xiàn)的文字,若是沒有設(shè)定,瀏覽器也會(huì)自動(dòng)替您加上“送出查詢”、“重設(shè)”等字樣。
          • align="對(duì)齊方式",是設(shè)定此一欄位的對(duì)齊方式,其值有:top(向上對(duì)齊)、middle(向中對(duì)齊)、bottom(向下對(duì)齊)、right(向右對(duì)齊)、left(向左對(duì)齊)、texttop(向文字頂部對(duì)齊)、baseline(向文字底部對(duì)齊)、absmiddle(絕對(duì)置中)、absbottom(絕對(duì)置下)等。


          1. 按鈕元件:表單中或是java script常會(huì)用到按鈕來作一些效果,因此,我們可以利用type=" button "來產(chǎn)生一個(gè)按鈕,相當(dāng)簡(jiǎn)單。

          呈現(xiàn)結(jié)果

          請(qǐng)按下按鈕:

          原始碼

          <form>

          請(qǐng)按下按鈕:<input type="button" name="ok" value="我同意">

          </form>

          它有下列可設(shè)定之屬性:

          • name="名稱",是設(shè)定此一按鈕的名稱。
          • value="文字",是設(shè)定此一按鈕上要呈現(xiàn)的文字。
          • align="對(duì)齊方式",是設(shè)定此一欄位的對(duì)齊方式,其值有:top(向上對(duì)齊)、middle(向中對(duì)齊)、bottom(向下對(duì)齊)、right(向右對(duì)齊)、left(向左對(duì)齊)、texttop(向文字頂部對(duì)齊)、baseline(向文字底部對(duì)齊)、absmiddle(絕對(duì)置中)、absbottom(絕對(duì)置下)等。


          1. 隱藏欄位:表單中有時(shí)有些東西因?yàn)槟承┮蛩兀幌胱屖褂谜呖吹剑虺淌叫枰獏s又不得不存在,此時(shí),我們就可以利用type=" hidden "來產(chǎn)生一個(gè)隱藏的欄位。

          呈現(xiàn)結(jié)果

          隱藏欄位:

          原始碼

          <form>

          隱藏欄位:<input type="hidden" name="nosee" value="看不到">

          </form>

          它有下列可設(shè)定之屬性:

          • name="名稱",是設(shè)定此一欄位的名稱。
          • value="文字",是設(shè)定此一欄位的值、文字或意義。

          【大量文字輸入元件】

          1. 有時(shí)候我們會(huì)希望讓使用者輸入比較大量的文字,此時(shí),文字輸入列就顯得不敷使用,因此我們就可以利用<textarea></textarea>來產(chǎn)生一個(gè)可以輸入大量文字的元件,夾在兩個(gè)標(biāo)簽中的文字會(huì)出現(xiàn)在框框中,可作為預(yù)設(shè)文字。

          呈現(xiàn)結(jié)果

          請(qǐng)輸入您的意見:

          原始碼

          <form>

          請(qǐng)輸入您的意見:<br>

          <textarea name="talk" cols="20" rows="3"></textarea>

          </form>

          它有下列可設(shè)定之屬性:

          • name="名稱",是設(shè)定此一欄位的名稱。
          • wrap="設(shè)定值",是設(shè)定此一欄位的換行模式。設(shè)定值有三種:off(輸入文字不會(huì)自動(dòng)換行)、virtual(輸入文字在螢?zāi)簧蠒?huì)自動(dòng)換行,不過若是使用者沒有自行按下enter換行,送出資料時(shí),也視為沒有換行)、physical(輸入文字會(huì)自動(dòng)換行,送出資料時(shí),會(huì)將螢?zāi)簧系淖詣?dòng)換行,視為換行效果送出)。
          • cols="數(shù)值",是設(shè)定此一欄位的行數(shù)(橫向字?jǐn)?shù))。
          • rows="數(shù)值",是設(shè)定此一欄位的列數(shù)(垂直字?jǐn)?shù))。


          【下拉式選單】

          1. 下拉式選單令整個(gè)網(wǎng)頁看起來有很專業(yè)的感覺,我們只要利用<select name="名稱">便可以產(chǎn)生一個(gè)下拉式選單,另外,還需要配合<option>標(biāo)簽來產(chǎn)生選項(xiàng),這樣才算完整喔!

          呈現(xiàn)結(jié)果

          您喜歡看書嗎?:

          非常喜歡

          還算喜歡

          不太喜歡

          非常討厭

          原始碼

          <form>

          您喜歡看書嗎?:

          <select name="like">

          <option value="非常喜歡">非常喜歡

          <option value="還算喜歡">還算喜歡

          <option value="不太喜歡">不太喜歡

          <option value="非常討厭">非常討厭

          </select>

          </form>

          它有下列可設(shè)定之屬性:

          1. size="數(shù)值",是設(shè)定此一欄位的大小,預(yù)設(shè)值為1,若是您的選項(xiàng)有四個(gè),然后您將size設(shè)成4,那么,下拉式選單便會(huì)變成選項(xiàng)方塊,將四個(gè)選項(xiàng)一起呈現(xiàn)在方塊中。

          multiple,是設(shè)定此一欄位為復(fù)選,可以一次選好幾個(gè)選項(xiàng)。

          ....................................................................

          我的微信公眾號(hào):UI嚴(yán)選 —越努力,越幸運(yùn)

          TMl 的標(biāo)簽可以分為單個(gè)標(biāo)簽和成對(duì)標(biāo)簽。

          單個(gè)標(biāo)簽:html4 規(guī)定單個(gè)標(biāo)簽要有一個(gè) / 表示結(jié)尾, html5 則不用

          <!--單個(gè)標(biāo)簽-->
          <meta>
          <!--成對(duì)標(biāo)簽 -->
          <div></div>

          以下是HTMl中常用的一些標(biāo)簽


          div 標(biāo)簽

          div 標(biāo)簽 主要用來將相關(guān)的內(nèi)容組合到一塊,就像菜市場(chǎng)把各個(gè)蔬菜分成不同種類區(qū)分?jǐn)[放是一個(gè)道理。

          div 是最常見也是比較重要的標(biāo)簽,網(wǎng)頁布局中經(jīng)常使用的一類標(biāo)簽。通常布局被稱為 DIV + CSS 布局

          <div>
            div 就是一個(gè)分類的存儲(chǔ)箱子
          </div>


          p標(biāo)簽

          p標(biāo)簽表示段落, 在網(wǎng)頁文字中應(yīng)用的比較多

          <!--段落和段落間會(huì)換行-->
          <p>第一段</p>
          <p>第二段</p>


          H-標(biāo)題標(biāo)簽

          h標(biāo)簽分為六個(gè)

          標(biāo)簽

          語義

          h1

          一級(jí)標(biāo)題

          h2

          二級(jí)標(biāo)題

          h3

          三級(jí)標(biāo)題

          h4

          四級(jí)標(biāo)題

          h5

          五級(jí)標(biāo)題

          h6

          六級(jí)標(biāo)題

          引用標(biāo)題標(biāo)簽后,字體會(huì)加粗、字號(hào)一會(huì)變大


          ul 無序標(biāo)簽

          無序標(biāo)簽是沒有顯示順序的列表,無序列表前面通常會(huì)有一個(gè)“小點(diǎn)”, 這個(gè)小點(diǎn)可以用type屬性控制。其中有三個(gè)展示方式(不過這種方式比較固定,不夠靈活和美觀, 已經(jīng)被CSS的效果代替),如下:

          值(type屬性)

          描述

          disc

          默認(rèn)值,實(shí)心圓

          circle

          空心圓

          square

          實(shí)心方框

          舉例:

          <!--ul標(biāo)簽內(nèi)部只能放置li標(biāo)簽-->
          <!--li標(biāo)簽內(nèi)部可以放其他的標(biāo)簽-->
          <ul type=">
              <li>無序列表元素1</li> <!--列表項(xiàng)-->
              <li>無序列表元素2</li>
          </ul>
          
          
          
          
          實(shí)心圓
          <ul type="disc">
            <li>西紅柿</li>
            <li>黃瓜</li>
          </ul>
          空心圓
          <ul type="circle">
            <li>西紅柿</li>
            <li>黃瓜</li>
          </ul>
          實(shí)心方框
          <ul type="square">
            <li>西紅柿</li>
            <li>黃瓜</li>
          </ul>


          ol 有序標(biāo)簽

          • ol 前面的標(biāo)簽是有序的,可以是數(shù)字、字母、羅馬數(shù)字等。同樣控制這些樣式使用的是type屬性。

          type屬性值

          意義

          a

          小寫英文字母編號(hào)

          A

          大寫英文字母編號(hào)

          i

          小寫羅馬數(shù)字編號(hào)

          I

          大寫羅馬數(shù)字編號(hào)

          1

          數(shù)字編號(hào)(默認(rèn))

          • 設(shè)置start屬性,表示從哪個(gè)編號(hào)開始
          • 加 reversed 表示倒敘排列


          有序列表, 從2開始
          <ol start="2">
            <li>元素1</li>
            <li>元素2</li>
          </ol>
          
          
          小寫字母表示
          <ol type="a">
            <li>元素1</li>
            <li>元素2</li>
            <li>元素3</li>
          </ol>
          
          
          倒敘
          <ol reversed>
            <li>元素1</li>
            <li>元素2</li>
            <li>元素3</li>
          </ol>


          dl 自定義列表

          dl標(biāo)簽表示自定義列表

          dt表示數(shù)據(jù)項(xiàng),dd表示數(shù)據(jù)定義, dd是dt標(biāo)簽的解釋


          <dl>
              <dt>西紅柿</dt>
              <dd>紅、酸</dd>
              <dt>黃瓜</dt>
              <dd>綠、澀</dd>
            </dl>


          img標(biāo)簽

          img 用來插入圖片,包括但不限于以下圖片格式

          圖片格式

          備注

          .jpg、.jpeg

          通常用于照片,是一種有損壓縮格式

          .png

          通常用于logo、背景,支持透明和半透明。便攜式網(wǎng)絡(luò)圖像

          .svg

          矢量圖片


          <!-- src(source)屬性, 圖片地址,可以為相對(duì)路徑,也可以為絕對(duì)路徑-->
          <!-- alt 如果遇到圖片無法加載的情況,網(wǎng)頁上會(huì)展示 alt的 值 -->
          <!-- width 和 height 表示 寬和高, 如果只設(shè)置一個(gè), 那么另外一個(gè)就會(huì)跟著成比例縮放-->
          <img src="./images/images.jpg" alt="星期一" width="120" height="20">


          a 標(biāo)簽

          用a標(biāo)簽來制作超級(jí)鏈接

          <!-- href 屬性 表示 其他頁面的鏈接,支持相對(duì)路徑和絕對(duì)路徑,還可以鏈接到其它網(wǎng)站 -->
          <!--target 屬性表示 打開其他鏈接的方式-->
          <!-- title 屬性表示 鏈接的標(biāo)題, 當(dāng)鼠標(biāo)移動(dòng)到鏈接上,會(huì)展示出來-->
          <a href="http://www.baidu.com" target="blank" title="文字標(biāo)題">百度</a>
          
          
          
          
          
          
          <!--也可以用a標(biāo)簽作為錨點(diǎn) 錨點(diǎn)可以是本頁面的錨點(diǎn),也可以是其他頁面的錨點(diǎn)-->
          <h1 id="title">頭部標(biāo)題</h1>
          ... 此處省略一些代碼
          <a href="#title">返回標(biāo)題</a>
          
          
          
          
          <!--下載鏈接,指向 doc, zip, zip等文件格式時(shí),a標(biāo)簽將成為自動(dòng)下載鏈接-->
          <a href="./download/halou.zip">發(fā)郵件</a>
          <!-- mailto:前綴的鏈接是郵件鏈接,系統(tǒng)將自動(dòng)打開email相關(guān)軟件-->
          <a href="mailto:halouworld@126.com">發(fā)郵件</a>
          <!-- tel: 前綴鏈接是電話鏈接,系統(tǒng)將自動(dòng)打開撥號(hào)鍵-->
          <a href="tel:11111111111">打開撥號(hào)鍵盤</a>


          audio標(biāo)簽

          audio標(biāo)簽用來插入音頻標(biāo)簽

          <!--添加 controls 后才會(huì)顯示 播放控件-->
          <!--常用音頻格式 mp3 和 ogg格式-->
          <!--autoplay 自動(dòng)播放屬性-->
          <!--loop 屬性表示循環(huán)播放-->
          <audio controls src="./video/demo.mp3">
                 您的瀏覽器不支持 audio標(biāo)簽,請(qǐng)升級(jí)
          </audio>
          
          
          
          
          <audio controls src="./video/demo.mp3" autoplay loop>
               您的瀏覽器不支持 audio標(biāo)簽,請(qǐng)升級(jí)
          </audio>

          video標(biāo)簽

          video 標(biāo)簽用于插入一段視頻

          <!--有的視頻不能播放 ,詳見 https://blog.csdn.net/weixin_34272308/article/details/94614657 -->
          <!-- controls 顯示視頻播放控件  -->
          <!-- autoplay 自動(dòng)播放 -->
          <!-- loop 循環(huán)播放 -->
          <!-- 常見的 視頻格式 mp4 ogv webm 等-->
          <video controls autoplay loop src="./video/5-4 RDB2.mp4" >
              您的瀏覽器不支持 video標(biāo)簽,請(qǐng)升級(jí)
          </video>


          其它區(qū)塊標(biāo)簽

          以前的區(qū)塊標(biāo)簽只有div,現(xiàn)在為了更好的方便搜索引擎抓取網(wǎng)站,因此有了以下語義更加明確的區(qū)塊標(biāo)簽

          <section>

          文檔的區(qū)域,比div語義上還要大一點(diǎn)

          <header>

          頁頭

          <main>

          網(wǎng)頁核心部分

          <footer>

          頁腳


          其他的語義標(biāo)簽

          • span 標(biāo)記文本標(biāo)記區(qū)域,沒有特殊效果,結(jié)合CSS使用
          • b 標(biāo)簽 加粗文章(可以使用CSS實(shí)現(xiàn)同樣效果)
          • u 加下?lián)Q線文字
          • br 換行
          • i 傾斜文字(可以使用CSS實(shí)現(xiàn)同樣效果)
          • strong 代表特別重要的文字
          • em 需要強(qiáng)調(diào)的文字,有一定的傾斜,也可以用其配置CSS做表情文字
          • mark 高亮文字
          • figure 和 figcaption 。figure - 一段獨(dú)立的內(nèi)容 figcaption- figure 內(nèi)部元素的說明性內(nèi)容


          表單

          表單用來收集信息并且可以完成和后端的數(shù)據(jù)傳輸

          表單中大致可以分為三種標(biāo)簽

          • form標(biāo)簽,標(biāo)識(shí)表單區(qū)域, 內(nèi)部的元素都可能被表單提取信息
          • input 標(biāo)簽, 標(biāo)識(shí)輸入、點(diǎn)擊等需要和用戶交互的場(chǎng)景
          • datalist 下拉框,支持搜索,通常和input一塊使用

          一些表單的示例

          <!--action 表示要提交到后端的網(wǎng)址-->
          <!--method 表示表單提交的方式,通常有 get 、 post 、put、delete等-->
          
          
          <form action="/save" meththo="post"></form>
          
          
          <!--<form> 標(biāo)簽中 input 文本框 type="text" 表示文本框-->
          <!-- value 表示文本框中的值 -->
          <!--planceholder表示提示文字,在沒任何輸入值的情況下,作為提示信息-->
          <!--disabled 表示禁用-->
          <input type="text" value="123" planceholder="提示文字" disabled>
          
          
          <!---單選按鈕,name相等,表示選擇了一個(gè),另一個(gè)就不能選擇了-->
          <!--checked 表示默認(rèn)被選中-->
          <!-- value 屬性表示要提交到后端服務(wù)器的值-->
          <input type="radio" name="radio_group" checked>
          <input type="radio"  name="radio_group">
          
          
          
          
          <label>
              <input type="radio" name="sex"> 男
          </label>
          <label> 
              <input type="radio" name="sex"> 女
          </label>
          
          
          
          
          <!--html4 中的標(biāo)簽 通過for 屬性 和 其他標(biāo)簽的id屬性進(jìn)行綁定-->
          
          
          <input type="radio" name="sex" id="nan"> 
          <label for="nan">男</label>
          
          
          <input type="radio" name="sex"   id="nv">
          <label for="nv">女</label>
          
          
          <!--復(fù)選框 type="checkbox" 同一組的的復(fù)選框,name值應(yīng)該相同 ,復(fù)選框也有value值, 用于向服務(wù)器提交數(shù)據(jù)-->
          <input type="checkbox" name="hobby" value="soccer" > 足球
          <input type="checkbox" name="hobby" value="basket" > 籃球
          
          
          <!--密碼框-->
          <input type="password" placeholder="請(qǐng)輸入密碼">
          
          
          <!-- 下拉菜單 -->
          <select>
            <option value="alipay">支付寶</option>
            <option value="wxpay">微信支付</option>
          </select>
          
          
          <!--多文本框 rows 和  clos 分別用于設(shè)置 行數(shù) 和 列數(shù)-->
          <textarea rows="3" cols="5"></textarea>
          
          
          <!--三種按鈕 submit 提交按鈕  button 普通按鈕 可以簡(jiǎn)寫為  <button></button> reset 按鈕 重置按鈕-->
          <input type="button" value="普通按鈕">
              <input type="reset" value="重置按鈕"> 
              <input type="submit" value="提交表單">
          
          
          
          
          <!--像 email 和 url 等格式,如果點(diǎn)擊提交按鈕,不符合格式,會(huì)有提示-->
          <form>
              日期空間: <input type="date">  <br/>
              時(shí)間空間: <input type="time">  <br/>
              日期時(shí)間空間 <input type="datetime-local">  <br/>
          
          
              文件:<input type="file"> <br/>  <br/>
              數(shù)字控件: <input type="number"> <br/>
              拖拽條: <input type="range"> <br/>
              搜索框: <input type="search"> <br/>
              網(wǎng)址控件: <input type="url"> <br/>
              郵箱控件: <input type="email" >
              <input type="submit" value="提交">
          </form>
          
          
          
          
          <!-- datalist 備選項(xiàng)示例 -->
          <input type="text" list="province">
          <datalist id="province">
            <option value="陜西"></option>
            <option value="山西"></option>
            <option value="河北"></option>
            <option value="山東"></option>
          </datalist>


          表格

          可以用html渲染表格

          • table 標(biāo)簽表示表格
          • tr 表示行
          • td 表示單元格
          • caption 表格的標(biāo)題,通常放在表格的第一行
          • th 表示列標(biāo)題


          <!--表格示例-->
          <table border="1">
            <caption>我是標(biāo)題</caption>
            <tr>
                <th>第一列標(biāo)題</th>
                <th>第二列標(biāo)題</th>
            </tr>
            <tr>
                <td>第一行第一列</td>
                <td>第一行第二列</td>
            </tr>
            <tr>
                <td>第二行第一列</td>
                <td>第二行第二列</td>
            </tr>
          </table>


          • 單元格的合并, clospan 用來設(shè)置td 或者th的列跨度 , rowspan屬性用來設(shè)置td或者th的行跨度
          <!--跨列示例-->
          <table border="1">
              <caption>我是標(biāo)題</caption>
              <tr>
                  <th>第一列標(biāo)題</th>
                  <th>第二列標(biāo)題</th>
              </tr>
              <tr>
                  <td colspan="2">跨兩行</td>
              </tr>
              <tr>
                  <td>第二行第一列</td>
                  <td>第二行第二列</td>
              </tr>
          </table>
          
          
          <!--跨行示例-->
          <table border="1">
                  <caption>我是標(biāo)題</caption>
                  <tr>
                      <th>第一列標(biāo)題</th>
                      <th>第二列標(biāo)題</th>
                  </tr>
                  <tr>
                      <td rowspan="2">第一行第一列</td>
                      <td>第一行第二列</td>
                  </tr>
                  <tr>
                      <td>第二行第二列</td>
                  </tr>
                  <tr>
                      <td>第三行第一列</td>
                      <td>第三行第二列</td>
                  </tr>
            </table>


          • 表格的其他標(biāo)簽 , thead 定義表頭, tbody 定義表格的主題內(nèi)容, tfoot 標(biāo)簽定義表格底部,通常用來匯總等

          主站蜘蛛池模板: 国产精品视频一区国模私拍| 亚洲综合av一区二区三区| 无码毛片一区二区三区中文字幕 | 91香蕉福利一区二区三区| 美女免费视频一区二区三区| 亚洲日韩一区二区三区| 国产亚洲3p无码一区二区| 国产精品一区二区四区| 国模私拍福利一区二区| 免费一区二区三区| 久久精品国产亚洲一区二区三区| 在线视频一区二区三区四区| 99久久精品国产一区二区成人| 国产伦精品一区二区三区视频金莲| 成人精品一区二区电影| 在线观看一区二区三区av| 人妻夜夜爽天天爽爽一区| 岛国无码av不卡一区二区| 国产福利电影一区二区三区久久久久成人精品综合 | 亚洲精品无码一区二区| 日本欧洲视频一区| 精品久久国产一区二区三区香蕉 | 无码AⅤ精品一区二区三区| 在线播放精品一区二区啪视频| 国产经典一区二区三区蜜芽 | 丝袜人妻一区二区三区网站| 日韩一区二区三区在线精品| 精品国产天堂综合一区在线| 亚洲av色香蕉一区二区三区蜜桃| 精品亚洲A∨无码一区二区三区| 免费一区二区三区| 久久久久无码国产精品一区| 高清一区二区三区免费视频| 亚洲国产精品一区二区久久| 亚洲综合无码一区二区| 一区二区三区日韩精品| 精品人妻AV一区二区三区| 亚洲日韩一区精品射精| 国产精品盗摄一区二区在线| 北岛玲在线一区二区| 亚洲一区二区视频在线观看|