老孟導讀:【Flutter實戰】系列文章地址:http://laomengit.com/guide/introduction/mobile_system.html 預設情況下,Flutter 的滾動組件(比如 ListView)沒有顯示滾動條,使用 Scrollbar 顯示滾動條: Scrollba ...
老孟導讀:【Flutter實戰】系列文章地址:http://laomengit.com/guide/introduction/mobile_system.html
預設情況下,Flutter 的滾動組件(比如 ListView)沒有顯示滾動條,使用 Scrollbar 顯示滾動條:
Scrollbar(
child: ListView.builder(
reverse: false,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Container(
height: 45,
alignment: Alignment.center,
child: Text('$index'),
),
);
},
itemCount: 30,
itemExtent: 50,
),
)
在滑動的過程中,右側顯示滾動條,然而 Scrollbar 無法實現自定義滾動條的樣式,比如實現如下滾動條樣式,
這時需要自定義一個滾動條組件。
實現自定義滾動條組件首先需要監聽滾動組件 滾動的位置,使用 NotificationListener 監聽滾動的位置:
bool _handleScrollNotification(ScrollNotification notification) {
final ScrollMetrics metrics = notification.metrics;
print('滾動組件最大滾動距離:${metrics.maxScrollExtent}');
print('當前滾動位置:${metrics.pixels}');
return true;
}
@override
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotification,
child: ListView.builder(
reverse: false,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Container(
height: 45,
alignment: Alignment.center,
child: Text('$index'),
),
);
},
itemCount: 30,
itemExtent: 50,
),
);
}
通過 ScrollNotification 獲取當前滾動組件最大滾動距離和當前滾動位置,其中 metrics.maxScrollExtent 表示當前滾動組件最大滾動距離,metrics.pixels 表示當前滾動位置。
通過這兩個值計算滾動條在當前屏幕的位置,通過 Stack 組件 將 ListView 和 自定義的滾動條進行疊加顯示:
NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotification,
child: Stack(
alignment: Alignment.topRight,
children: <Widget>[
ListView.builder(
reverse: false,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Container(
height: 45,
alignment: Alignment.center,
child: Text('$index'),
),
);
},
itemCount: 30,
itemExtent: 50,
),
//滾動條
Container(
height: 100,
width: 20,
color: Colors.red,
)
],
),
)
將此滾動條和 NotificationListener 監聽到的滾動事件聯動,通過 Container 的 alignment 屬性控制滾動條的位置:
Container(
alignment: Alignment(1, _alignmentY),
padding: EdgeInsets.only(right: 5),
child: Container(
height: 100,
width: 20,
color: Colors.red,
),
)
_alignmentY 就是計算出的偏移位置,計算方法如下:
_alignmentY = -1 + (metrics.pixels / metrics.maxScrollExtent) * 2;
這裡要註意 alignment 的坐標系:
最終效果:
然後只需修改滾動條的樣式即可:
class _ScrollBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 18,
height: 60,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.blue),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.arrow_drop_up,
size: 18,
),
Icon(
Icons.arrow_drop_down,
size: 18,
),
],
),
);
}
}
最後將代碼封裝,就可以給所有的滾動組件添加自定義的滾動條,而不僅僅是 ListView。
交流
老孟Flutter博客地址(330個控制項用法):http://laomengit.com
歡迎加入Flutter交流群(微信:laomengit)、關註公眾號【老孟Flutter】: