mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 13:32:54 +08:00
feat(fullscreen): add fullscreen property to ion-content
This commit is contained in:
@ -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 {
|
||||||
|
@ -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>
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
it('should go to page and open child navs', function() {
|
|
||||||
element(by.css('.nested-children-test')).click();
|
|
||||||
});
|
|
@ -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');
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user