從0開始學Flutter

第三部分:Flutter佈局

  Flutter開發中,佈局比較另類一點,由於邏輯代碼和佈局代碼都寫在一塊兒了,都是使用Dart來寫。數組

  Flutter中的佈局容器主要分爲兩類:只能包含一個子Widget的佈局容器和能夠包含多個子Widget的容器bash

一:包含單個子Widget的佈局容器

Center組件

Center組件中的子組件會居中顯示。Center組件會盡量的大,若是你不給它設置任何約束。下面是Center組件的使用方法:app

import 'package:flutter/material.dart'; main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Center( child: new Text("hello world") ), ), ); } }

Container組件

Container是使用很是多的一個佈局容器,關於Container容器的顯示規則,有以下幾條:less

  1. 若是Container中沒有子組件,則Container會盡量的大
  2. 若是Container中有子組件,則Container會適應子組件的大小
  3. 若是給Container設置了大小,則Container按照設置的大小顯示
  4. Container的顯示規則除了跟自身約束和子組件有關,跟它的父組件也有關

下面的代碼展現了Container的用法:ide

import 'package:flutter/material.dart'; main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Container( width: 100.0, height: 100.0, color: Colors.red, child: new Text("Flutter!"), ) ), ); } }

Container還能夠設置內邊距和外邊距,以下代碼所示:佈局

body: new Container(
  // 設置外邊距都爲20.0
  margin: const EdgeInsets.all(20.0),
  // 設置內邊距,4個邊分別設置
  padding: const EdgeInsets.fromLTRB(10.0, 20.0, 30.0, 40.0),
  width: 100.0,
  height: 100.0,
  color: Colors.red,
  child: new Text("Flutter!"), )

Padding組件

Padding組件專門用於給它的子組件設置內邊距,用法比較簡單:ui

new Padding(
  padding: new EdgeInsets.all(8.0),
  child: const Card(child: const Text('Hello World!')), )

Align組件

Align組件用於將它的子組件放置到肯定的位置,好比下面的代碼展現了將Text組件放置到100*100的容器的右下角:spa

new Container(
  width: 100.0,
  height: 100.0,
  color: Colors.red,
  child: new Align(
    child: new Text("hello"), alignment: Alignment.bottomRight, ), )

FittedBox組件

FittedBox組件根據fit屬性來肯定子組件的位置,fit屬性是一個BoxFit類型的值,BoxFit是個枚舉類,取值有以下幾種:code

enum BoxFit {
  fill,
  contain,
  cover,
  fitWidth,
  fitHeight,
  none,
  scaleDown,
}

在大小爲200*100的Container中放置一個Text,使用FittedBox來控制Text的不一樣顯示狀態:orm

new Container(
  width: 200.0,
  height: 100.0,
  color: Colors.red,
  child: new FittedBox(
    child: new Text("hello world"), fit: BoxFit.fill, ) )

AspectRatio組件

AspectRatio組件用於讓它的子組件按必定的比例顯示,下面是示例代碼:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new AspectRatio( // Container組件按16:9(width / height)顯示 aspectRatio: 16.0 / 9.0, child: new Container( color: Colors.red, ), ) ), ); } }

若是將aspectRatio設置爲1.0,則Container顯示爲正方形。(注意,Dart中/表明除法運算,不是取整運算,使用~/作取整運算)

ConstrainedBox組件

ConstrainedBox組件用於給它的子組件強制加上一些約束,好比下面的代碼:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new ConstrainedBox( constraints: const BoxConstraints.expand(width: 50.0, height: 50.0), child: new Container( color: Colors.red, width: 200.0, height: 200.0, ) ) ), ); } }

IntrinsicWidth & IntrinsicHeight

這兩個組件的做用是將他們的子組件調整到組件自己的寬度/高度。

這個類是很是有用的,例如,當寬度/高度沒有任何限制時,你會但願子組件按更合理的寬度/高度顯示而不是無限的擴展。

LimitedBox組件

LimitedBox是一個當其自身不受約束時才限制其大小的容器。

若是這個組件的最大寬度是沒有約束,那麼它的寬度就限制在maxWidth。相似地,若是這個組件的最大高度沒有約束,那麼它的高度就限制在maxHeight

Offstage組件

Offstage組件用於顯示或隱藏它的子組件,以下代碼所示:

