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',
                ),
              ),
            ),
          ]
        ],
      ),
    );
  }
 
     
    
