1. 程式人生 > 實用技巧 >【Flutter實戰】自定義滾動條

【Flutter實戰】自定義滾動條

老孟導讀:【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】: