119 lines
3.0 KiB
Dart
119 lines
3.0 KiB
Dart
![]() |
/// 自定义PageView分页指示器
|
||
|
library;
|
||
|
|
||
|
import 'package:flutter/material.dart';
|
||
|
|
||
|
class CustomPageViewIndicator extends StatefulWidget {
|
||
|
const CustomPageViewIndicator({
|
||
|
super.key,
|
||
|
required this.count,
|
||
|
required this.controller,
|
||
|
this.color = Colors.black12,
|
||
|
this.activeColor = Colors.black26,
|
||
|
this.pageSnapping = true,
|
||
|
});
|
||
|
|
||
|
/// 数量
|
||
|
final int count;
|
||
|
final PageController controller;
|
||
|
/// 颜色
|
||
|
final Color color;
|
||
|
/// 激活颜色
|
||
|
final Color activeColor;
|
||
|
// 是否停止滑动时吸附到最近页面
|
||
|
final bool pageSnapping;
|
||
|
|
||
|
@override
|
||
|
State<CustomPageViewIndicator> createState() => _CustomPageViewIndicatorState();
|
||
|
}
|
||
|
|
||
|
class _CustomPageViewIndicatorState extends State<CustomPageViewIndicator> {
|
||
|
int pageIndex = 0;
|
||
|
double page = 0;
|
||
|
|
||
|
// 圆点指示器
|
||
|
Widget dotIndicator() {
|
||
|
return Row(
|
||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||
|
children: List.generate(
|
||
|
widget.count,
|
||
|
(index) => Container(
|
||
|
margin: EdgeInsets.symmetric(horizontal: 3.0),
|
||
|
width: pageIndex == index ? 15.0 : 4.0,
|
||
|
height: 4.0,
|
||
|
decoration: BoxDecoration(
|
||
|
borderRadius: BorderRadius.circular(10.0),
|
||
|
color: pageIndex == index ? widget.activeColor : widget.color,
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
// 滚动槽指示器
|
||
|
Widget scrollIndicator() {
|
||
|
return Stack(
|
||
|
children: [
|
||
|
Container(
|
||
|
decoration: BoxDecoration(
|
||
|
color: widget.color,
|
||
|
borderRadius: BorderRadius.circular(50.0),
|
||
|
),
|
||
|
height: 4.0,
|
||
|
width: (widget.count - 1) * 15.0 + 15.0,
|
||
|
),
|
||
|
Container(
|
||
|
margin: EdgeInsets.only(left: page * 15.0),
|
||
|
decoration: BoxDecoration(
|
||
|
color: widget.activeColor,
|
||
|
borderRadius: BorderRadius.circular(50.0),
|
||
|
),
|
||
|
width: 15.0,
|
||
|
height: 4.0,
|
||
|
),
|
||
|
],
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return widget.count > 1 ?
|
||
|
widget.pageSnapping ? dotIndicator() : scrollIndicator()
|
||
|
:
|
||
|
SizedBox.shrink();
|
||
|
}
|
||
|
|
||
|
void _setInitialPage() {
|
||
|
pageIndex = widget.controller.initialPage;
|
||
|
page = pageIndex.toDouble();
|
||
|
}
|
||
|
|
||
|
void _onController() {
|
||
|
if (!widget.controller.hasClients) return;
|
||
|
page = widget.controller.page ?? 0.0;
|
||
|
pageIndex = page.round();
|
||
|
setState(() {});
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void initState() {
|
||
|
super.initState();
|
||
|
widget.controller.addListener(_onController);
|
||
|
_setInitialPage();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void didUpdateWidget(CustomPageViewIndicator oldWidget) {
|
||
|
super.didUpdateWidget(oldWidget);
|
||
|
if (widget.controller != oldWidget.controller) {
|
||
|
oldWidget.controller.removeListener(_onController);
|
||
|
widget.controller.addListener(_onController);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void dispose() {
|
||
|
widget.controller.removeListener(_onController);
|
||
|
super.dispose();
|
||
|
}
|
||
|
}
|