custom_banner.dart 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. /// Description: custom banner
  4. /// Time : 07/17/2023 Monday
  5. /// Author : liuyuqi.gov@msn.cn
  6. class CustomBanner extends StatefulWidget {
  7. final List<String> _images;
  8. final double height;
  9. final ValueChanged<int> onTap;
  10. final Curve curve;
  11. const CustomBanner(
  12. this._images, {
  13. super.key,
  14. this.height = 200,
  15. required this.onTap,
  16. this.curve = Curves.linear,
  17. });
  18. @override
  19. _CustomBannerState createState() => _CustomBannerState();
  20. }
  21. class _CustomBannerState extends State<CustomBanner> {
  22. late PageController _pageController;
  23. late int _curIndex;
  24. late Timer _timer;
  25. @override
  26. void initState() {
  27. super.initState();
  28. _curIndex = widget._images.length * 5;
  29. _pageController = PageController(initialPage: _curIndex);
  30. _initTimer();
  31. }
  32. @override
  33. Widget build(BuildContext context) {
  34. return Stack(
  35. alignment: Alignment.bottomCenter,
  36. children: [
  37. _buildPageView(),
  38. _buildIndicator(),
  39. ],
  40. );
  41. }
  42. Widget _buildIndicator() {
  43. var length = widget._images.length;
  44. return Positioned(
  45. bottom: 10,
  46. child: Row(
  47. children: widget._images.map((s) {
  48. return Padding(
  49. padding: const EdgeInsets.symmetric(horizontal: 3.0),
  50. child: ClipOval(
  51. child: Container(
  52. width: 8,
  53. height: 8,
  54. color: s == widget._images[_curIndex % length]
  55. ? Colors.white
  56. : Colors.grey,
  57. ),
  58. ),
  59. );
  60. }).toList(),
  61. ),
  62. );
  63. }
  64. Widget _buildPageView() {
  65. var length = widget._images.length;
  66. return SizedBox(
  67. height: widget.height,
  68. child: PageView.builder(
  69. controller: _pageController,
  70. onPageChanged: (index) {
  71. setState(() {
  72. _curIndex = index;
  73. if (index == 0) {
  74. _curIndex = length;
  75. _changePage();
  76. }
  77. });
  78. },
  79. itemBuilder: (context, index) {
  80. return GestureDetector(
  81. onPanDown: (details) {
  82. _cancelTimer();
  83. },
  84. onTap: () {
  85. ScaffoldMessenger.of(context).showSnackBar(
  86. SnackBar(
  87. content: Text('当前 page 为 ${index % length}'),
  88. duration: const Duration(milliseconds: 500),
  89. ),
  90. );
  91. },
  92. child: Image.asset(
  93. widget._images[index % length],
  94. fit: BoxFit.cover,
  95. ),
  96. );
  97. },
  98. ),
  99. );
  100. }
  101. /// 点击到图片的时候取消定时任务
  102. _cancelTimer() {
  103. _timer.cancel();
  104. _initTimer();
  105. }
  106. /// 初始化定时任务
  107. _initTimer() {
  108. _timer = Timer.periodic(const Duration(seconds: 3), (t) {
  109. _curIndex++;
  110. _pageController.animateToPage(
  111. _curIndex,
  112. duration: const Duration(milliseconds: 300),
  113. curve: Curves.linear,
  114. );
  115. });
  116. }
  117. /// 切换页面,并刷新小圆点
  118. _changePage() {
  119. Timer(const Duration(milliseconds: 350), () {
  120. _pageController.jumpToPage(_curIndex);
  121. });
  122. }
  123. }