在〈捲動單一元件 SingleChildScrollView〉中第二個範例,也可以使用 ListView
如下撰寫:
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Openhome.cc')),
body: Body(),
)
)
);
class Body extends StatefulWidget {
@override
State<StatefulWidget> createState() => _Body();
}
class _Body extends State<Body> {
final scrollController = ScrollController();
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
var children = List<Widget>();
for(var i = 0; i < 20; i++) {
children.add(RawMaterialButton(
child: Text('$i'),
onPressed: () {
print(scrollController.offset);
},
fillColor: Colors.lightGreen,
splashColor: Colors.red,
));
}
return Center(
child: Container(
height: 50,
child: ListView( // 使用 ListView
controller: scrollController,
scrollDirection: Axis.horizontal,
children: children,
),
),
);
}
}
這樣就能獲得延遲載入的效果了嗎?並不會!畢竟你還是在 build
時,建立了 ListView
全部的子元件,以上的使用方式,跟使用 SingleChildScrollView
時,其實沒有什麼差別。
如果想要有延遲載入的效果,可以透過 ListView.builder
建構式,指定 itemBuilder
來定義捲動時元件的生成方式。例如:
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Openhome.cc')),
body: ListView.builder(
itemCount: 50,
itemBuilder: (BuildContext context, int i) {
print(i);
return ListTile(
title: RawMaterialButton(
child: Text('$i'),
fillColor: Colors.lightGreen,
)
);
}
),
)
)
);
操作時的效果如下,可以看到一開始先建立了索引 0 到 10,接著依捲動按需地建立元件,由於 itemCount
指定為 50,因此最多只會到索引 49,如果 itemCount
指定為 null
,表示元件長度不受限:
如果要自訂分隔元件,可以透過 ListView.separated
建構式,指定 separatorBuilder
來定義分隔元件:
import 'package:flutter/material.dart';
void main() {
Widget blueDivider = Divider(
thickness: 4,
color: Colors.blue
);
Widget redDivider = Divider(
thickness: 4,
color: Colors.green
);
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Openhome.cc')),
body: ListView.separated(
itemCount: 50,
itemBuilder: (BuildContext context, int i) {
return ListTile(
title: RawMaterialButton(
child: Text('$i'),
)
);
},
separatorBuilder: (BuildContext context, int i) {
return i % 2 == 0 ? blueDivider : redDivider;
}
),
)
)
);
}
執行後的效果如下:
話說範例中使用了 ListTile
,這是做列表時還蠻常用的小元件,可以設定圖示、子標題等內容,例如:
import 'package:flutter/material.dart';
void main() {
Widget blueDivider = Divider(
thickness: 4,
color: Colors.blue
);
Widget redDivider = Divider(
thickness: 4,
color: Colors.green
);
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Openhome.cc')),
body: ListView.separated(
itemCount: 30,
itemBuilder: (BuildContext context, int i) {
return ListTile(
leading: Icon(
IconData(59677 + i, fontFamily: 'MaterialIcons')
),
title: Text('$i'),
subtitle: Text('圖示 ${59677 + i}'),
);
},
separatorBuilder: (BuildContext context, int i) {
return i % 2 == 0 ? blueDivider : redDivider;
}
),
)
)
);
}
執行後的效果如下: