flutter/lib/components/custom_pageview_indicator.dart
2025-07-21 15:46:30 +08:00

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();
}
}