Flutter PageView 禁止滑动

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter PageView 禁止滑动相关的知识,希望对你有一定的参考价值。

参考技术A flutter 中的 PageView 应该类似于android 中的ViewPager ,可以和底部导航或者 Tab Bar 联动时。

当然如果需要禁止滑动:

PageView中有physics 属性:具体内容可查看官方文档

禁止滑动可以这样使用:

在 Flutter 的 PageView 中动态创建或重新排序子小部件

【中文标题】在 Flutter 的 PageView 中动态创建或重新排序子小部件【英文标题】:Dynamically creating or reordering children widgets in a PageView in Flutter 【发布时间】:2020-11-16 07:43:32 【问题描述】:

背景:想象一下 Snapchat UI。您在您的好友列表屏幕上(在相机屏幕的左侧)。你在朋友的名字上从左向右滑动,当你滑动时,Snapchat 会动画化从朋友列表屏幕到该朋友的聊天窗口的过渡。

所需行为:在垂直列表中的任何图块上从右向左滑动,以从右侧显示与该图块相关的上下文屏幕。在上下文屏幕中,从左向右滑动以返回磁贴列表屏幕。

当前方法:使用带有两个孩子的PageView 小部件。第一个孩子是朋友列表小部件。第二个孩子将是任何一个“向左滑动”的图块的上下文屏幕小部件。为了实现这一点,需要动态创建第二个孩子(意思是在运行时),可能通过将每个图块包装在GestureDetector 小部件中,并在给定图块的onHorizontalDragStart 回调函数中设置 PageView 的第二个子节点。

我的问题:您如何在 Flutter 应用程序中动态(在运行时)创建或重新排序 PageView 小部件的子级?

PageView.builder 的颤振文档说:

默认情况下,PageView.builder 不支持子重新排序。如果您打算稍后更改子订单,请考虑使用 PageView 或 PageView.custom。

听起来这对于 PageView 或 PageView.custom 都是可能的,但是如何实现呢?

【问题讨论】:

【参考方案1】:

他们在PageView.custom 中有一个关于重新排序处理的非常直接的示例:

  class MyPageView extends StatefulWidget 
    const MyPageView(Key? key) : super(key: key);
 
    @override
    State<MyPageView> createState() => _MyPageViewState();
  
 
  class _MyPageViewState extends State<MyPageView> 
    List<String> items = <String>['1', '2', '3', '4', '5'];
 
    void _reverse() 
      setState(() 
        items = items.reversed.toList();
      );
    
 
    @override
    Widget build(BuildContext context) 
      return Scaffold(
        body: SafeArea(
          child: PageView.custom(
            childrenDelegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) 
                return KeepAlive(
                  data: items[index],
                  key: ValueKey<String>(items[index]),
                );
              ,
              childCount: items.length,
              findChildIndexCallback: (Key key) 
                final ValueKey<String> valueKey = key as ValueKey<String>;
                final String data = valueKey.value;
                return items.indexOf(data);
              
            ),
          ),
        ),
        bottomNavigationBar: BottomAppBar(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextButton(
                onPressed: () => _reverse(),
                child: const Text('Reverse items'),
              ),
            ],
          ),
        ),
      );
    
  
 
  class KeepAlive extends StatefulWidget 
    const KeepAlive(Key? key, required this.data) : super(key: key);
 
    final String data;
 
    @override
    State<KeepAlive> createState() => _KeepAliveState();
  
 
  class _KeepAliveState extends State<KeepAlive> with AutomaticKeepAliveClientMixin
    @override
    bool get wantKeepAlive => true;
 
    @override
    Widget build(BuildContext context) 
      super.build(context);
      return Text(widget.data);
    
  

在我的理解中可以简化为:

  class MyPageView extends StatefulWidget 
    const MyPageView(Key? key) : super(key: key);
 
    @override
    State<MyPageView> createState() => _MyPageViewState();
  
 
  class _MyPageViewState extends State<MyPageView> 
    List<String> items = <String>['1', '2', '3', '4', '5'];
 
    void _reverse() 
      setState(() 
        items = items.reversed.toList();
      );
    
 
    @override
    Widget build(BuildContext context) 
      return Scaffold(
        body: SafeArea(
          child: PageView.custom(
            childrenDelegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) 
                return KeepAlive(
                  data: items[index],
                  key: ValueKey<String>(items[index]),
                );
              ,
              childCount: items.length,
              // This is default, can be omitted.
              addAutomaticKeepAlives: true,
              findChildIndexCallback: (Key key) 
                final ValueKey<String> valueKey = key as ValueKey<String>;
                final String data = valueKey.value;
                return items.indexOf(data);
              
            ),
          ),
        ),
        bottomNavigationBar: BottomAppBar(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextButton(
                onPressed: () => _reverse(),
                child: const Text('Reverse items'),
              ),
            ],
          ),
        ),
      );
    
  
 
  class KeepAlive extends StatelessWidget 
    const KeepAlive(Key? key, required this.data) : super(key: key);
 
    final String data;
 
    @override
    Widget build(BuildContext context) 
      super.build(context);
      return Text(data);
    
  

【讨论】:

以上是关于Flutter PageView 禁止滑动的主要内容,如果未能解决你的问题,请参考以下文章

Flutter自定义Widget—随滑动改变高度的PageView

如何在 Flutter 中使用 PageView 创建轮播(滑动动画)?

Flutter 专题108 图解 PageView 滑动页面预览小尝试 #yyds干货盘点#

Flutter 错误“在使用它构建 PageView 之前无法访问 PageController.page。”

颤振:PageView.builder onPage 属性 - 我可以更改以便在全页面滑动而不是 0.50 时触发索引

如何在 Flutter 中创建垂直滚动的 PageView?