首页 > 解决方案 > 如何使用不同的控制器同步两个或多个 PageView

问题描述

我有 2 个具有不同 viewportFraction 的 PageView。有什么方法可以滚动其中一个 PageViews 而另一个在同一页面上滚动或偏移?

还要问,是否可以在代码中将 PageView 控制到偏移量的中间?

class MyPageControllers extends StatefulWidget {
  @override
  _MyPageControllersState createState() => _MyPageControllersState();
}

class _MyPageControllersState extends State<MyPageControllers> {

  PageController _controller1;
  PageController _controller2;

  Widget _itemBuilder(BuildContext context, int index) => Container(
    color: Colors.primaries[index % Colors.primaries.length],
    child: Center(
      child: Text(
        index.toString(),
        style: TextStyle(color: Colors.white, fontSize: 60),
      ),
    ),
  );

  @override
  void initState() {
    super.initState();
    _controller1 = PageController(viewportFraction: 0.8);
    _controller2 = PageController(viewportFraction: 0.5);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: PageView.builder(
            controller: _controller1,
            itemBuilder: _itemBuilder,
          ),
        ),
        SizedBox(
          height: 40,
        ),
        Expanded(
          child: PageView.builder(
            controller: _controller2,
            itemBuilder: _itemBuilder,
          ),
        ),
      ],
    );
  }
}

在此处输入图像描述

标签: fluttercontroller

解决方案


PageView因此,您需要在其中一个小部件PageController( )上附加一个侦听器_controller1,然后更改offset另一个PageView小部件 PageController( _controller2) 的监听器。

initState您需要在初始化控制器后添加这段代码:

_controller1.addListener(() {
   _controller2.jumpTo(_controller1.offset);
});

更新的答案(选择页面同步):

_controller1.addListener(() {
   _controller2.animateToPage(
     _controller1.page.toInt(),
     duration: Duration(milliseconds: 500),
     curve: Curves.ease,
   );
});

更新答案(检测手动滚动):

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyPageControllers(),
        ),
      ),
    );
  }
}

class MyPageControllers extends StatefulWidget {
  @override
  _MyPageControllersState createState() => _MyPageControllersState();
}

class _MyPageControllersState extends State<MyPageControllers> {
  PageController _controller1;
  PageController _controller2;
  int manualController = -1;

  Widget _itemBuilder(BuildContext context, int index) => Container(
        color: Colors.primaries[index % Colors.primaries.length],
        child: Center(
          child: Text(
            index.toString(),
            style: TextStyle(color: Colors.white, fontSize: 60),
          ),
        ),
      );

  @override
  void initState() {
    super.initState();
    _controller1 = PageController(viewportFraction: 0.8);
    _controller2 = PageController(viewportFraction: 0.5);
    _controller1.addListener(() {
      if (manualController == 1) {
        _controller2.jumpTo(_controller1.offset);
      }
    });
    _controller2.addListener(() {
      if (manualController == 2) {
        _controller1.jumpTo(_controller2.offset);
      }
    });

//     _controller1.addListener(() {
//       _controller2.animateToPage(
//         _controller1.page.toInt(),
//         duration: Duration(milliseconds: 500),
//         curve: Curves.ease,
//       );
//     });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: GestureDetector(
            onTapDown: (tapDownDetails){
              manualController = 1;
              setState(() {});
            },
            onTapUp: (tapUpDetails){
              manualController = -1;
              setState(() {});
            },
            child: PageView.builder(
              controller: _controller1,
              itemBuilder: _itemBuilder,
            ),
          ),
        ),
        SizedBox(
          height: 40,
        ),
        Expanded(
          child: GestureDetector(
            onTapDown: (tapDownDetails){
              manualController = 2;
              setState(() {});
            },
            onTapUp: (tapUpDetails){
              manualController = -1;
              setState(() {});
            },
            child: PageView.builder(
              controller: _controller2,
              itemBuilder: _itemBuilder,
            ),
          ),
        ),
      ],
    );
  }
}



推荐阅读