From 0eaa5b4183782743b2ad6632f9597921bb9ad0a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Wed, 13 Jun 2018 16:48:48 +0200 Subject: [PATCH] MOBILE-2430 navigation: Fix transitions --- src/app/app.module.ts | 10 ++- src/classes/page-transition.ts | 143 +++++++++++++++++++++++++++++++++ src/components/tabs/tabs.scss | 2 +- 3 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 src/classes/page-transition.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8737ec72f..8728449ec 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -15,7 +15,7 @@ import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { NgModule, COMPILER_OPTIONS } from '@angular/core'; -import { IonicApp, IonicModule, Platform, Content, ScrollEvent } from 'ionic-angular'; +import { IonicApp, IonicModule, Platform, Content, ScrollEvent, Config } from 'ionic-angular'; import { assert } from 'ionic-angular/util/util'; import { HttpModule } from '@angular/http'; import { HttpClient, HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; @@ -26,6 +26,7 @@ import { TranslateHttpLoader } from '@ngx-translate/http-loader'; import { MoodleMobileApp } from './app.component'; import { CoreInterceptor } from '@classes/interceptor'; +import { CorePageTransition } from '@classes/page-transition'; import { CoreLoggerProvider } from '@providers/logger'; import { CoreDbProvider } from '@providers/db'; import { CoreAppProvider } from '@providers/app'; @@ -153,7 +154,7 @@ export const CORE_PROVIDERS: any[] = [ HttpClientModule, // HttpClient is used to make JSON requests. It fails for HEAD requests because there is no content. HttpModule, IonicModule.forRoot(MoodleMobileApp, { - pageTransition: 'ios-transition' + pageTransition: 'core-page-transition' }), TranslateModule.forRoot({ loader: { @@ -255,7 +256,7 @@ export const CORE_PROVIDERS: any[] = [ ] }) export class AppModule { - constructor(platform: Platform, initDelegate: CoreInitDelegate, updateManager: CoreUpdateManagerProvider, + constructor(platform: Platform, initDelegate: CoreInitDelegate, updateManager: CoreUpdateManagerProvider, config: Config, sitesProvider: CoreSitesProvider, fileProvider: CoreFileProvider) { // Register a handler for platform ready. initDelegate.registerProcess({ @@ -287,6 +288,9 @@ export class AppModule { // Execute the init processes. initDelegate.executeInitProcesses(); + // Set transition animation. + config.setTransition('core-page-transition', CorePageTransition); + // Decorate ion-content. this.decorateIonContent(); } diff --git a/src/classes/page-transition.ts b/src/classes/page-transition.ts new file mode 100644 index 000000000..575e08c1e --- /dev/null +++ b/src/classes/page-transition.ts @@ -0,0 +1,143 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Animation } from 'ionic-angular/animations/animation'; +import { isPresent } from 'ionic-angular/util/util'; +import { PageTransition } from 'ionic-angular/transitions/page-transition'; + +const DURATION = 500; +const EASING = 'cubic-bezier(0.36,0.66,0.04,1)'; +const OPACITY = 'opacity'; +const TRANSFORM = 'transform'; +const TRANSLATEX = 'translateX'; +const CENTER = '0%'; +const OFF_OPACITY = 0.8; +const SHOW_BACK_BTN_CSS = 'show-back-button'; + +/** + * This class overrides the default transition to avoid glitches with new tabs and split view. + * Is based on IOSTransition class but it has some changes: + * - The animation is done to the full page not header, footer and content separetely. + * - On the Navbar only the back button is animated (title and other buttons will be done as a whole). Otherwise back button won't + * appear. + */ +export class CorePageTransition extends PageTransition { + init(): void { + super.init(); + const plt = this.plt; + const OFF_RIGHT = plt.isRTL ? '-99.5%' : '99.5%'; + const OFF_LEFT = plt.isRTL ? '33%' : '-33%'; + const enteringView = this.enteringView; + const leavingView = this.leavingView; + const opts = this.opts; + this.duration(isPresent(opts.duration) ? opts.duration : DURATION); + this.easing(isPresent(opts.easing) ? opts.easing : EASING); + const backDirection = (opts.direction === 'back'); + const enteringHasNavbar = (enteringView && enteringView.hasNavbar()); + const leavingHasNavbar = (leavingView && leavingView.hasNavbar()); + if (enteringView) { + // Get the native element for the entering page. + const enteringPageEle = enteringView.pageRef().nativeElement; + // Entering content. + const enteringContent = new Animation(plt, enteringPageEle); + this.add(enteringContent); + if (backDirection) { + // Entering content, back direction. + enteringContent + .fromTo(TRANSLATEX, OFF_LEFT, CENTER, true) + .fromTo(OPACITY, OFF_OPACITY, 1, true); + } + else { + // Entering content, forward direction. + enteringContent + .beforeClearStyles([OPACITY]) + .fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true); + } + if (enteringHasNavbar) { + // Entering page has a navbar. + const enteringNavbarEle = enteringPageEle.querySelector('ion-navbar'); + const enteringNavBar = new Animation(plt, enteringNavbarEle); + this.add(enteringNavBar); + const enteringBackButton = new Animation(plt, enteringNavbarEle.querySelector('.back-button')); + enteringNavBar + .add(enteringBackButton); + // Set properties depending on direction. + if (backDirection) { + // Entering navbar, back direction. + if (enteringView.enableBack()) { + // Back direction, entering page has a back button. + enteringBackButton + .beforeAddClass(SHOW_BACK_BTN_CSS) + .fromTo(OPACITY, 0.01, 1, true); + } + } + else { + // Entering navbar, forward direction. + if (enteringView.enableBack()) { + // Forward direction, entering page has a back button. + enteringBackButton + .beforeAddClass(SHOW_BACK_BTN_CSS) + .fromTo(OPACITY, 0.01, 1, true); + const enteringBackBtnText = new Animation(plt, enteringNavbarEle.querySelector('.back-button-text')); + enteringBackBtnText.fromTo(TRANSLATEX, (plt.isRTL ? '-100px' : '100px'), '0px'); + enteringNavBar.add(enteringBackBtnText); + } + else { + enteringBackButton.beforeRemoveClass(SHOW_BACK_BTN_CSS); + } + } + } + } + // Setup leaving view. + if (leavingView && leavingView.pageRef()) { + // Leaving content. + const leavingPageEle = leavingView.pageRef().nativeElement; + const leavingContent = new Animation(plt, leavingPageEle); + this.add(leavingContent); + if (backDirection) { + // Leaving content, back direction. + leavingContent + .beforeClearStyles([OPACITY]) + .fromTo(TRANSLATEX, CENTER, (plt.isRTL ? '-100%' : '100%')); + } + else { + // Leaving content, forward direction. + leavingContent + .fromTo(TRANSLATEX, CENTER, OFF_LEFT) + .fromTo(OPACITY, 1, OFF_OPACITY) + .afterClearStyles([TRANSFORM, OPACITY]); + } + if (leavingHasNavbar) { + // Leaving page has a navbar. + const leavingNavbarEle = leavingPageEle.querySelector('ion-navbar'); + const leavingNavBar = new Animation(plt, leavingNavbarEle); + const leavingBackButton = new Animation(plt, leavingNavbarEle.querySelector('.back-button')); + leavingNavBar + .add(leavingBackButton); + this.add(leavingNavBar); + // Fade out leaving navbar items. + leavingBackButton.fromTo(OPACITY, 0.99, 0); + if (backDirection) { + const leavingBackBtnText = new Animation(plt, leavingNavbarEle.querySelector('.back-button-text')); + leavingBackBtnText.fromTo(TRANSLATEX, CENTER, (plt.isRTL ? -300 : 300) + 'px'); + leavingNavBar.add(leavingBackBtnText); + } + else { + // Leaving navbar, forward direction. + leavingBackButton.afterClearStyles([OPACITY]); + } + } + } + } +} diff --git a/src/components/tabs/tabs.scss b/src/components/tabs/tabs.scss index 429f386d5..b7e7618b1 100644 --- a/src/components/tabs/tabs.scss +++ b/src/components/tabs/tabs.scss @@ -55,7 +55,7 @@ max-width: $tabs-ios-tab-max-width; min-height: $tabs-ios-tab-min-height; - font-size: $tabs-ios-tab-font-size; + font-size: $tabs-ios-tab-font-size + 4; font-weight: $tabs-ios-tab-font-weight; color: $tabs-ios-tab-text-color; }