我們今天來用DartPaf來練習
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Container(width: 100, height: 100, color: Colors.red)
);
}
}
我們能看Container
Container(
color: Colors.red
),
Conainer的父級裝置屏幕,強制將Container變成和屏幕一樣大小
接著我們定義Container的大小
Container(width: 100, height: 100, color: Colors.red)
我們能看到Container想要變成100x100大小,但由於父widget強制約束他,使Container變成和屏幕相同大小
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Center(
child: Container(width: 100, height: 100, color: Colors.red),
)
);
}
}
我們能看到螢幕強制Center與屏幕一樣大(嚴格約束),Center告訴Container可以變成任意大小,但不能超出屏幕(寬鬆約束)
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Center(
child: Container(width: double.infinity, height: 100, color: Colors.red),
)
);
}
}
我們試著讓Container的width變成無限大Container(width: double.infinity, height: 100, color: Colors.red)
我們能看到,寬鬆布局約束讓Container不超過父widget
我們接著用UnconstrainedBox來創建無邊界約束
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: UnconstrainedBox(
child: Container(color: Colors.red, width: 5000, height: 50),
)
);
}
}
UnconstrainedBox允許子級的Container可以變為任意大小。
由於是任意大小,我們這邊讓Container的寬度為5000像素。這遠遠超出超出我們的屏幕,以至於無法容納,所以UnconstrainedBox將顯示溢出警告(overflow warning)
UnconstrainedBox(
child: Container(color: Colors.red, width: 5000, height: 50),
)
接著我們把UnconstrainedBox加入一個父widget
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Center(
child: UnconstrainedBox(
child: Container(color: Colors.red, width: 5000, height: 50),
)
)
);
}
}
Center(
child: UnconstrainedBox(
child: Container(color: Colors.red, width: 5000, height: 50),
)
)
我們能看到出現溢出警告,但範圍不同
簡單的整理順序
1.裝置強制Center和裝置屏幕同樣大小,於是佔滿屏幕(嚴格布局約束)
2.Center允許UnconstrainedBox為不超過自己的任意大小(寬鬆布局約束)
3.UnconstrainedBox允許Container為任意大小(無邊界約束)
比較兩者溢出警告
Ex1的溢出警告是佔滿整個裝置屏幕,所以封鎖線是整個屏幕
Ex2的溢出警告則是超出我們Center,所以封鎖線是超出Center的範圍
接著我們使用OverflowBox
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: OverflowBox(
minWidth: 0.0,
minHeight: 0.0,
maxWidth: double.infinity,
maxHeight: double.infinity,
child: Container(color: Colors.red, width: 5000, height: 50),
)
);
}
}
OverflowBox(
minWidth: 0.0,
minHeight: 0.0,
maxWidth: double.infinity,
maxHeight: double.infinity,
child: Container(color: Colors.red, width: 5000, height: 50),
)
屏幕強制OverflowBox變得和屏幕一樣大,然後OverflowBox允許其子widget設置為任意大小
OverflowBox
與UnconstrainedBox
類似,但不同的是,如果其子級超出該空間,它將不會顯示任何警告。
也就是在這種情況下,容器的寬度為5000像素,並且太大而無法容納在 OverflowBox 中,但是OverflowBox會全部顯示,而不會發出警告。
使用FittedBox
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const FittedBox(
child: Text('Example Text Test !!'),
)
);
}
}
const FittedBox(
child: Text('Example Text Test !!'),
)
我們的FittedBox被強制和屏幕一樣大,並且Text則是有一個自然寬度(intrinsic width),它取決於文本數量,字體大小等因素。FittedBox讓Text可以變為任意大小。
但是在Text告訴FittedBox 其大小後,FittedBox 縮放text直到填滿所有可用寬度(被嚴格布局約束,強制FittedBox大小,導致Text被縮放)
接著我們在FittedBox的父widget使用Center
const Center(
child: FittedBox(
child: Text('Example Text Test !!'),
),
)
這裡Center將會讓FittedBox能夠變為不超過自己的任意大小。
FittedBox然後會根據Text調整自己的大小,然後讓 Text 可以變為所需的任意大小,由於二者俱有同一大小,因此不會發生縮放。(沒有被嚴格布局約束)
修改Text文本來測試單Text太大超出範圍會發生甚麼
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const Center(
child: FittedBox(
child: Text(
'Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!'),
),
)
);
}
}
我們知道FittedBox會嘗試根據Text大小調整大小,但不能大於widget的大小範圍。所以調整Text的大小以使其不超過屏幕
去掉FittedBox
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const Center(
child: Text(
'Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!'),
)
);
}
}
能看到Text則會從屏幕上獲取其最大寬度,並在合適的地方換行
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Row(
children: [
Container(
color: Colors.red,
child: const Text(
'Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!',
),
),
Container(color: Colors.blue, child: const Text('Hello Test!')),
],
)
);
}
}
Row(
children: [
Container(
color: Colors.red,
child: const Text(
'Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!',
),
),
Container(color: Colors.blue, child: const Text('Hello Test!')),
],
)
Row
不會對其子級施加任何約束(無邊界約束),因此它的children有可能超出Row的可用寬度。當超出時,Row會和UnconstrainedBox一樣顯示溢出警告(Column亦同)
Exapanded
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Row(
children: [
Expanded(
child: Container(
color: Colors.red,
child: const Text(
'Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!',
),
),
),
Container(color: Colors.blue, child: const Text('Hello Test!')),
],
)
);
}
}
也就是
Row(
children: [
Expanded(
child: Container(
color: Colors.red,
child: const Text(
'Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!',
),
),
),
Container(color: Colors.blue, child: const Text('Hello Test!')),
],
)
當Row的子widget被包在了Expanded
widget後,Row 會根據所有 Expanded 的子級來計算其該有的寬度。 使用Expanded,子widget自身的寬度就變得無關緊要,直接會被忽略掉
Flexible
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Row(
children: [
Flexible(
child: Container(
color: Colors.red,
child: const Text(
'Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!Example Text Test !!',
),
),
),
Container(color: Colors.blue, child: const Text('Hello Test!')),
],
)
);
}
}
使用Flexible
而不是Expanded
的唯一的區別是
但無論是Expanded還是Flexible在它們決定子級大小時都會忽略其寬度。
今天簡單的介紹一些常見會出現的例子,我們明天見