Skip to content

Instantly share code, notes, and snippets.

@AlexV525
Created May 8, 2020 07:25
Show Gist options
  • Save AlexV525/49e930bdc197c5278aa59810b944fea7 to your computer and use it in GitHub Desktop.
Save AlexV525/49e930bdc197c5278aa59810b944fea7 to your computer and use it in GitHub Desktop.
Dots Indicator for page switching.
import 'dart:math' as math;
import 'package:flutter/material.dart';
///
/// An indicator showing the currently selected page of a PageController.
///
class DotsIndicator extends AnimatedWidget {
const DotsIndicator({
@required this.controller,
@required this.itemCount,
this.onPageSelected,
this.maxWidth = 24.0,
this.height = 20.0,
this.size = 8.0,
this.spacing = 30.0,
this.color,
this.colors,
this.unselectedColor = Colors.grey,
}) : assert(
color == null || colors == null, 'Cannot provide color and colors at the same time.'),
super(listenable: controller);
/// The PageController that this DotsIndicator is representing.
final PageController controller;
/// The number of items managed by the PageController
final int itemCount;
/// Called when a dot is tapped
final ValueChanged<int> onPageSelected;
/// The maximum width of the indicator.
final double maxWidth;
/// The height of the indicator.
final double height;
/// The color of the dots.
/// Defaults to `Colors.black`.
final Color color;
final List<Color> colors;
/// The color of the dots which is unselected.
/// Defaults to `Colors.grey`.
final Color unselectedColor;
/// The size of the dots
final double size;
/// The distance between the center of each dot
final double spacing;
void _onPageSelected(int index) {
controller.animateToPage(
index,
duration: const Duration(milliseconds: 300),
curve: Curves.fastOutSlowIn,
);
}
Widget _buildDot(int index) {
final unselected = Curves.easeOut.transform(
math.max(
0.0,
1.0 - ((controller.page ?? controller.initialPage) - index).abs(),
),
);
final zoom = 1.0 + (maxWidth / size - 1.0) * unselected;
List<Color> _colors;
if (colors != null) {
_colors = List(2);
_colors[0] = Color.lerp(unselectedColor, colors[0], unselected);
_colors[1] = Color.lerp(unselectedColor, colors[1], unselected);
}
return SizedBox(
width: spacing,
child: Center(
child: Container(
width: size * zoom,
height: size,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(size),
color: _colors == null
? Color.lerp(
unselectedColor,
color,
unselected,
)
: (color == null ? unselectedColor : color),
gradient: (_colors != null)
? LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: _colors,
)
: null,
),
child: GestureDetector(onTap: () => _onPageSelected(index)),
),
),
);
}
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List<Widget>.generate(itemCount, _buildDot),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment