MOBILE-2430 tabs: Add tab sliding effect

main
Pau Ferrer Ocaña 2018-06-08 15:59:06 +02:00
parent eb36ee048c
commit 19269f36f9
4 changed files with 131 additions and 14 deletions

View File

@ -25,7 +25,7 @@
<!-- Content. -->
<core-loading [hideUntil]="loaded" class="core-loading-center">
<core-tabs [selectedIndex]="selectedTab">
<core-tabs [hideUntil]="loaded" [selectedIndex]="selectedTab">
<!-- Page contents. -->
<core-tab [title]="'addon.mod_wiki.viewpage' | translate" icon="document">
<ng-template>

View File

@ -1,14 +1,28 @@
<core-loading [hideUntil]="hideUntil" class="core-loading-center">
<div class="core-tabs-bar" #topTabs [hidden]="!tabs || tabs.length < 2">
<ng-container *ngFor="let tab of tabs; let idx = index">
<a *ngIf="tab.show" [attr.aria-selected]="selected == idx" (click)="selectTab(idx)">
<core-icon *ngIf="tab.icon" [name]="tab.icon"></core-icon>
<span *ngIf="tab.title">{{ tab.title }}</span>
<ion-badge *ngIf="tab.badge" [color]="tab.badgeStyle" class="tab-badge">{{tab.badge}}</ion-badge>
</a>
</ng-container>
<ion-row>
<ion-col class="col-with-arrow" (click)="slidePrev()" no-padding col-1>
<ion-icon *ngIf="showPrevButton" name="arrow-back"></ion-icon>
</ion-col>
<ion-col no-padding col-10>
<ion-slides (ionSlideDidChange)="slideChanged()" [slidesPerView]="slidesShown">
<ng-container *ngFor="let tab of tabs; let idx = index">
<ion-slide *ngIf="tab.show">
<a [attr.aria-selected]="selected == idx" (click)="selectTab(idx)" class="tab-slide">
<core-icon *ngIf="tab.icon" [name]="tab.icon"></core-icon>
<span *ngIf="tab.title">{{ tab.title }}</span>
<ion-badge *ngIf="tab.badge" [color]="tab.badgeStyle" class="tab-badge">{{tab.badge}}</ion-badge>
</a>
</ion-slide>
</ng-container>
</ion-slides>
</ion-col>
<ion-col class="col-with-arrow" (click)="slideNext()" no-padding col-1>
<ion-icon *ngIf="showNextButton" name="arrow-forward"></ion-icon>
</ion-col>
</ion-row>
</div>
<div class="core-tabs-content-container" #originalTabs>
<ng-content></ng-content>
</div>
</core-loading>
</core-loading>

View File

@ -6,7 +6,11 @@
width: 100%;
background: $core-top-tabs-background;
> a {
.row {
width: 100%;
}
a.tab-slide {
@extend .tab-button;
background: $core-top-tabs-background;
@ -20,9 +24,25 @@
border-bottom: 2px solid $core-top-tabs-color-active !important;
}
}
ion-col {
text-align: center;
font-size: 1.6rem;
line-height: 1.6rem;
&.col-with-arrow {
display: flex;
justify-content: center;
align-items: center;
ion-icon {
color: #ccc;
}
}
}
}
.md .core-tabs-bar > a {
.md .core-tabs-bar a.tab-slide {
// @extend .tabs-md .tab-button;
min-height: $tabs-md-tab-min-height;
@ -30,7 +50,7 @@
color: $tabs-md-tab-text-color;
}
.ios .core-tabs-bar > a {
.ios .core-tabs-bar a.tab-slide {
// @extend .tabs-ios .tab-button;
max-width: $tabs-ios-tab-max-width;
min-height: $tabs-ios-tab-min-height;
@ -40,7 +60,7 @@
color: $tabs-ios-tab-text-color;
}
.wp .core-tabs-bar > a {
.wp .core-tabs-bar a.tab-slide {
//@extend .tabs-wp .tab-button;
@include border-radius(0);

View File

@ -17,7 +17,7 @@ import {
SimpleChange
} from '@angular/core';
import { CoreTabComponent } from './tab';
import { Content } from 'ionic-angular';
import { Content, Slides } from 'ionic-angular';
/**
* This component displays some tabs that usually share data between them.
@ -48,9 +48,16 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges {
@Output() ionChange: EventEmitter<CoreTabComponent> = new EventEmitter<CoreTabComponent>(); // Emitted when the tab changes.
@ViewChild('originalTabs') originalTabsRef: ElementRef;
@ViewChild('topTabs') topTabs: ElementRef;
@ViewChild(Slides) slides: Slides;
tabs: CoreTabComponent[] = []; // List of tabs.
selected: number; // Selected tab number.
showPrevButton: boolean;
showNextButton: boolean;
maxSlides = 3;
slidesShown = this.maxSlides;
numTabsShown = 0;
protected originalTabsContainer: HTMLElement; // The container of the original tabs. It will include each tab's content.
protected initialized = false;
protected afterViewInitTriggered = false;
@ -77,10 +84,16 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges {
*/
ngAfterViewInit(): void {
this.afterViewInitTriggered = true;
if (!this.initialized && this.hideUntil) {
// Tabs should be shown, initialize them.
this.initializeTabs();
}
window.addEventListener('resize', () => {
this.calculateMaxSlides();
this.updateSlides();
});
}
/**
@ -107,6 +120,7 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges {
if (this.getIndex(tab) == -1) {
this.tabs.push(tab);
this.sortTabs();
this.updateSlides();
if (this.initialized && this.tabs.length > 1 && this.tabBarHeight == 0) {
// Calculate the tabBarHeight again now that there is more than 1 tab and the bar will be seen.
@ -190,9 +204,72 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges {
}
}
// Check which arrows should be shown
this.calculateMaxSlides();
this.updateSlides();
this.initialized = true;
}
/**
* Method executed when the slides are changed.
*/
slideChanged(): void {
const currentIndex = this.slides.getActiveIndex();
if (this.slidesShown >= this.numTabsShown) {
this.showPrevButton = false;
this.showNextButton = false;
} else if (typeof currentIndex !== 'undefined') {
this.showPrevButton = currentIndex > 0;
this.showNextButton = currentIndex < this.numTabsShown - this.slidesShown;
} else {
this.showPrevButton = false;
this.showNextButton = this.numTabsShown > this.slidesShown;
}
}
/**
* Update slides.
*/
protected updateSlides(): void {
this.numTabsShown = this.tabs.reduce((prev: number, current: any) => {
return current.show ? prev + 1 : prev;
}, 0);
this.slidesShown = Math.min(this.maxSlides, this.numTabsShown);
this.slides.update();
this.slides.resize();
this.slideChanged();
}
protected calculateMaxSlides(): void {
if (this.slides && this.slides.renderedWidth) {
this.maxSlides = Math.floor(this.slides.renderedWidth / 120);
return;
}
this.maxSlides = 3;
}
/**
* Method that shows the next slide.
*/
slideNext(): void {
if (this.showNextButton) {
this.slides.slideNext();
}
}
/**
* Method that shows the previous slide.
*/
slidePrev(): void {
if (this.showPrevButton) {
this.slides.slidePrev();
}
}
/**
* Show or hide the tabs. This is used when the user is scrolling inside a tab.
*
@ -221,6 +298,8 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges {
removeTab(tab: CoreTabComponent): void {
const index = this.getIndex(tab);
this.tabs.splice(index, 1);
this.updateSlides();
}
/**
@ -252,6 +331,10 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges {
currentTab.unselectTab();
}
if (this.selected) {
this.slides.slideTo(index);
}
this.selected = index;
newTab.selectTab();
this.ionChange.emit(newTab);