flutter 常用widget及其使用

簡單列舉總結(jié)一下常用的布局widget钻注。
Flutter有豐富的layout組件庫。其中有一些是常用庫配猫。
下面的widget分為兩類:標準組件和來自Material Components的特殊組件幅恋。
只有Material App能夠使用Material Components的組件。

標準組件 - Standard widgets

  • Container
    • 給一個組件添加 padding, margins, 邊界(borders), 背景顏色或其它裝飾(decorations)泵肄。
  • GridView
    • 將多個widget放在一個可滑動的表格中捆交。
  • ListView
    • 將多個widget放在一個可滑動的列表中。
  • Stack
    • 在一個widget上面蓋上另一個widget腐巢。

Material Components

  • Card
    • 將一些相近的信息裝進一個有圓角和陰影的盒子里冯勉。
  • ListTile
    • 一個Row中裝載最多3行文字饿这;可選則在前面或尾部添加圖標衡载。

Container

Container用法比較自由贞绵”睿可以把整個layout放進container里面绊袋,然后改變背景顏色或圖片努隙。

Container 小結(jié):

  • 添加 padding, margins, 和邊界(borders)
  • 能夠更好背景顏色和圖片
  • 包含一個單獨的子widget腐碱,這個子widget可以是Row洁墙、Column或一個widget樹的根widget
image

測試代碼widgetdemo/container_page.dart

import 'package:flutter/material.dart';
import 'package:demo_flutter/widgetdemo/container_page.dart';
// 引入自定義的包......

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Container demo 1',
      theme: new ThemeData(primarySwatch: Colors.brown),
      home: new ContainerDemoPage(), // 這里換上想要測試的界面
    );
  }
}

widgetdemo/container_page.dart代碼

import 'package:flutter/material.dart';

/// container示例界面
class ContainerDemoPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _ContainerDemoPageState();
}

class _ContainerDemoPageState extends State<ContainerDemoPage> {
  @override
  Widget build(BuildContext context) {
    Expanded imageExpanded(String img) {
      return new Expanded(child: new Container(
        decoration: new BoxDecoration(
            border: new Border.all(width: 10.0, color: Colors.black38),
            borderRadius: const BorderRadius.all(
                const Radius.circular(8.0))),
        margin: const EdgeInsets.all(4.0),
        child: new Image.asset(img),
      ));
    }

    var container = new Container(
      decoration: new BoxDecoration(color: Colors.black26),
      child: new Column(
        children: <Widget>[
          new Row(children: <Widget>[
            imageExpanded('images/c1.jpg'),
            imageExpanded('images/c2.jpg'),
          ],),
          new Row(children: <Widget>[
            imageExpanded('images/d1.jpg'),
            imageExpanded('images/d2.jpg'),
          ],),
          new Row(children: <Widget>[
            imageExpanded('images/p1.jpg'),
          ],)
        ],
      ),
    );

    return new Scaffold(
      appBar: new AppBar(title: new Text('Container Page demo'),),
      body: new Center(
        child: container,
      ),
    );
  }
}

image

GridView

用GridView來將widget放入一個2維的列表中蛹疯。
GridView提供了2個預裝配好的列表,也可以自己建立自定義列表热监。
GridView支持滾動捺弦。

GridView 小結(jié):

  • 將多個widget放進一個表格中
  • 當超出渲染范圍時,自動提供滾動功能
  • 可自定義格子孝扛,也可用下面提供的2種
    • GridView.count 指定列的數(shù)目
    • GridView.extent 允許指定子項的最大像素寬度

示例1 - 用GridView.extent

GridView.extent指定子項占據(jù)的最大寬度

import 'package:flutter/material.dart';

/// gridView示例界面1
class GridDemo1Page extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _GridDemo1PageState();
}

class _GridDemo1PageState extends State<GridDemo1Page> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text('Grid Page 1 demo'),),
      body: new Center(
        child: buildGrid(),
      ),
    );
  }

  List<Container> _buildGridTileList(int count) {
    return new List<Container>.generate(count, (int index) =>
    new Container(child: new Image.asset('images/pic${index + 1}.jpg'),));
  }

  Widget buildGrid() {
    return new GridView.extent(
      maxCrossAxisExtent: 150.0,
      padding: const EdgeInsets.all(4.0),
      mainAxisSpacing: 4.0,
      crossAxisSpacing: 4.0,
      children: _buildGridTileList(30),);
  }
}

image

示例2 - 用GridView.count

crossAxisCount設(shè)為2列吼,分成2列。

  Widget buildGrid() {
    var countGrid = GridView.count(
      crossAxisCount: 2,
      mainAxisSpacing: 4.0,
      crossAxisSpacing: 4.0,
      padding: const EdgeInsets.all(4.0),
      childAspectRatio: 1.3,
      children: _buildGridTileList(30),
    );
    return countGrid;
  }

image

ListView

ListView能以列的形式展示數(shù)據(jù)苦始。當內(nèi)容超過渲染范圍時寞钥,自動提供滾動的功能。

