如何让ListView在转换到另一个路线时保留其滚动?

2024-04-04

我想在我的颤动应用程序中完成滑动到右侧的转换。 问题是路线转换有点创建我想要从中转换的页面的新实例,所以ListView滚动重置。

看视频 https://youtu.be/-PdLhyvNoU8

这就是我创建新路线的方式

/// @oldRoute needed cause this route transition utilizes `SlideStackRightRoute`
Route createSettingsRoute(Widget oldRoute) {
  return SlideStackRightRoute(exitPage: oldRoute, enterPage: SettingsRoute());
}

最后是幻灯片过渡类本身

import 'package:flutter/material.dart';

/// Creates cupertino-like route transition, where new route pushes old from right to left
class SlideStackRightRoute extends PageRouteBuilder {
  final Widget enterPage;
  final Widget exitPage;
  static var exBegin = Offset(0.0, 0.0);
  static var exEnd = Offset(-0.5, 0.0);
  static var entBegin = Offset(1.0, 0.0);
  static var entEnd = Offset.zero;
  static var curveIn = Curves.easeOutSine;
  static var curveOut = Curves.easeInSine;

  SlideStackRightRoute({@required this.exitPage, @required this.enterPage})
      : super(
          transitionDuration: Duration(milliseconds: 400),
          pageBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
          ) =>
              enterPage,
          transitionsBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
            Widget child,
          ) =>
              Stack(
            children: <Widget>[
              SlideTransition(
                position: Tween(begin: exBegin, end: exEnd)
                    .chain(CurveTween(curve: curveIn))
                    .chain(CurveTween(curve: curveOut))
                    .animate(animation),
                child: Container(
                    foregroundDecoration: BoxDecoration(
                      color: Colors.black.withOpacity(animation.value / 2),
                    ),
                    child: exitPage),
              ),
              SlideTransition(
                position: Tween(begin: entBegin, end: entEnd)
                    .chain(CurveTween(curve: curveIn))
                    .chain(CurveTween(curve: curveOut))
                    .animate(animation),
                child: enterPage,
              )
            ],
          ),
        );
}


我在问题中创建“滑出”动画的方式不正确。就框架而言,它被称为secondaryAnimation

要创建您自己的辅助动画,您需要使用PageRouteBuilder 过渡构建器 https://api.flutter.dev/flutter/widgets/PageRouteBuilder/transitionsBuilder.html财产

下面的代码可以产生这样的动画,并且 ListView 没有问题

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primaryColor: Colors.white),
      initialRoute: '/',
      onGenerateInitialRoutes: (initialRoute) => [createCustomTransition(HomeScreen())],
      onGenerateRoute: (settings) {
        if (settings.name == '1') {
          return createCustomTransition(SomeScreen());
        }
        return createCustomTransition(OtherScreen());
      },
      debugShowCheckedModeBanner: false,
    );
  }
}

/// Will create a custom route transition for you. 
PageRouteBuilder createCustomTransition(Widget screen) {
  return PageRouteBuilder(
    transitionDuration: const Duration(milliseconds: 700),
    reverseTransitionDuration: const Duration(milliseconds: 700),
    pageBuilder: (context, animation, secondaryAnimation) => screen,
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      
      final slideAnimation = Tween(
        begin: const Offset(1.0, 0.0),
        end: Offset.zero,
      ).animate(CurvedAnimation(
        curve: Curves.easeOutCubic,
        reverseCurve: Curves.easeInCubic,
        parent: animation,
      ));

      final slideOutAnimation = Tween(
        begin: Offset.zero,
        end: const Offset(-0.3, 0.0),
      ).animate(CurvedAnimation(
        curve: Curves.easeOutCubic,
        reverseCurve: Curves.easeInCubic,
        parent: secondaryAnimation,
      ));

      return SlideTransition(
        position: slideAnimation,
        child: SlideTransition(
          position: slideOutAnimation,
          child: child,
        ),
      );
    },
  );
}

class HomeScreen extends StatelessWidget {
  HomeScreen({Key key}) : super(key: key);
  final List<int> list = List.generate(1000, (index) => index);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            Expanded(
              child: ListView.builder(
                itemCount: list.length,
                itemBuilder: (context, index) => ListTile(
                  title: Center(
                    child: Text(list[index].toString()),
                  )
                ),
              )
            ),
            ElevatedButton(
              child: const Text('go to some screen'),
              onPressed: () {
                Navigator.of(context).pushNamed('1');
              },
            ),
          ],
        ),
      ),
    );
  }
}
class SomeScreen extends StatelessWidget {
  const SomeScreen({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.red,
      appBar: AppBar(),
      body: Center(
        child: ElevatedButton(
          child: const Text('go to other screen'),
          onPressed: () {
            Navigator.of(context).pushNamed('');
          },
        ),
      ),
    );
  }
}

class OtherScreen extends StatelessWidget {
  const OtherScreen({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blue,
      appBar: AppBar(),
    );
  }
}

根据文档PageRouteBuilder is

一种实用程序类,用于根据回调定义一次性页面路由。

它非常适合一般用途,但如果您正在构建更复杂的东西,我建议看一下一些框架页面路由动画实现以及它们具有的不同类关系

  • 小部件/page_transitions_theme.dart https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/page_transitions_theme.dart- 各种页面路由构建器
  • 材料/路线 https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/page.dart- Android 路线实施
  • 库比蒂诺/路线 https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/cupertino/route.dart- 铜管路线实施
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让ListView在转换到另一个路线时保留其滚动? 的相关文章