學習內容
以下是可滾動Widgets的部分彙總:
- SingleChildScrollView
- ListView
- GridView
- CustomScrollView
簡單使用
// SingleChildScrollView
class NewSingleChildScrollView extends StatelessWidget {
@override
Widget build(BuildContext context) {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return new Scaffold(
appBar: AppBar(title: Text('SingleChildScrollView學習')),
body: Scrollbar(
child: SingleChildScrollView(
padding: EdgeInsets.all(16.0),
child: Center(
child: Column(
// 動態建立一個 List<Widget>
children: str
.split('')
// 每個字母都用一個Text顯示,設定字型大小為原來的兩倍
.map((c) => Text(
c,
textScaleFactor: 2.0,
))
.toList(),
),
),
)),
);
}
}
// ListView 一個無限載入例項
class InfiniteListView extends StatefulWidget {
@override
_InfiniteListViewState createState() => new _InfiniteListViewState();
}
class _InfiniteListViewState extends State<InfiniteListView> {
static const loadingTag = "##loading##"; //表尾標記
var _words = <String>[loadingTag];
@override
void initState() {
_retrieveData();
}
void _retrieveData() {
Future.delayed(Duration(seconds: 2)).then((e) {
_words.insertAll(
_words.length - 1,
//每次生成20個單詞
generateWordPairs().take(20).map((e) => e.asPascalCase).toList());
setState(() {
//重新構建列表
});
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: Text("ListView學習")),
body: ListView.separated(
itemCount: _words.length,
itemBuilder: (context, index) {
//如果到了表尾
if (_words[index] == loadingTag) {
//不足100條,繼續獲取資料
if (_words.length - 1 < 100) {
//獲取資料
_retrieveData();
//載入時顯示loading
return Container(
padding: const EdgeInsets.all(16.0),
alignment: Alignment.center,
child: SizedBox(
width: 24.0,
height: 24.0,
child: CircularProgressIndicator(strokeWidth: 2.0)),
);
} else {
//已經載入了100條資料,不再獲取資料。
return Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16.0),
child: Text(
"沒有更多了",
style: TextStyle(color: Colors.grey),
));
}
}
//顯示單詞列表項
return ListTile(title: Text(_words[index]));
},
separatorBuilder: (context, index) => Divider(height: .0),
));
}
}
// 模擬非同步獲取資料並利用GirdView展示
class InfiniteGridView extends StatefulWidget {
@override
_InfiniteGridViewState createState() => new _InfiniteGridViewState();
}
class _InfiniteGridViewState extends State<InfiniteGridView> {
List<IconData> _icons = []; //儲存Icon資料
@override
void initState() {
// 初始化資料
_retrieveIcons();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: Text('GridView')),
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, //每行三列
childAspectRatio: 1.0 //顯示區域寬高相等
),
itemCount: _icons.length,
itemBuilder: (context, index) {
//如果顯示到最後一個並且Icon總數小於200時繼續獲取資料
if (index == _icons.length - 1 && _icons.length < 200) {
_retrieveIcons();
}
return Icon(_icons[index]);
}),
);
}
//模擬非同步獲取資料
void _retrieveIcons() {
Future.delayed(Duration(milliseconds: 200)).then((e) {
setState(() {
_icons.addAll([
Icons.ac_unit,
Icons.airport_shuttle,
Icons.all_inclusive,
Icons.beach_access,
Icons.cake,
Icons.free_breakfast
]);
});
});
}
}
class CustomScrollViewTestRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
//因為本路由沒有使用Scaffold,為了讓子級Widget(如Text)使用
//Material Design 預設的樣式風格,我們使用Material作為本路由的根。
return Material(
child: CustomScrollView(
slivers: <Widget>[
//AppBar,包含一個導航欄
SliverAppBar(
pinned: true,
expandedHeight: 250.0,
flexibleSpace: FlexibleSpaceBar(
title: const Text('Demo'),
background: Image.asset(
"./images/avatar.png",
fit: BoxFit.cover,
),
),
),
SliverPadding(
padding: const EdgeInsets.all(8.0),
sliver: new SliverGrid(
//Grid
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, //Grid按兩列顯示
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: new SliverChildBuilderDelegate(
(BuildContext context, int index) {
//建立子widget
return new Container(
alignment: Alignment.center,
color: Colors.cyan[100 * (index % 9)],
child: new Text('grid item $index'),
);
},
childCount: 20,
),
),
),
//List
new SliverFixedExtentList(
itemExtent: 50.0,
delegate: new SliverChildBuilderDelegate(
(BuildContext context, int index) {
//建立列表項
return new Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: new Text('list item $index'),
);
}, childCount: 50 //50個列表項
),
),
],
),
);
}
}
複製程式碼
部分效果:
Summary
走馬觀花式的學習並不能帶來高的學習效率,尤其是缺乏學習資料的技術,僅僅靠著一本書是不夠的,需要深入思考,結合文件,原始碼應該才是最佳學習實踐機會。