new Offstage(
  offstage: false, // true: 隱藏, false: 顯示 child: new Text("hello world"), )

OverflowBox & SizedOverflowBox

OverflowBox組件它給它的子組件帶來不一樣的約束,而不是從它的父組件中獲得,可能容許子組件溢出到父組件中。

SizedOverflowBox組件是一個指定大小的組件,它的約束會傳遞給子組件,子組件可能溢出。

SizedBox組件

SizedBox是一個指定了大小的容器。

若是指定了SizedBox的大小,則子組件會使用SizedBox的大小,若是沒有指定SizedBox的大小,則SizedBox會使用子組件的大小。若是SizedBox沒有子組件,SizedBox會按它本身的大小來顯示,將nulls看成0。

new SizedBox(
  // 若是指定width和height,則Container按照指定的大小顯示,而不是Container本身的大小,若是沒有指定width和height,則SizedBox按照Container的大小顯示
  width: 50.0,
  height: 50.0,
  child: new Container(
    color: Colors.red,
    width: 300.0,
    height: 300.0,
  ),
)

Transform組件

Transform用於在繪製子組件前對子組件進行某些變換操做,好比平移、旋轉、縮放等。

示例代碼以下:

new Container(
  color: Colors.black,
  child: new Transform(
    alignment: Alignment.topRight,
    // 須要導包:import 'dart:math' as math; transform: new Matrix4.skewY(0.3)..rotateZ(-math.pi / 12.0), child: new Container( padding: const EdgeInsets.all(8.0), color: const Color(0xFFE8581C), child: const Text('Apartment for rent!'), ), ), )

2、包含多個子Widget的佈局容器

Row組件

Row組件字面理解就是表明一行,在一行中能夠放入多個子組件。

下面是示例代碼:

import 'package:flutter/material.dart'; main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ new Text("hello"), new Container( width: 50.0, height: 50.0, color: Colors.red, ), new Text("world") ], ) ), ); } }

Row組件的構造方法中,children參數是一個數組,表示能夠有多個子組件,mainAxisAlignment表示Row中的子組件在主軸(Row組件主軸表示水平方向,交叉軸表示垂直方向,Column組件主軸表示垂直方向,交叉軸表示水平方向)上的對齊方式,能夠有以下幾個取值:

Column組件

Column組件表示一列,能夠在一列中放入多個組件,以下代碼所示:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Column( children: <Widget>[ new Text("hello"), new Text("world"), new Text("nihao~") ], ) ), ); } }

Column和Row組件同樣,能夠經過MainAxisAlignment或者CrossAxisAlignment來設置主軸和交叉軸的對齊方式,這裏再也不贅述。

Stack組件

Stack組件相似於Android中的FrameLayout,其中的子組件是一層層堆起來的,並不像Row或者Column中的子組件,按水平或垂直方向排列,下面用代碼說明:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Stack( children: <Widget>[ new Container( width: 100.0, height: 100.0, color: Colors.red, ), new Container( width: 30.0, height: 30.0, color: Colors.green, ) ], ) ), ); } }

IndexedStack組件

IndexedStack用於根據索引來顯示子組件,index爲0則顯示第一個子組件,index爲1則顯示第二個子組件,以此類推,下面用代碼說明:

new IndexedStack(
  index: 1,
  children: <Widget>[
    new Container(
      width: 100.0,
      height: 100.0,
      color: Colors.red,
      child: new Center(
        child: new Text("index: 0", style: new TextStyle(fontSize: 20.0),), ), ), new Container( width: 100.0, height: 100.0, color: Colors.green, child: new Center( child: new Text("index: 1", style: new TextStyle(fontSize: 20.0),), ), ) ], )

IndexedStack的構造方法中有個index屬性,上面的index屬性爲1,則顯示的是children數組中的第2個元素(綠色方塊),

若是index改成0,則顯示的是第1個元素(紅色方塊),若是index的大小超過了children數組的長度,則會報錯。

Table組件

Table組件用於顯示多行多列的佈局,若是隻有一行或者一列,使用Row或者Column更高效。下面用一段代碼展現Table的用法:

class MyApp extends StatelessWidget {

  // 生成Table中的數據
  List<TableRow> getData() { var data = [ "hello", "world" ]; List<TableRow> result = new List<TableRow>(); TextStyle style = new TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold); for (int i = 0; i < data.length; i++) { String str = data[i]; List<Widget> row = new List(); for (int j = 0; j < str.length; j++) { row.add(new Text(" ${str[j]} ", style: style)); } result.add(new TableRow( children: row )); } return result; } @override Widget build(BuildContext context) { return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Table( children: getData() ) ), ); } }

Wrap組件

Wrap組件能夠在水平或垂直方向上多行顯示其子組件,下面是示例代碼:

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Wrap( spacing: 5.0, // 水平方向上兩個子組件的間距 runSpacing: 20.0, // 兩行的垂直間距 children: <Widget>[ new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), ], ) ), ); } }

若是你把上面代碼中的Wrap換成Row,你會發現Row中的子組件超過屏幕寬度後,不會自動換行顯示。

ListView組件

ListView是一個很是經常使用的組件。

相關文章
相關標籤/搜索