feat(nav): animate nested navs

This commit is contained in:
Adam Bradley
2015-10-30 23:31:23 -05:00
parent 25b672dabe
commit 1a865eaf7b
5 changed files with 67 additions and 47 deletions

View File

@ -184,7 +184,7 @@ export class NavController extends Ion {
if (opts.preCleanup !== false) { if (opts.preCleanup !== false) {
raf(() => { raf(() => {
this._cleanup(enteringView); this._cleanup(enteringView);
}); });
} }
if (this.router) { if (this.router) {
@ -286,7 +286,7 @@ export class NavController extends Ion {
let leavingView = this._views[this._views.length - 1]; let leavingView = this._views[this._views.length - 1];
let enteringView = view; let enteringView = view;
if(this.router) { if (this.router) {
this.router.stateChange('pop', enteringView); this.router.stateChange('pop', enteringView);
} }

View File

@ -4,6 +4,7 @@ import {IonicApp} from '../app/app';
import {Config} from '../../config/config'; import {Config} from '../../config/config';
import {ConfigComponent} from '../../config/decorators'; import {ConfigComponent} from '../../config/decorators';
import {NavController} from './nav-controller'; import {NavController} from './nav-controller';
import {ViewController} from './view-controller';
/** /**
* _For a quick walkthrough of navigation in Ionic, check out the * _For a quick walkthrough of navigation in Ionic, check out the
@ -59,25 +60,23 @@ import {NavController} from './nav-controller';
* <ion-nav> * <ion-nav>
* | * |
* | * |
* Pane 3 +--------------------+ LoginPage * Page 3 +--------------------+ LoginPage
* Pane 2 +--------------------+ | Has header, animates into pane 1 * Page 2 +--------------------+ |
* Pane 1 +--------------------+ | | +--------------------+ * Page 1 +--------------------+ | | +--------------------+
* | | Header (Pane 1) |<-----------------| Login | * | | Header |<-----------------| Login |
* +--------------------+ | | +--------------------+ * +--------------------+ | | +--------------------+
* | | | | | | | Username: | * | | | | | | | Username: |
* | | | | | | | Password: | * | | | | | | | Password: |
* | | | Pane 3 is | | | | | * | | | Page 3 is | | | | |
* | | | only content | | | | | * | | | only content | | | | |
* | | | |<-----------------| | * | | | |<-----------------| |
* | | | | | | | | * | | | | | | | |
* | | | | | | | | * | | | | | | | |
* | +------------------|-+ | | | * | +------------------|-+ | | |
* | | Footer (Pane 2)--|-|-+ | | * | | Footer |-|-+ | |
* | +------------------|-+ | | * | +------------------|-+ | |
* +--------------------+ +--------------------+ * +--------------------+ +--------------------+
* <ion-pane> <ion-view>
* *
* Pane 1 Pane 2 Pane 3
* +--------------------+ +--------------------+ +--------------------+ * +--------------------+ +--------------------+ +--------------------+
* | Header | | Content | | Content | * | Header | | Content | | Content |
* +--------------------+ | | | | * +--------------------+ | | | |
@ -96,31 +95,6 @@ import {NavController} from './nav-controller';
* </pre> * </pre>
* </div> * </div>
* *
* ### Panes
*
* NOTE: You don't have to do anything with panes because Ionic takes care of
* animated transitions for you. This is an explanation of how Nav works to
* accompany the diagram above.
*
* When you push a new page onto the navigation stack using [NavController.push()](../NavController/#push)
* or the [NavPush directive](../NavPush/), Nav animates the new page into the
* appropriate pane.
*
* Panes are the containers Nav creates to animate views into. They do not have
* any content of their own, as they are just a structural reference for where
* the various parts of a page (header, footer, content) should animate into.
*
* The easiest scenario is animating between pages with the same structure. If
* you have a page with a header and content, and navigate to another page that
* also has a header and content, Nav can smoothly animate the incoming page
* into the pane the exiting page is leaving. This allows for things like
* seamless header animations between pages that both have headers.
*
* But suppose you have a page with a header and content and want to navigate to
* a page with no header. Nav creates a new pane with no header that is directly
* behind the current pane. It then animates the exiting page out of the current
* pane and the new page into the new content-only pane.
*
*/ */
@ConfigComponent({ @ConfigComponent({
selector: 'ion-nav', selector: 'ion-nav',
@ -136,6 +110,7 @@ export class Nav extends NavController {
constructor( constructor(
@Optional() hostNavCtrl: NavController, @Optional() hostNavCtrl: NavController,
@Optional() viewCtrl: ViewController,
app: IonicApp, app: IonicApp,
config: Config, config: Config,
elementRef: ElementRef, elementRef: ElementRef,
@ -146,11 +121,15 @@ export class Nav extends NavController {
renderer: Renderer renderer: Renderer
) { ) {
super(hostNavCtrl, app, config, elementRef, compiler, loader, viewManager, zone, renderer); super(hostNavCtrl, app, config, elementRef, compiler, loader, viewManager, zone, renderer);
if (viewCtrl) {
// an ion-nav can also act as an ion-page within a parent ion-nav
// this would happen when an ion-nav nests a child ion-nav.
viewCtrl.setContent(this);
viewCtrl.setContentRef(elementRef);
}
} }
/**
* @private
*/
onInit() { onInit() {
super.onInit(); super.onInit();

View File

@ -24,7 +24,7 @@ export class Login {
} }
@Page({ @Page({
template: ` template: `
<ion-menu [content]="content"> <ion-menu [content]="content">
<ion-toolbar secondary> <ion-toolbar secondary>
@ -67,7 +67,7 @@ export class Account {
} }
logOut() { logOut() {
this.app.getComponent('root-nav').setRoot(Login); this.app.getComponent('root-nav').setRoot(Login, null, { animate: true });
} }
} }
@ -75,27 +75,63 @@ export class Account {
@Page({ @Page({
template: ` template: `
<ion-navbar *navbar primary> <ion-navbar *navbar primary>
<a menu-toggle>
<icon menu></icon>
</a>
<ion-title>Account Dashboard</ion-title> <ion-title>Account Dashboard</ion-title>
</ion-navbar> </ion-navbar>
<ion-content padding> <ion-content padding>
Dashboard <p><button (click)="goToProfile()">Profile</button></p>
<p><button (click)="logOut()">Logout</button></p>
</ion-content> </ion-content>
` `
}) })
export class Dashboard {} export class Dashboard {
constructor(app: IonicApp, nav: NavController) {
this.app = app;
this.nav = nav;
}
goToProfile() {
this.nav.push(Profile);
}
logOut() {
this.app.getComponent('root-nav').setRoot(Login, null, {
animate: true,
direction: 'back'
});
}
}
@Page({ @Page({
template: ` template: `
<ion-navbar *navbar danger> <ion-navbar *navbar danger>
<a menu-toggle>
<icon menu></icon>
</a>
<ion-title>Account Profile</ion-title> <ion-title>Account Profile</ion-title>
</ion-navbar> </ion-navbar>
<ion-content padding> <ion-content padding>
Profile <p><button (click)="goToDashboard()">Dashboard</button></p>
<p><button (click)="logOut()">Logout</button></p>
</ion-content> </ion-content>
` `
}) })
export class Profile {} export class Profile {
constructor(app: IonicApp, nav: NavController) {
this.app = app;
this.nav = nav;
}
goToDashboard() {
this.nav.push(Dashboard);
}
logOut() {
this.app.getComponent('root-nav').setRoot(Login, null, {
animate: true,
direction: 'back'
});
}
}
@App({ @App({

View File

@ -106,6 +106,9 @@ class IOSTransition extends Animation {
let enteringBackBtnText = new Animation(enteringView.backBtnTextRef()); let enteringBackBtnText = new Animation(enteringView.backBtnTextRef());
enteringBackBtnText.fromTo(TRANSLATEX, '100px', '0px'); enteringBackBtnText.fromTo(TRANSLATEX, '100px', '0px');
enteringNavBar.add(enteringBackBtnText); enteringNavBar.add(enteringBackBtnText);
} else {
enteringBackButton.before.removeClass(SHOW_BACK_BTN_CSS);
} }
} }
} }

View File

@ -39,11 +39,13 @@ class MDTransition extends Animation {
.fadeIn(); .fadeIn();
} }
// entering navbar let enteringBackButton = new Animation(enteringView.backBtnRef());
this.add(enteringBackButton);
if (enteringHasNavbar && enteringView.enableBack()) { if (enteringHasNavbar && enteringView.enableBack()) {
let enteringBackButton = new Animation(enteringView.backBtnRef());
enteringBackButton.before.addClass(SHOW_BACK_BTN_CSS); enteringBackButton.before.addClass(SHOW_BACK_BTN_CSS);
this.add(enteringBackButton);
} else {
enteringBackButton.before.removeClass(SHOW_BACK_BTN_CSS);
} }
// setup leaving view // setup leaving view