feat(fullscreen): add fullscreen property to ion-content

This commit is contained in:
Adam Bradley
2016-06-21 11:22:01 -05:00
parent 7842991c1a
commit f20c7e42a2
4 changed files with 94 additions and 44 deletions

View File

@ -1,4 +1,4 @@
import {Component, ElementRef, Optional, NgZone, ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core'; import {ChangeDetectionStrategy, Component, ElementRef, Input, NgZone, Optional, ViewEncapsulation} from '@angular/core';
import {App} from '../app/app'; import {App} from '../app/app';
import {Ion} from '../ion'; import {Ion} from '../ion';
@ -8,6 +8,7 @@ import {nativeRaf, nativeTimeout, transitionEnd} from '../../util/dom';
import {ScrollView} from '../../util/scroll-view'; import {ScrollView} from '../../util/scroll-view';
import {Tabs} from '../tabs/tabs'; import {Tabs} from '../tabs/tabs';
import {ViewController} from '../nav/view-controller'; import {ViewController} from '../nav/view-controller';
import {isTrueProperty} from '../../util/util';
/** /**
@ -59,19 +60,23 @@ import {ViewController} from '../nav/view-controller';
} }
}) })
export class Content extends Ion { export class Content extends Ion {
private _computedTop: number;
private _computedBottom: number;
private _paddingTop: number; private _paddingTop: number;
private _paddingRight: number;
private _paddingBottom: number; private _paddingBottom: number;
private _paddingLeft: number;
private _lastTop: number;
private _lastBottom: number;
private _scrollPadding: number; private _scrollPadding: number;
private _headerHeight: number; private _headerHeight: number;
private _footerHeight: number; private _footerHeight: number;
private _tabbarOnTop: boolean = null; private _tabbarHeight: number;
private _tabbarPlacement: string;
private _inputPolling: boolean = false; private _inputPolling: boolean = false;
private _scroll: ScrollView; private _scroll: ScrollView;
private _scLsn: Function; private _scLsn: Function;
private _scrollEle: HTMLElement; private _scrollEle: HTMLElement;
private _sbPadding: boolean; private _sbPadding: boolean;
private _fullscreen: boolean;
constructor( constructor(
private _elementRef: ElementRef, private _elementRef: ElementRef,
@ -322,6 +327,22 @@ export class Content extends Ion {
this.getNativeElement().classList.add(className); this.getNativeElement().classList.add(className);
} }
/**
* @input {boolean} By default, content is positioned between the headers
* and footers. However, using `fullscreen="true"`, the content will be
* able to scroll "under" the headers and footers. At first glance the
* fullscreen option may not look any different than the default, however,
* by adding a transparency effect to a header then the content can be
* seen under the header as the user scrolls.
*/
@Input()
get fullscreen(): boolean {
return !!this._fullscreen;
}
set fullscreen(val: boolean) {
this._fullscreen = isTrueProperty(val);
}
/** /**
* @private * @private
* DOM WRITE * DOM WRITE
@ -414,13 +435,12 @@ export class Content extends Ion {
* DOM READ * DOM READ
*/ */
readDimensions() { readDimensions() {
this._computedTop = 0 ;
this._computedBottom = 0;
this._paddingTop = 0; this._paddingTop = 0;
this._paddingRight = 0;
this._paddingBottom = 0; this._paddingBottom = 0;
this._paddingLeft = 0;
this._headerHeight = 0; this._headerHeight = 0;
this._footerHeight = 0; this._tabbarPlacement = null;
this._tabbarOnTop = null;
let ele: HTMLElement = this._elementRef.nativeElement; let ele: HTMLElement = this._elementRef.nativeElement;
let parentEle: HTMLElement = ele.parentElement; let parentEle: HTMLElement = ele.parentElement;
@ -430,43 +450,34 @@ export class Content extends Ion {
ele = <HTMLElement>parentEle.children[i]; ele = <HTMLElement>parentEle.children[i];
if (ele.tagName === 'ION-CONTENT') { if (ele.tagName === 'ION-CONTENT') {
computedStyle = getComputedStyle(ele); if (this._fullscreen) {
this._computedTop = parsePxUnit(computedStyle.paddingTop); computedStyle = getComputedStyle(ele);
this._paddingTop += this._computedTop; this._paddingTop = parsePxUnit(computedStyle.paddingTop);
this._paddingBottom = parsePxUnit(computedStyle.paddingBottom);
this._computedBottom = parsePxUnit(computedStyle.paddingBottom); this._paddingRight = parsePxUnit(computedStyle.paddingRight);
this._paddingBottom += this._computedBottom; this._paddingLeft = parsePxUnit(computedStyle.paddingLeft);
}
} else if (ele.tagName === 'ION-HEADER') { } else if (ele.tagName === 'ION-HEADER') {
this._headerHeight = ele.clientHeight; this._headerHeight = ele.clientHeight;
this._paddingTop += this._headerHeight;
} else if (ele.tagName === 'ION-FOOTER') { } else if (ele.tagName === 'ION-FOOTER') {
this._footerHeight = ele.clientHeight; this._footerHeight = ele.clientHeight;
this._paddingBottom += this._footerHeight;
} }
} }
ele = parentEle; ele = parentEle;
let tabbarEle: HTMLElement; let tabbarEle: HTMLElement;
let tabbarOnTop: boolean;
while (ele && ele.tagName !== 'ION-MODAL' && !ele.classList.contains('tab-subpage')) { while (ele && ele.tagName !== 'ION-MODAL' && !ele.classList.contains('tab-subpage')) {
if (ele.tagName === 'ION-TABS') { if (ele.tagName === 'ION-TABS') {
tabbarEle = <HTMLElement>ele.firstElementChild; tabbarEle = <HTMLElement>ele.firstElementChild;
tabbarOnTop = ele.getAttribute('tabbarplacement') === 'top'; this._tabbarHeight = tabbarEle.clientHeight;
if (tabbarOnTop) { if (this._tabbarPlacement === null) {
this._paddingTop += tabbarEle.clientHeight;
} else {
this._paddingBottom += tabbarEle.clientHeight;
}
if (this._tabbarOnTop === null) {
// this is the first tabbar found, remember it's position // this is the first tabbar found, remember it's position
this._tabbarOnTop = tabbarOnTop; this._tabbarPlacement = ele.getAttribute('tabbarplacement');
} }
} }
@ -479,18 +490,54 @@ export class Content extends Ion {
* DOM WRITE * DOM WRITE
*/ */
writeDimensions() { writeDimensions() {
// only add inline padding styles if the computed padding value, which would let newVal: number;
// have come from the app's css, is different than the new padding value
if (this._paddingTop !== this._computedTop) { // only write when it has changed
this._scrollEle.style.paddingTop = (this._paddingTop > 0 ? this._paddingTop + 'px' : ''); if (this._fullscreen) {
// adjust the content with padding, allowing content to scroll under headers/footers
// however, on iOS you cannot control the margins of the scrollbar (last tested iOS9.2)
// only add inline padding styles if the computed padding value, which would
// have come from the app's css, is different than the new padding value
newVal = this._headerHeight + this._paddingTop;
if (this._tabbarPlacement === 'top') {
newVal += this._tabbarHeight;
}
if (newVal !== this._lastTop) {
this._scrollEle.style.paddingTop = (newVal > 0 ? newVal + 'px' : '');
}
newVal = this._footerHeight + this._paddingBottom;
if (this._tabbarPlacement === 'bottom') {
newVal += this._tabbarHeight;
}
if (newVal !== this._lastBottom) {
this._scrollEle.style.paddingBottom = (newVal > 0 ? newVal + 'px' : '');
}
} else {
// adjust the content with margins
newVal = this._headerHeight;
if (this._tabbarPlacement === 'top') {
newVal += this._tabbarHeight;
}
if (newVal !== this._lastTop) {
this._scrollEle.style.marginTop = (newVal > 0 ? newVal + 'px' : '');
}
newVal = this._footerHeight;
if (this._tabbarPlacement === 'bottom') {
newVal += this._tabbarHeight;
}
if (newVal !== this._lastBottom) {
this._scrollEle.style.marginBottom = (newVal > 0 ? newVal + 'px' : '');
}
} }
if (this._paddingBottom !== this._computedBottom) {
this._scrollEle.style.paddingBottom = (this._paddingBottom > 0 ? this._paddingBottom + 'px' : '');
}
if (this._tabbarOnTop !== null && this._tabs) { if (this._tabbarPlacement !== null && this._tabs) {
if (this._tabbarOnTop) { // set the position of the tabbar
if (this._tabbarPlacement === 'top') {
this._tabs.setTabbarPosition(this._headerHeight, -1); this._tabs.setTabbarPosition(this._headerHeight, -1);
} else { } else {

View File

@ -214,7 +214,7 @@ class FullPage {
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-content padding> <ion-content padding fullscreen>
<p><button class="e2eFrom3To2" (click)="nav.pop()">Pop</button></p> <p><button class="e2eFrom3To2" (click)="nav.pop()">Pop</button></p>
<p><button (click)="pushAnother()">Push to AnotherPage</button></p> <p><button (click)="pushAnother()">Push to AnotherPage</button></p>
<p><button (click)="pushFullPage()">Push to FullPage</button></p> <p><button (click)="pushFullPage()">Push to FullPage</button></p>

View File

@ -1,3 +0,0 @@
it('should go to page and open child navs', function() {
element(by.css('.nested-children-test')).click();
});

View File

@ -158,6 +158,8 @@ export class Tabs extends Ion {
private _onReady: any = null; private _onReady: any = null;
private _sbPadding: boolean; private _sbPadding: boolean;
private _useHighlight: boolean; private _useHighlight: boolean;
private _top: number;
private _bottom: number;
/** /**
* @private * @private
@ -518,11 +520,15 @@ export class Tabs extends Ion {
* DOM WRITE * DOM WRITE
*/ */
setTabbarPosition(top: number, bottom: number) { setTabbarPosition(top: number, bottom: number) {
let tabbarEle = <HTMLElement>this._tabbar.nativeElement; if (this._top !== top || this._bottom !== bottom) {
let tabbarEle = <HTMLElement>this._tabbar.nativeElement;
tabbarEle.style.top = (top > -1 ? top + 'px' : '');
tabbarEle.style.bottom = (bottom > -1 ? bottom + 'px' : '');
tabbarEle.classList.add('show-tabbar');
tabbarEle.style.top = (top > -1 ? top + 'px' : ''); this._top = top;
tabbarEle.style.bottom = (bottom > -1 ? bottom + 'px' : ''); this._bottom = bottom;
tabbarEle.classList.add('show-tabbar'); }
} }
} }