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

标签 android ios flutter dart flutter-animation

上下文:想象一下 Snapchat UI。您在您的好友列表屏幕上(在相机屏幕的左侧)。你在 friend 的名字上从左到右滑动,当你滑动时,Snapchat 会动画化从 friend 列表屏幕到该 friend 的聊天窗口的过渡。
期望行为:在垂直列表中的任何图 block 上从右向左滑动,以从右侧显示与该图 block 相关的上下文屏幕。在上下文屏幕中,从左向右滑动以返回磁贴列表屏幕。
当前方法:使用 PageView有两个 child 的小部件。第一个 child 是 friend 列表小部件。第二个 child 将是任何一个“向左滑动”的图 block 的上下文屏幕小部件。为了实现这一点,需要动态创建第二个 child (意思是在运行时),也许通过将每个图 block 包装在 GestureDetector 中。小部件并在 onHorizontalDragStart 中设置 PageView 的第二个 child 给定图 block 的回调函数。
我的问题:您如何在 Flutter 应用程序中动态(在运行时)创建或重新排序 PageView 小部件的子级?
PageView.builder 的 flutter 文档说:

PageView.builder by default does not support child reordering. If you are planning to change child order at a later time, consider using PageView or PageView.custom.


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

最佳答案

他们在 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);
    }
  }

关于android - 在 Flutter 的 PageView 中动态创建或重新排序子小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63107491/

相关文章:

java - 为什么使用 jarsigner 进行 apk 签名会给出 java.security.NoSuchAlgorithmException : SHA11 MessageDigest not available?

android - AdMob 广告未显示在模拟器中

ios - 在两个现有 View 层之间插入模糊层

ios - 避免像在 FMDatabaseQueue 中那样使用带有 block 方法的 __block 变量保留计数

android - 无法创建新的 flutter 项目

android - 在 TextView 上强制淡化边缘

iphone - 访问 iPhone 通讯录中的人员信息

android - 如何使用 Flutter 将 Braintree 集成到 iOS 或 Android 应用程序?

arrays - 如何将 Dart 列表中的所有字符串转换为小写?

java - Java 中比 double 更大的数据类型是什么?