ListView 小結(jié)

  • 把子視圖裝進列表中
  • 水平或豎直都可以
  • 支持滑動
  • 相比于Column陌选,可選配置比較少理郑,但更易用并且支持滑動

和Android中的ListView差別不大

示例1

ListTile當做子項來裝載數(shù)據(jù)蹄溉。

import 'package:flutter/material.dart';

class ListViewPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _ListViewPageState();
}

class _ListViewPageState extends State<ListViewPage> {

  @override
  Widget build(BuildContext context) {
    List<Widget> list = <Widget>[];
    for (int i = 0; i < 30; i++) {
      list.add(new ListTile(
        title: new Text('title$i', style: _itemTextStyle,),
        subtitle: new Text('A'),
        leading: i % 3 == 0
            ? new Icon(Icons.theaters, color: Colors.blue,)
            : new Icon(Icons.restaurant, color: Colors.blue,),
      ));
    }
    return new Scaffold(
      appBar: new AppBar(title: new Text('ListView Demo'),),
      body: new Center(child: new ListView(children: list,),),
    );
  }
}

TextStyle _itemTextStyle = new TextStyle(
    fontWeight: FontWeight.w500, fontSize: 14.0);

image

另外可以參考 https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/colors_demo.dart

Stack

使用Stack在widget之上顯示另一些widget,通常用來顯示圖片您炉。
顯示的widget可以完全地把底部widget蓋住柒爵。

Stack 小結(jié):

  • 用來在當前widget上面再蓋上一層widget
  • Stack children中的第一個widget放在最下,后面的widget會一層層蓋上去
  • Stack的內(nèi)容不支持滾動
  • 可以裁剪超出范圍的子widget

Stack示例1

顯示一個CircleAvatar

import 'package:flutter/material.dart';

class StackPage1 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _StackPage1State();
}

class _StackPage1State extends State<StackPage1> {

  @override
  Widget build(BuildContext context) {
    var stack = new Stack(
      alignment: const Alignment(0.6, 0.6),
      children: <Widget>[
        new CircleAvatar(
          backgroundImage: new AssetImage('images/android_1.jpg'),
          radius: 100.0,),
        new Container(decoration: new BoxDecoration(color: Colors.black45),
          child: new Text(
            'Android Avatar', style: new TextStyle(color: Colors.white70),),),
        new Container(decoration: new BoxDecoration(color: Colors.transparent),
          padding: const EdgeInsets.fromLTRB(0.0, 0.0, 100.0, 0.0),
          child: new CircleAvatar(
            backgroundImage: new AssetImage('images/p_box1.png'),
            backgroundColor: Colors.transparent,
            radius: 10.0,),),
      ],
    );
    return new Scaffold(
      appBar: new AppBar(title: new Text('Stack Demo 1'),),
      body: new Center(child: stack,),
    );
  }
}

image

Card

Card來自Material組件庫赚爵,可包含一些數(shù)據(jù)棉胀,通常用ListTile來組裝。Card只有一個子widget冀膝,可以是column唁奢、row、list窝剖、grid或其它組合widget驮瞧。
默認情況下,Card把自己的尺寸縮小為0像素枯芬÷郾剩可以用SizedBox來指定card的尺寸。

Flutter中的Card有圓角和陰影效果千所。修改elevation可改變陰影效果狂魔。

elevation取值范圍,參考 Elevation and Shadows

若設(shè)置的范圍外的值淫痰,陰影效果會消失最楷。

Card 小結(jié):

  • 實現(xiàn)了Material Design card
  • 用于展示相關(guān)的數(shù)據(jù)
  • 有一個子項(child),可以是column待错、row籽孙、list、grid或其它組合widget
  • 有圓角和陰影效果
  • 不支持滾動

Card示例1

將前面的ListView示例修改一下

import 'package:flutter/material.dart';

class ListViewPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _ListViewPageState();
}

class _ListViewPageState extends State<ListViewPage> {

  @override
  Widget build(BuildContext context) {
    List<Widget> list = <Widget>[];
    for (int i = 0; i < 30; i++) {
      list.add(new Card(child: new Column(
        children: <Widget>[
          new Image.asset(
            'images/pic${i + 1}.jpg',),
          new ListTile(
            title: new Text('title$i', style: _itemTextStyle,),
            subtitle: new Text('A'),
            leading: i % 3 == 0
                ? new Icon(Icons.theaters, color: Colors.blue,)
                : new Icon(Icons.restaurant, color: Colors.blue,),
          ),
        ],
      ),));
    }
    return new Scaffold(
      appBar: new AppBar(title: new Text('ListView Demo'),),
      body: new Center(child: new ListView(children: list,),),
    );
  }
}

TextStyle _itemTextStyle = new TextStyle(
    fontWeight: FontWeight.w500, fontSize: 14.0);

image

ListTile

來自Material組件庫的橫向組件火俄》附ǎ可自定義3行文字及其可選的頭尾圖標。
此控件常與Card或ListView一起用瓜客。

