簡體   English   中英

在 Flutter 中如何讓 PageView 滾動得更快? 動畫似乎很慢,內部 ListView 無法響應我的垂直手勢

[英]In Flutter how to make PageView scroll faster? The animation seems to be slow and the inner ListView cant response my vertical gesture

你可以在視頻中看到細節

不知道怎么解決這個問題。。對比Android Native ViewPager,Flutter中PageView的動畫好像比較慢,用戶只能等這個慢動畫完全停止,才能拖動內部ListView。感覺用戶體驗比原生android ViewPager差。希望有一個完美的解決方案。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/reactive_page_view/reactive_page_view.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Page(),
    );
  }
}

class Page extends StatefulWidget {
  @override
  _PageState createState() => _PageState();
}

PageView view;

class _PageState extends State<Page> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CupertinoNavigationBar(
        middle: Text("Demo"),
      ),
      body: PageView.builder(
          physics: BouncingScrollPhysics(),
          itemCount: 3,
          itemBuilder: (context, index) {
            return ItemPage();
          }),
    );
  }
}

class ItemPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        physics: BouncingScrollPhysics(),
        itemCount: 30,
        itemBuilder: (context, index) {
          return Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text('這是第$index', style: TextStyle(fontSize: 30)),
          );
        });
  }
}


您可以定義自己的 PageController 實例並使用其方法 nextPage() 和 previousPage()。 他們有“持續時間”參數來控制頁面視圖滾動的速度。

final PageController controller = PageController(
    viewportFraction: 0.9,
  );

  void nextPage() async {
    await controller.nextPage(
      duration: Duration(milliseconds: 200),
      curve: Curves.easeOut,
    );
  }

  void prevPage() async {
    await controller.previousPage(
      duration: Duration(milliseconds: 200),
      curve: Curves.easeOut,
    );
  }

然后將此控制器應用於您的頁面視圖:

return PageView.builder(
      physics: NeverScrollableScrollPhysics(),
      controller: controller,
      ...
    );

main.dart 的完整代碼:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyPageViewExample(),
    );
  }
}

class MyPageViewExample extends StatelessWidget {
  MyPageViewExample({Key key}) : super(key: key);

  final PageController controller = PageController(
    viewportFraction: 0.9,
  );

  void nextPage() async {
    await controller.nextPage(
      duration: Duration(milliseconds: 200),
      curve: Curves.easeOut,
    );
  }

  void prevPage() async {
    await controller.previousPage(
      duration: Duration(milliseconds: 200),
      curve: Curves.easeOut,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: <Widget>[
          Container(
            color: Colors.grey[100],
          ),
          Padding(
            padding: EdgeInsets.only(top: 20.0 + MediaQuery.of(context).padding.top, bottom: 20.0),
            child: _buildCarousel(context),
          ),
        ],
      ),
    );
  }

  Widget _buildCarousel(BuildContext context) {
    return PageView.builder(
      physics: NeverScrollableScrollPhysics(),
      controller: controller,
      scrollDirection: Axis.horizontal,
      itemBuilder: (BuildContext context, int itemIndex) {
        return _buildItem(context, itemIndex);
      },
      itemCount: 5,
    );
  }

  Widget _buildItem(BuildContext context, int itemIndex) {
    return Padding(
      padding: EdgeInsets.only(left: 4.0, top: 10.0, right: 4.0, bottom: 10.0),
      child: GestureDetector(
        onPanUpdate: (details) {
          if (details.delta.dx < 0) {
            nextPage();
          }
          if (details.delta.dx > 0) {
            prevPage();
          }
        },
        child: Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.all(Radius.circular(35.0)),
          ),
          child: Center(
            child: Text(
              'Item ' + (itemIndex + 1).toString(),
            ),
          ),
        ),
      ),
    );
  }
}

您可以控制滾動動畫的一般物理。

PageView(
  physics: CustomPageViewScrollPhysics(),
            

控制滾動行為:


class CustomPageViewScrollPhysics extends ScrollPhysics {
  const CustomPageViewScrollPhysics({ScrollPhysics? parent})
      : super(parent: parent);

  @override
  CustomPageViewScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return CustomPageViewScrollPhysics(parent: buildParent(ancestor)!);
  }

  @override
  SpringDescription get spring => const SpringDescription(
        mass: 50,
        stiffness: 100,
        damping: 0.8,
      );
}

您還應該能夠計算質量、剛度、阻尼的持續時間,但我相信這些選項更適合您的問題。 來源

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM