Recently, I happened to use PageView, and found that there seems to be no indicator provided by the official. I searched indicator in pub and clicked the star with the largest number. I found that his refresh is refreshed together with PageView, which does not match what I need. I decided to do it myself.
rendering
The project address
flutter_page_indicator
The source code
The item Indicator on the pub seems to be painted in paint.
My first impression is that the outer layer of the Stack is wrapped with regular dots and dots in the current position.
The lower layer is a ListView, and the upper layer of the ListView is a Container representing the current progress. When the location changes, you only need to change the location of the upper-layer Container.
Modify dot properties using Decoration
1. Create onePageIndicator
class
class PageIndicator extends StatefulWidget {
///PageView Specifies the length of the subview set
final int length;
///PageController
final PageController pageController;
/// Default color
final Color defaultColor;
/// Default width
final double defaultWidth;
/// Default height
final double defaultHeight;
/ / / the default Decoration
final Decoration defaultDecoration;
/// The current color
final Color currentColor;
/// The current width
final double currentWidth;
/// The current height
final double currentHeight;
/ / / the current Decoration
final Decoration currentDecoration;
/ / / spacing
final double padding;
PageIndicator({
Key key,
this.length,
this.pageController,
this.defaultColor = Colors.white,
this.defaultWidth = 8.this.defaultHeight = 8.this.defaultDecoration,
this.currentColor = Colors.grey,
this.currentWidth = 8.this.currentHeight = 8.this.currentDecoration,
this.padding = 8,
}): assert(length ! =null), assert(pageController ! =null), super(key:key);
@override
State<StatefulWidget> createState() {
return_PageState(); }}Copy the code
PageIndicator declares some variables, except length and pageController, which are required and all have default values.
Create the _PageState class
In the PageIndicator constructor we pass in the PageController so that we can get the page value of the current PageView simply by adding an addListener to the PageController at initState. Then call setState(() {}); Refresh.
When sliding pageView, what we really need to change is the upper layer of the progress dot, so we don’t need to use setState(() {}); To refresh the entire indicator, just refresh the progress dots individually. The StreamBuilder is used here to do the partial refresh
_PageState source code:
class _PageState extends State<PageIndicator> {
StreamController _streamController;
@override
void initState() {
super.initState();
_streamController = StreamController<double> (); widget.pageController.addListener((){ _streamController.sink.add(widget.pageController.page); }); }@override
Widget build(BuildContext context) {
return Container(
width: widget.normalWidth * widget.length +
widget.padding * (widget.length + 1),
height: widget.currentHeight,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0.// use ListView to display normal dots
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: widget.length,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (_, position) {
return Container(
width: widget.normalWidth,
height: widget.normalHeight,
margin: EdgeInsets.only(
left: widget.padding),
decoration: widget.normalDecoration ??
BoxDecoration(
color: widget.normalColor, shape: BoxShape.circle),
);
}),
),
Positioned(
/ / / StreamBuilder refresh
child: StreamBuilder<double>(
stream: _streamController.stream,
initialData: 0,
builder: (context, snapshot) {
/// A dot that represents the current progress
return Container(
width: widget.currentWidth,
height: widget.currentHeight,
decoration: widget.currentDecoration ?? BoxDecoration(
color: widget.currentColor, shape: BoxShape.circle),
margin: EdgeInsets.only(
left: left(snapshot.data),
),
);
}),
left: 0() [(), (); }double left(double page){
if(widget.currentWidth > widget.normalWidth){
return widget.normalWidth * page + widget.padding*page + widget.padding - (widget.currentWidth - widget.normalWidth)/2;
}else{
return (widget.normalWidth * page + (page+1) * widget.padding); }}@override
void dispose() {
super.dispose();
_streamController?.close();
}
}
Copy the code
use
In Pubspec.yaml introduce:
dependencies:
pageview_indicator_plugins: ^0.02.
Copy the code
1. By default, you only need to pass pageView Children’s length and pageController.
PageIndicator(
length: 6,
pageController: pageController,
)
Copy the code
2. You can also modify the width and height of the dot and modify the Decoration property
PageIndicator(
length: 6,
pageController: secondController,
currentWidth: 16,
currentDecoration: BoxDecoration(
color: Colors.cyanAccent,
borderRadius: BorderRadius.circular(10)))Copy the code
Making address:
Github.com/Zhengyi66/f…