1
  1. 我的问题总结

目标

我的目标是展示一个长页面的轮播。所以我使用带有滚动视图的 PageView。PageView 水平滚动。滚动视图(子视图)垂直滚动。

预期成绩

水平滑动和垂直滚动平滑。

实际结果

如果我水平滑动到下一页,我无法立即垂直滚动它。我需要等待 1 秒钟。似乎用户必须等待动画完成才能与新的当前页面进行交互。

到目前为止我尝试了什么:

  • 我尝试了手势识别器来传递拖动事件,但我没有让它工作。
  • 我尝试了不同的小部件来替换 PageView 但效果相同。
  • 我用 wantKeepAlive = true 尝试了 AutomaticKeepAliveClientMixin
  • 我试过 PageView.physics = AlwaysScrollableScrollPhysics()

这是重现问题所需的最少代码

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: carousel(),
    );
  }

  Widget carousel() {
    return PageView(
      children: <Widget>[
        page(Colors.pinkAccent),
        page(Colors.blueAccent),
        page(Colors.orangeAccent)
      ],
    );
  }

  Widget page(Color color) {
    return Container(
        decoration: BoxDecoration(
          color: color,
        ),
        child: SingleChildScrollView(
          child: Column(
              children: pageContent()),
        ));
  }

  List<Widget> pageContent() {
    return <Widget>[
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
    ];
  }
}

4

2 回答 2

0

我成功地找到了一种解决方案,使我的 PageView 在水平和垂直方向上都非常平滑。

我禁用 PageView.pageSnapping 以使轮播非常流畅。但是我失去了磁效应,所以我使用 NotificationListener 来捕获 ScrollEndNotification 事件。当滚动结束时,我计算出对用户最可见的页面并调用 PageController.animateToPage() 来完成这项工作。

代码如下所示:

Widget getCarousel() {

  return NotificationListener<ScrollNotification>(
  onNotification: (scrollNotification) {

    if (scrollNotification is ScrollEndNotification) {
      print("ScrollEndNotification");

      Future.delayed(const Duration(milliseconds: 0), () {
        int newPage = pageController.page.round();
        print("end at $newPage");
        pageController.animateToPage(newPage, duration: Duration(milliseconds: 400), curve: Curves.fastOutSlowIn);
      });
    }
    return true;
  },
  child: PageView.builder(
    scrollDirection: Axis.horizontal,
    pageSnapping: false,
    controller: pageController,
    itemBuilder: (BuildContext context, int index) {
      return myPages[index];
    },
  )
);
}
于 2020-12-22T21:50:47.647 回答
0

经过一番挖掘,我相信问题出在 PageView 的 DragStartBehavior 上。为了流畅,PageView 的默认行为最终感觉迟缓,页面快照几乎感觉就像喝了太多酒。

这意味着当您想要垂直滚动时,PageView 仍然在变化中模糊不清。

当您调用 PageView 时调整 DragStartBehavior,它会感觉更加被动 - 它会感觉更加活泼,我相信这可以解决您的问题。

Widget carousel() {
    return PageView(
      children: <Widget>[
        dragStartBehavior: DragStartBehavior.down,
        page(Colors.pinkAccent),
        page(Colors.blueAccent),
        page(Colors.orangeAccent)
      ],
    );
  }

ps谢谢Yunnosch的谴责和笑声:)也可以随意编辑,因为我还不能准确评论!

于 2020-06-24T20:46:31.907 回答