文章目錄
- Flutter 滾動控制元件
- SingleChildScrollView
- ListView
- 默認建構式
- ListView.builder
- ListView.separated
- ScrollController
- NotificationListener
Flutter 滾動控制元件
SingleChildScrollView
滾動組件,類似于Android中的ScrollView,只能接收一個子元素,
scrollDirection:滾動方向,
BouncingScrollPhysics:滾動到邊界效果,
- ClampingScrollPhysics:類似安卓效果,會有微光顯示,
- BouncingScrollPhysics:類似ios效果,會有回彈,

Scrollbar(
child: Container(
width: double.infinity,
child: SingleChildScrollView(
physics: BouncingScrollPhysics(),
padding: EdgeInsets.all(10),
child: Column(
children:
str.split("").map((e) => Text(e, textScaleFactor: 2)).toList(),
),
),
),
)
ListView
itemExtent:子組件長度,指定itemExtent后有利于提高性能,避免每次構建子組件時再次計算,
prototypeItem:串列項原型,指定子元素的Widget,有利于提供ListView性能,與itemExtent互斥,
shrinkWrap:是否根據子組件的總長度設定ListView的長度,默認為false,如果為false時,ListView會在主軸方向盡可能多占空間,
默認建構式
適合資料量比較小,
ListView(
shrinkWrap: true,
padding: EdgeInsets.all(20),
children: [
Text("A"),
Text("B"),
Text("C"),
Text("D"),
],
)
ListView.builder
適合資料量比較多或不確定的情況,
itemCount:子元素數量,如果為null,表示無限串列,
itemBuilder:設定子元素的Widget,
ListView.builder(
itemCount: null,
itemExtent: 50,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
}
)
ListView.separated
可以給ListView添加一個分割線,
Widget divider1 = Divider(color: Colors.red);
Widget divider2 = Divider(color: Colors.blue);
ListView.separated(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
},
separatorBuilder: (BuildContext context, int index) {
return index % 2 == 0 ? divider1 : divider2;
},
)
ScrollController
監聽滾動組件,
offset:滾動距離,
animateTo & jumpTo:滾動到指定位置,前者滾動時會執行影片,后者則不會,
addListener:監聽滾動組件,


class ListViewPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ListViewPageState();
}
}
class _ListViewPageState extends State<ListViewPage> {
final ScrollController _controller = ScrollController();
bool showTopBtn = false;
@override
void initState() {
super.initState();
_controller.addListener(() {
print("滾動距離:${_controller.offset}");
if (_controller.offset < 1000) {
if (showTopBtn) {
showTopBtn = false;
setState(() {});
}
} else {
if (!showTopBtn) {
showTopBtn = true;
setState(() {});
}
}
});
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ListView"),
actions: [],
),
body: ListView.builder(
itemCount: null,
itemExtent: 50,
physics: BouncingScrollPhysics(),
controller: _controller,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
}),
floatingActionButton: !showTopBtn
? null
: FloatingActionButton(
onPressed: () {
_controller.animateTo(
0,
duration: Duration(microseconds: 800),
curve: Curves.ease,
);
},
child: Icon(Icons.arrow_upward),
),
);
}
}
NotificationListener
可以監聽ListView、NestedScrollView、GridView的滾動監聽,
NotificationListener與ScrollController對比
- NotificationListener可以在任意位置監聽,并且攜帶的資訊更多,
- ScrollController只能和具體的滾動組件關聯后才能監聽,只能獲取當前滾動位置,
ScrollNotification類里包含一個metrics屬性,其型別是ScrollMetrics,包含一些資訊:
var extentBefore = notification.metrics.extentBefore; //已滑出ViewPort頂部的長度,已滾動距離
var extentInside = notification.metrics.extentInside; //ViewPort內部長度,表示螢屏顯示的串列部分的長度
var extentAfter = notification.metrics.extentAfter; //未劃入ViewPort部分的長度
var pixels = notification.metrics.pixels; //當前滾動距離
var maxScrollExtent = notification.metrics.maxScrollExtent; //最大可滾動距離

class NotificationListenerPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _NotificationListenerPageState();
}
}
class _NotificationListenerPageState extends State<NotificationListenerPage> {
String _progress = "0%";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("滾動監聽")),
body: Scrollbar(
child: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
double progress = notification.metrics.pixels /
notification.metrics.maxScrollExtent;
setState(() => _progress = "${(progress * 100).toInt()}%");
return false;
},
child: Stack(
alignment: Alignment.center,
children: [
ListView.builder(
itemCount: 100,
itemExtent: 50,
itemBuilder: (context, index) => ListTile(
title: Text("$index"),
),
),
CircleAvatar(
radius: 30,
child: Text(_progress),
backgroundColor: Colors.transparent.withAlpha(200),
),
],
),
),
),
);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/355357.html
標籤:其他
上一篇:appium原理常用指北
