2

我想要的是:

我的场景分为两部分:按钮栏和内容。我想要类似于 Android ViewPager 行为的东西:当我点击一个按钮时,相应的场景会从左侧或右侧滑入,具体取决于按钮栏中的按钮位置:

 ______________________________
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|______________________________|
|          |          |        |
| Discover | TV Shows | Movies |
|__________|__________|________|

例如,当从Discover导航到TV Shows时,TV Shows场景应该从右侧滑动,同时Discover场景应该向左移动。

请注意,中间项目TV Shows可以有不同的过渡,这取决于我们来自哪里:

  • DiscoverTV Shows --> TV Shows场景应该来自右边
  • 电影电视节目-->电视节目场景应该来自左边

我做了什么:

我创建了自己的 PageRoute,并在其中覆盖了该buildTransitions方法。我有一点逻辑来确定幻灯片动画的方向:

import 'package:flutter/material.dart';

class CustomPageRoute<T> extends MaterialPageRoute<T> {
  final String currentTab;
  final String newTab;
  final Widget child;

  CustomPageRoute(this.currentTab, this.newTab, this.child) : super(builder: (BuildContext context) => child);

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    if (currentTab == null) {
      // First scene of the Navigator, use the theme (FadeTransition)
      return super.buildTransitions(context, animation, secondaryAnimation, child);
    }

    Offset startPosition;
    switch ('$currentTab-->$newTab') {
      case '/-->/tvshow':
      case '/-->/movie':
      case '/tvshow-->/movie':
        // If the button is on the right in the tab bar, the scene will come from the right
        startPosition = Offset(1.0, 0.0);
        break;
      case '/tvshow-->/':
      case '/movie-->/':
      case '/movie-->/tvshow':
        // If the button is on the left in the tab bar, the scene will come from the left
        startPosition = Offset(-1.0, 0.0);
        break;
      default:
        startPosition = Offset.zero;
    }

    return SlideTransition(
      position: Tween<Offset>(
        begin: startPosition,
        end: Offset.zero,
      ).animate(animation),
      child: child,
    );
  }
}

onGenerateRoute我的用法Navigator

onGenerateRoute: (RouteSettings settings) {
  Widget widget;

  switch (settings.name) {
    case '/':
      widget = DiscoverTab();
      break;
    case '/tvshow':
      widget = TvShowTab();
      break;
    case '/movie':
      widget = MovieTab();
      break;
    default:
      throw Exception('Invalid route: ${settings.name}');
  }

  CustomPageRoute route = CustomPageRoute(this.lastRoute, settings.name, widget);
  // Save the route for the next one
  this.lastRoute = settings.name;

  return route;
}

问题:

传入场景来自正确的一侧(从左到右),但传出场景保持原位。所以传入的场景正在“覆盖”传出的场景。

外观和感觉还不错,但它不是理想的结果:

我希望传出场景以相反的方向移出屏幕,以便像真正的滑块一样将位置留给传入场景。因此,我还必须通过参数为即将传出的场景设置动画secondaryAnimation

我可以编写 2 个动画,如下所示:

SlideTransition(
  position: new Tween<Offset>(
    begin: Offset(1.0, 0.0),
    end: Offset.zero,
  ).animate(animation), // Incoming scene from right
  child: new SlideTransition(
    position: new Tween<Offset>(
      begin: Offset.zero,
      end: Offset(-1.0, 0.0),
    ).animate(secondaryAnimation), // Outgoing scene to the left
    child: child,
  ),
);

除了中间电视节目场景外,它将工作,因为它可以根据下一条路线有 2 种不同的过渡:在路线创建时方向未知。只有在创建下一条路线时才能知道。

所以我的问题是:在创建新路由时,是否可以访问当前路由的传出转换定义并重新定义它?

我最好的线索是TransitionRoute类中_updateSecondaryAnimation调用的方法,但我不知道如何使用它。didChangeNext

4

0 回答 0