ListTile 小結(jié):

  • 可定制3行帶圖標的文字
  • 相比于Row适瓦,配置更少,但更易用

加一個主界面

放置一些按鈕谱仪,點擊跳轉(zhuǎn)到相應(yīng)的界面玻熙。
使用Navigator.of(context).pushNamed(routeName)來跳轉(zhuǎn)。

import 'package:flutter/material.dart';
import 'package:demo_flutter/widgetdemo/container_page.dart';
import 'package:demo_flutter/widgetdemo/grid_page.dart';
import 'package:demo_flutter/widgetdemo/listview_demo.dart';
import 'package:demo_flutter/widgetdemo/stack_page1.dart';
import 'package:demo_flutter/widgetdemo/button_page.dart';

const String CONTAINER_DEMO_PAGE = '/a';

void main() {
  runApp(new MaterialApp(
    home: new HomePage(),
    routes: {
      CONTAINER_DEMO_PAGE: (BuildContext context) => new ContainerDemoPage(),
      '/b': (BuildContext context) => new GridDemo1Page(),
      '/c': (BuildContext context) => new ListViewPage(),
      '/d': (BuildContext context) => new StackPage1(),
      '/e': (BuildContext context) => new ButtonPage(),
    },
  ));
}

class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {

  @override
  Widget build(BuildContext context) {
    getGestureDetector(String routeName, String content) {
      return new GestureDetector (
        onTap: () {
          Navigator.of(context).pushNamed(routeName);
        },
        child: new Container (
            padding: EdgeInsets.all(20.0),
            child: new Center(child: new Text (content),)),
      );
    }
    return new Scaffold(
      appBar: new AppBar(title: new Text('Home'),),
      body: new Column(children: <Widget>[
        getGestureDetector(CONTAINER_DEMO_PAGE, 'Container Demo'),
        getGestureDetector('/b', 'Grid Demo 1'),
        getGestureDetector('/c', 'ListView Demo'),
        getGestureDetector('/d', 'Stack Demo'),
        getGestureDetector('/e', 'Button Page'),
      ],),
    );
  }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疯攒,一起剝皮案震驚了整個濱河市嗦随,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敬尺,老刑警劉巖枚尼,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肌毅,死亡現(xiàn)場離奇詭異,居然都是意外死亡姑原,警方通過查閱死者的電腦和手機悬而,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锭汛,“玉大人笨奠,你說我怎么就攤上這事』脚梗” “怎么了般婆?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長朵逝。 經(jīng)常有香客問我蔚袍,道長,這世上最難降的妖魔是什么配名? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任啤咽,我火速辦了婚禮,結(jié)果婚禮上渠脉,老公的妹妹穿的比我還像新娘宇整。我一直安慰自己,他們只是感情好芋膘,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布鳞青。 她就那樣靜靜地躺著,像睡著了一般为朋。 火紅的嫁衣襯著肌膚如雪臂拓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天习寸,我揣著相機與錄音胶惰,去河邊找鬼。 笑死融涣,一個胖子當著我的面吹牛童番,可吹牛的內(nèi)容都是我干的精钮。 我是一名探鬼主播威鹿,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼轨香!你這毒婦竟也來了忽你?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤臂容,失蹤者是張志新(化名)和其女友劉穎科雳,沒想到半個月后根蟹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡糟秘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年简逮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尿赚。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡散庶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凌净,到底是詐尸還是另有隱情悲龟,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布冰寻,位于F島的核電站须教,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏斩芭。R本人自食惡果不足惜轻腺,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望划乖。 院中可真熱鬧约计,春花似錦、人聲如沸迁筛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽细卧。三九已至尉桩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贪庙,已是汗流浹背蜘犁。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留止邮,地道東北人这橙。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像导披,于是被迫代替她去往敵國和親屈扎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 簡單列舉總結(jié)一下常用的布局widget撩匕。Flutter有豐富的layout組件庫鹰晨。其中有一些是常用庫。下面的wid...
    AnRFDev閱讀 10,778評論 6 22
  • 國慶后面兩天在家學習整理了一波flutter,基本把能擼過能看到的代碼都過了一遍模蜡,此文篇幅較長漠趁,建議保存(star...
    Nealyang閱讀 4,338評論 1 17
  • 前言 本文的目的是為了讓讀者掌握不同布局類Widget的布局特點,分享一些在實際使用過程遇到的一些問題忍疾,在《Flu...
    xqqlv閱讀 5,245評論 0 18
  • 本文對Flutter的29種布局控件進行了總結(jié)分類闯传,講解一些布局上的優(yōu)化策略,以及面對具體的布局時卤妒,如何去選擇控件...
    Q吹個大氣球Q閱讀 10,537評論 15 153
  • 下雨丸边。 風吹起來的時候很冷。 已經(jīng)是春天了的荚孵,油菜花在田間開滿妹窖。 這是第二次來到他們家里,和之前有什么不同呢收叶。沒有...
    深海垃圾場閱讀 123評論 0 0