PageView slide page preview application in many scenarios, side dish before only used the most basic usage, today side dish try to systematically learn the basic application of PageView;
PageView General users need a small number of sliding page switching scenarios, but the overall use is very flexible, often used to switch Tab page or active Banner;
Source code analysis
PageView({Key Key, this.scrolldirection = Axis. Horizontal, // Horizontal) this.reverse = false, This.pagesnapping = true, // If you want to slide the PageController controller backwards, // this. List<Widget> children = const <Widget>[], This.dragstartbehavior = dragStartBehavior.start,}) PageView.builder({Key Key, this.scrollDirection = Axis.horizontal, ... this.dragStartBehavior = DragStartBehavior.start, }) PageView.custom({ Key key, this.scrollDirection = Axis.horizontal, . this.dragStartBehavior = DragStartBehavior.start, })Copy the code
PageView is a stateless StatefulWidget that controls sliding and data listening via PageController and onPageChanged. It provides two named constructors that learn attributes one by one.
Case try
Default constructor
1. PageView()
The side dishes first generate a basic PageView using the default constructor;
return Container( height: 240,
child: PageView(children: <Widget>[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
Copy the code
2. scrollDirection
The scrollDirection is mainly used for PageView sliding direction, namely Axis. Horizontal and Axis. Vertical.
return Container( height: 240,
child: PageView(scrollDirection: Axis.horizontal, children: <Widget>[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
Copy the code
3. pageSnapping
PageSnapping is used to disable Page capture, which means whether the Page is the whole Page sliding switch; When pageSnapping=false, the Page can slide gradually and stop halfway.
return Container( height: 240,
child: PageView(pageSnapping: false, children: <Widget>[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
Copy the code
4. reverse
Reverse is used to determine whether to slide backwards by default. Similar to ListView, PageView initially defaults to left to right or top to bottom; Reverse =true the default direction idea, which is right to left or bottom to top;
return Container( height: 240,
child: PageView(reverse: true, children: <Widget>[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
Copy the code
5. onPageChanged
OnPageChanged page to monitor the callback, when the page switching, returns the current Position, can be dealt with according to the current location for business;
return Container( height: 240,
child: PageView(onPageChanged: (position) => print('Current index = ${position + 1}'),
children: <Widget>[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
Copy the code
6. physics
Physics is mainly reflected in the animation effects at the end of the home page and the last page. It is a ScrollPhysics type, which can be customized or handled according to the animation provided by Flutter. ClampingScrollPhysics and BouncingScrollPhysics are similar;
return Container( height: 240,
child: PageView(physics: BouncingScrollPhysics(), children: <Widget>[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
Copy the code
7. controller
Controller is the controller of PageView, you can set the page jump or initialization position, and slide animation effect;
class PageController extends ScrollController { PageController({ this.initialPage = 0, this.keepPage = true, This.viewportfraction = 1.0,})} this. ViewportFraction = 1.0,})}Copy the code
A simple understanding of PageController source code, mainly involving initialPage initialPage display Page group subscript; KeepPage Whether to save data state; ViewportFraction is the proportion that each Page occupies the entire PageView;
PageController also provides several important methods, including animateToPage and jumpToPage, for specific Page switching and linkage with other widgets;
PageController _controller;
@override
void initState() {
super.initState();
_controller = PageController(initialPage: 1, viewportFraction: 0.75);
}
return Container( height: 240,
controller: _controller, children: <Widget>[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
Copy the code
PageView.builder
PageView provides a convenient.Builder () constructor for a number of dynamic or similar widgets, similar to the listView.Builder () method. Note: ItemCount cannot be empty, so when you don’t set itemCount, PageView defaults to an infinite loop, and the array just keeps growing;
When we need to linkage with other widgets outside, we can switch pages or jump directly through PageController;
_bodyWid() {return Column(children: <Widget>[Container(height: 60, color: color.green. WithOpacity (0.8), child: Row(children: <Widget>[ Expanded( child: GestureDetector( child: Row( mainAxisAlignment: MainAxisAlignment center, the children: "Widget > [Text (' the directory 'style: TextStyle (fontSize: 16.0, color: Colors.white)), Icon(Icons.arrow_downward, color: Colors.white) ]), onTap: () {print('-- GestureDetector-- directory --'); setState(() {}); _currentIndex = 0; _controller.animateTopage (0, duration: Duration(milliseconds: 400), Curve: Curves. EaseInOut);})), Container(width: 0.5, color: White), Expanded(Child: GestureDetector(Child: Center(Child: Text(' bookmark ', style: TextStyle(fontSize: 16.0 color: Colors. White))), onTap: () {print('-- GestureDetector-- '); setState(() {}); _currentIndex = 1; _controller.animatetopage (1, duration: Duration(milliseconds: 400), curve: Curves.easeInOut); })) ])), _leftMenuPage() ]); } _leftMenuPage() { return Expanded( child: PageView.builder( itemBuilder: (context, position) => _leftItemPage(context, position), itemCount: 2, controller: _controller, onPageChanged: (position) { print('PageView.onPageChanged---$position'); setState(() { if (_currentIndex ! = position) { _currentIndex = position; }}); })); }Copy the code
PageView.custom
PageView also provides a.custom() constructor; Can add Page Page through SliverChildBuilderDelegate agent lazy loading Page and rearrange the pages, it is. The builder () constructor does not support;
return Container( height: 240, child: PageView.custom( controller: _controller, childrenDelegate: SliverChildBuilderDelegate((BuildContext context, int index) => _itemTransCard(index), childCount: 4))); _itemTransCard(index) { Matrix4 _matrix = Matrix4.identity(); print('---_itemTransCard-${_currentPageValue.floor()}-'); if (index == _currentPageValue.floor()) { // The Current Page Item var currScale = 1 - (_currentPageValue - index) * (1 - _scaleFactor); Var currTrans = 240.0 * (1 - currScale) / 2; _matrix = Matrix4. Diagonal3Values (1.0, currScale, 1.0).. CurrTrans setTranslationRaw (0.0, 0.0); return Transform(transform: _matrix, child: _itemCard(index)); } else if (index == _currentPageValue.floor() + 1) { // The Right Page Item var currScale = _scaleFactor + (_currentPageValue - index + 1) * (1 - _scaleFactor); Var currTrans = 240.0 * (1 - currScale) / 2; _matrix = Matrix4. Diagonal3Values (1.0, currScale, 1.0).. CurrTrans setTranslationRaw (0.0, 0.0); return Transform(transform: _matrix, child: _itemCard(index)); } else if (index == _currentPageValue.floor() - 1) { // The Left Page Item var currScale = 1 - (_currentPageValue - index) * (1 - _scaleFactor); Var currTrans = 240.0 * (1 - currScale) / 2; _matrix = Matrix4. Diagonal3Values (1.0, currScale, 1.0).. CurrTrans setTranslationRaw (0.0, 0.0); return Transform(transform: _matrix, child: _itemCard(index)); } else {// else _matrix = matrix4.diagonal3values (1.0, _scaleFactor, 1.0).. SetTranslationRaw (0.0, 240.0 * (1-_scalefactor) / 2, 0.0); setTranslationRaw(0.0, 240.0 * (1-_scalefactor) / 2, 0.0); return Transform(transform: _matrix, child: _itemCard(index)); }}Copy the code
During the test, when the initial display Page is not the home Page, there is a problem with the display effect. The corresponding Page is not displayed to the corresponding zoom size, but the default home Page is still the normal zoom size; Side found that initialization time, _currentPageValue hasn’t from PageController. The addListener () to monitor the assignment, the default is 0, so lead to display error, side dishes to _currentPageValue set initialization position assignment;
var _initialIndex = 1;
var _currentPageValue = 0.0;
@override
void initState() {
super.initState();
// _controller = PageController();
_controller =
PageController(initialPage: _initialIndex, viewportFraction: 0.75);
_currentPageValue = _initialIndex * 1.0;
_controller.addListener(() {
print('--CurrentPage--${_controller.page}');
_currentPageValue = _controller.page;
setState(() {});
});
}
Copy the code
PageView case source code
Side dish on PageView bottom is not deep enough, you can customize a lot of cool effect, suggest more try; If there is any mistake, please give guidance!
Source: Young Monk Atze