Flutter Pageview.builder in default, does not do horizontal or vertical scalling. If we want to do any kind of scaling within PageView.builder, We need to do this scaling based on scaling factor. Scaling factor could come from current value of the page.
If we get the page value, we would solve the height problem and height scalling.
Download the starter code here
Below is the function and code for getting page's value.
PageController pageController = PageController(viewportFraction: 0.85);
var _currPageValue = 0.0;
@override
void initState(){
super.initState();
pageController.addListener(() {
setState(() {
_currPageValue= pageController.page!;
print(_currPageValue);
});
});
}
To get page value we need to attach a listener to our page controller. That's what we did in the initState() function.
And we want to update the page value immediately, we need to save it inside the setState() function.
We need to get that value from the PageController(). Some must know important keys about Pageview.builder
√ Current index value is same as page value
√ Index value suddenly changes, but page value changes slowly
√ Index value could be integer only, but page value have decimals
√ Moving to the left, index and page value increases
√ Moving to the right, index and page value decrease. Index value decreases imediately by one.
At the end, we need to dispose the controller.
@override
void dispose() {
super.dispose();
pageController.dispose();
}
Entry of the Pageview.builder
PageView.builder(
controller: pageController,
physics: BouncingScrollPhysics(),
itemCount: 5,
itemBuilder: (context, position) {
return _buildPageItem(position);
},
)
In the PageView.builder() contstructor we need to use property for mentioning pageController.
The algorithm to realise a smooth scaling for height. We also did the height transition here.
//scale factor
double _scaleFactor = .8;
//view page height
double _height = 230.0;
_buildPageItem(int index) {
Matrix4 matrix = new Matrix4.identity();
if(index==_currPageValue.floor()){
var currScale = 1-(_currPageValue-index)*(1- _scaleFactor );
var currTrans = _height*(1-currScale)/2;
matrix = Matrix4.diagonal3Values(1.0, currScale, 1.0)
..setTranslationRaw(0, currTrans, 0);
}else if(index ==_currPageValue.floor()+1){
var currScale = _scaleFactor+(_currPageValue-index+1)*(1- _scaleFactor );
var currTrans = _height*(1-currScale)/2;
matrix = Matrix4.diagonal3Values(1.0, currScale, 1.0)
..setTranslationRaw(0, currTrans, 0);
}else if(index ==_currPageValue.floor()-1){
var currScale = 1-(_currPageValue-index)*(1- _scaleFactor );
var currTrans = _height*(1-currScale)/2;
matrix = Matrix4.diagonal3Values(1.0, currScale, 1.0)
..setTranslationRaw(0, currTrans, 0);
}else{
var currScale = 0.8;
matrix = Matrix4.diagonal3Values(1.0, currScale, 1.0)
..setTranslationRaw(0, _height*(1-_scaleFactor)/2, 0);
}
return Transform(
transform: matrix,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5),
child: GestureDetector(
child: Align(
alignment: Alignment.topCenter,
child: Stack(
children: [
Container(
padding: const EdgeInsets.only(left: 20, top: 20),
height: 220,
width: MediaQuery.of(context).size.width-20,
margin: const EdgeInsets.only(right: 5, left: 5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color:index.isEven?Color(0xFF69c5df):Color(0xFF9294cc),
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
"img/food0.png"
)
)
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: const EdgeInsets.only(bottom: 40, left: 35, right: 35),
width: double.maxFinite,
height: 120,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color:Colors.white,
boxShadow: [
BoxShadow(
color: Color(0xFFe8e8e8),
blurRadius: 5.0,
offset: Offset(0, 5)
),
BoxShadow(
color: Colors.white,
offset: Offset(-5, 0)
),
BoxShadow(
color: Colors.white,
offset: Offset(5, 0)
)
]
),
child: Container(
padding: const EdgeInsets.only(top: 20, left: 15, right: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Fruit nutrition meal"),
SizedBox(height: 10,),
Row(
children: [
Wrap(
children: List.generate(5, (index) => Icon(Icons.star, color:Colors.cyan, size:15)),
),
SizedBox(width: 10,),
TextWidget(text: "4.5", color: Color(0xFFccc7c5)),
SizedBox(width: 10,),
TextWidget(text: "1287 comments", color: Color(0xFFccc7c5))
],
),
SizedBox(height: 20,),
],
),
),
),
),
],
),
),
),
),
);
}
Scaling can not be done without Matrix4 API in flutter. That's why we use this API, and pass the scaled value to the function called Matrix4.diagonal3Value() and Matrix4.setTransitionRaw()
Matrix4.diagonal3Value() is for setting the scaling factor in x, y and z.
Matrix4.setTransitionRaw() for changing the height position.