ntaoo blog

主にDart, Flutter, AngularDartについて書いていきます。ときどき長文。日本語のみ。Twitter: @ntaoo

AngularDart - UI Componentのアニメーションを維持したままページ遷移する

やりたいことは以下の動画のとおり。

f:id:ntaoo:20181018064021g:plain

ページ遷移してURLは変わるが、アニメーションは維持する。

モチベーション

Routerでページ遷移すると、対応するComponentが新たに起動する。しかし、上記の動画のように、たとえばTabの遷移に合わせてURLを変更したい場合、Component instanceが新たに起動して状態が一新されると、UI上はアニメーションがぶつりと中断してしまい不格好なUIになってしまう。アニメーションを維持したままページ遷移したい。

ソリューション

Tab1 page, Tab2 pageに対応するpathに紐つけるPageのComponentを、同一のものにする。ここでは、ATabCyclePageとする。 そして、Routerのlife cycle interfaceであるCanReuseを、Componentにimplementする。CanReuseは、Component instanceを再利用するかどうかを指定する。

class ATabCyclePage implements OnActivate, CanReuse {

  int activeTabIndex;

  @override
  void onActivate(RouterState previous, RouterState current) {
    activeTabIndex = _isTab1Page(current.path) ? 0 : 1;
  }

  @override
  Future<bool> canReuse(RouterState current, RouterState next) async {
    // Componentを再利用する条件を記述。たとえばcurrentとnextのpathを比較してUIのTab遷移に対応する状態ならばtrueを返す。
  }
}

Templateのサンプル

<material-tab-panel class="tab-panel" [activeTabIndex]="activeTabIndex" (tabChange)="handleTabChange($event)">
  <material-tab label="Tab 1">
    <template deferredContent>
      <ng-container *ngIf="activeTabIndex != null">
        <material-button raised (trigger)="navigateToTab2Page()">click to Tab 2</material-button>
      </ng-container>
    </template>
  </material-tab>
  <material-tab label="Tab 2">
    <template deferredContent>
      <!--Tab 2 Page-->
    </template>
  </material-tab>
</material-tab-panel>

Tabが変わった際のハンドラ

  void handleTabChange(TabChangeEvent event) {
    if (event.newIndex == 0) {
      _navigateToTab1Page();
    } else if (event.newIndex == 1) {
      navigateToTab2Page();
    } else {
      // throw
    }
  }

  void _navigateToTab1Page() => _router.navigate(RoutePaths.tab1
      .toUrl(parameters: {'id': _router.current.parameters['id']}));
  void navigateToTab2Page() => _router.navigate(RoutePaths.tab2
      .toUrl(parameters: {'id': _router.current.parameters['id']}));

これで、アニメーションを維持したままページ遷移が可能となった。

f:id:ntaoo:20181018064021g:plain