I implemented a perspective_page_view
like this. I updated the code to the new Flutter Version and everything is working fine.
The thing is that I would like that PageView
to have an infinite loop.
I tried multiple different solutions I found on this question but non of them worked. They all messed up the perspective in my case.
I feel like this should be possible, but I can not come up with a solution. Happy for every help! Let me know if you need any more info!
Minimal Producable Example:
My Scaffold
:
class ProjectsViewState extends State<ProjectsView>
with TickerProviderStateMixin {
late PageViewHolder holder;
late PageController _controller;
double fraction = 0.50;
@override
void initState() {
super.initState();
holder = PageViewHolder(value: 2.0);
_controller = PageController(initialPage: 2, viewportFraction: fraction);
_controller.addListener(() {
holder.setValue(_controller.page);
});
}
int currentPage = 2;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ChangeNotifierProvider<PageViewHolder>.value(
value: holder,
child: Flexible(
child: PageView.builder(
controller: _controller,
onPageChanged: (value) {
setState(() {
currentPage = value;
});
},
itemCount: projectsCounter,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return ProjectsGalleryView(
number: index.toDouble(),
fraction: fraction,
);
},
),
),
),
),
);
}
}
and the pageView
:
class ProjectsGalleryView extends StatefulWidget {
final double number;
final double fraction;
const ProjectsGalleryView(
{super.key, required this.number, required this.fraction});
@override
State<ProjectsGalleryView> createState() => _ProjectsGalleryViewState();
}
class _ProjectsGalleryViewState extends State<ProjectsGalleryView>
with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
double value = Provider.of<PageViewHolder>(context).value;
double diff = (widget.number - value);
//Matrix for Elements
final Matrix4 pvMatrix = Matrix4.identity()
..setEntry(3, 3, 1 / 0.8) // Increasing Scale by 80%
// ..setEntry(1, 1, widget.fraction) // Changing Scale Along Y Axis
..setEntry(3, 0, 0.003 * -diff); // Changing Perspective Along X Axis
return Transform(
transform: pvMatrix,
alignment: FractionalOffset.center,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 0),
child: SizedBox(
height: 200,
width: 200,
child: Container(
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.circular(10),
),
),
),
),
if (diff <= 1.0 && diff >= -1.0) ...[
AnimatedOpacity(
duration: const Duration(milliseconds: 100),
opacity: 1 - diff.abs(),
child: const Padding(
padding: EdgeInsets.symmetric(
horizontal: 15,
vertical: 20,
),
child: Text(
'A Text with animated opacity',
),
),
),
]
],
),
);
}