Column子PageView全屏交互

发布于 2025-01-20 19:28:37 字数 1670 浏览 4 评论 0 原文

我正在尝试创建一个屏幕,如下所示:

在此处输入图像描述

底部是 PageView.builder。我希望它可以通过整个屏幕进行交互。

我想到的第一件事是将它们包装在一个堆栈中,在顶部创建一个不可见的 PageView,并同步底部和不可见(顶部)PageView 的控制器。但是,在这种情况下,按钮不会接收输入。

PS:用 HitTestBehavior.translucent 监听器包裹顶部 PageView 不起作用。我认为 PageView 不允许点击事件传播。

我怎样才能接近这个屏幕?

class Test extends StatelessWidget {
  Test({Key? key}) : super(key: key);
  final pageController = PageController();
  final infoPages = [
    Container(
      color: Colors.blue[200],
      child: Text("info 1"),
    ),
    Container(
      color: Colors.blue[400],
      child: Text("info 2"),
    ),
    Container(
      color: Colors.blue[600],
      child: Text("info 3"),
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
            flex: 2,
            child: Container(
              color: Colors.grey,
              child: Text("this is a static image"),
            )),
        Expanded(
          child: TextButton(
            onPressed: () {
              print("button pressed");
            },
            child: const Text("This is a static button"),
          ),
        ),
        Expanded(
          flex: 2,
          child: PageView.builder(
            controller: pageController,
            itemCount: infoPages.length,
            itemBuilder: ((context, index) {
              return infoPages[index];
            }),
          ),
        ),
      ],
    );
  }
}

I'm trying to create a screen as follows:

enter image description here

The bottom part is PageView.builder. I want it to be interactable through the whole screen.

The first thing I came up with was wrapping them in a stack, creating an invisible PageView on the top, and synchronizing the bottom and invisible(top) PageViews' controllers. But, in this case, the button doesn't receive input.

PS: Wrapping the top PageView by a listener with HitTestBehavior.translucent didn't work. I think PageView doesn't let tap events propagate.

How can I aproach this screen?

class Test extends StatelessWidget {
  Test({Key? key}) : super(key: key);
  final pageController = PageController();
  final infoPages = [
    Container(
      color: Colors.blue[200],
      child: Text("info 1"),
    ),
    Container(
      color: Colors.blue[400],
      child: Text("info 2"),
    ),
    Container(
      color: Colors.blue[600],
      child: Text("info 3"),
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
            flex: 2,
            child: Container(
              color: Colors.grey,
              child: Text("this is a static image"),
            )),
        Expanded(
          child: TextButton(
            onPressed: () {
              print("button pressed");
            },
            child: const Text("This is a static button"),
          ),
        ),
        Expanded(
          flex: 2,
          child: PageView.builder(
            controller: pageController,
            itemCount: infoPages.length,
            itemBuilder: ((context, index) {
              return infoPages[index];
            }),
          ),
        ),
      ],
    );
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酒解孤独 2025-01-27 19:28:37

亲爱的平行宇宙的我;
我通过用堆栈包装它、禁用 PageView 交互并使用 GestureDetector 控制它来解决它。

class Test extends StatefulWidget {
  Test({Key? key}) : super(key: key);

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {
  final pageController = PageController();

  final infoPages = [
    Container(
      color: Colors.blue[200],
      child: Text("info 1"),
    ),
    Container(
      color: Colors.blue[400],
      child: Text("info 2"),
    ),
    Container(
      color: Colors.blue[600],
      child: Text("info 3"),
    ),
  ];

  late double offset;
  late double start;
  bool snap = true;

  @override
  Widget build(BuildContext context) {
    return Stack(children: [
      Column(
        children: [
          Expanded(
            flex: 2,
            child: Container(
              color: Colors.grey,
              child: Text("this is a static image"),
            ),
          ),
          Expanded(
            child: TextButton(
              onPressed: () {
                print("button pressed");
              },
              child: const Text("This is a static button"),
            ),
          ),
          Expanded(
            flex: 2,
            child: PageView.builder(
              pageSnapping: snap,
              physics: const NeverScrollableScrollPhysics(),
              controller: pageController,
              itemCount: infoPages.length,
              itemBuilder: ((context, index) {
                return infoPages[index];
              }),
            ),
          ),
        ],
      ),
      GestureDetector(
        onHorizontalDragStart: (details) {
          offset = pageController.offset;
          start = details.globalPosition.dx;
          setState(() {
            snap = false;
          });
        },
        onHorizontalDragUpdate: (details) {
          final dx = details.globalPosition.dx - start;
          double temp = offset - dx;
          pageController.jumpTo(temp);
        },
        onHorizontalDragEnd: (details) {
          setState(() {
            snap = true;
          });
        },
      )
    ]);
  }
}

Dear parallel universe me;
I solved it by wrapping it with a stack, disabling the PageView interaction, and controlling it with a GestureDetector.

class Test extends StatefulWidget {
  Test({Key? key}) : super(key: key);

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {
  final pageController = PageController();

  final infoPages = [
    Container(
      color: Colors.blue[200],
      child: Text("info 1"),
    ),
    Container(
      color: Colors.blue[400],
      child: Text("info 2"),
    ),
    Container(
      color: Colors.blue[600],
      child: Text("info 3"),
    ),
  ];

  late double offset;
  late double start;
  bool snap = true;

  @override
  Widget build(BuildContext context) {
    return Stack(children: [
      Column(
        children: [
          Expanded(
            flex: 2,
            child: Container(
              color: Colors.grey,
              child: Text("this is a static image"),
            ),
          ),
          Expanded(
            child: TextButton(
              onPressed: () {
                print("button pressed");
              },
              child: const Text("This is a static button"),
            ),
          ),
          Expanded(
            flex: 2,
            child: PageView.builder(
              pageSnapping: snap,
              physics: const NeverScrollableScrollPhysics(),
              controller: pageController,
              itemCount: infoPages.length,
              itemBuilder: ((context, index) {
                return infoPages[index];
              }),
            ),
          ),
        ],
      ),
      GestureDetector(
        onHorizontalDragStart: (details) {
          offset = pageController.offset;
          start = details.globalPosition.dx;
          setState(() {
            snap = false;
          });
        },
        onHorizontalDragUpdate: (details) {
          final dx = details.globalPosition.dx - start;
          double temp = offset - dx;
          pageController.jumpTo(temp);
        },
        onHorizontalDragEnd: (details) {
          setState(() {
            snap = true;
          });
        },
      )
    ]);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文