mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 03:32:21 +08:00
betterz iOS toolbars
This commit is contained in:
@ -18,6 +18,12 @@ export class Animation {
|
|||||||
|
|
||||||
this.children = [];
|
this.children = [];
|
||||||
|
|
||||||
|
this._addStartClasses = [];
|
||||||
|
this._removeStartClasses = [];
|
||||||
|
|
||||||
|
this._addEndClasses = [];
|
||||||
|
this._removeEndClasses = [];
|
||||||
|
|
||||||
this.elements(ele);
|
this.elements(ele);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +59,7 @@ export class Animation {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
_setupElements(clearCache, onNextFrame) {
|
_prepare(clearCache, onNextFrame) {
|
||||||
|
|
||||||
// ensure another animation wasnt about to start
|
// ensure another animation wasnt about to start
|
||||||
if (this._nextAF) {
|
if (this._nextAF) {
|
||||||
@ -105,7 +111,7 @@ export class Animation {
|
|||||||
this._options = util.extend(opts, this._options);
|
this._options = util.extend(opts, this._options);
|
||||||
|
|
||||||
// get the elements ready
|
// get the elements ready
|
||||||
for (var i = 0, ii = this._ele.length; i < ii; i++) {
|
for (let i = 0, ii = this._ele.length; i < ii; i++) {
|
||||||
processElement('start', this, i, clearCache);
|
processElement('start', this, i, clearCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +124,7 @@ export class Animation {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
_queueAnimation() {
|
_queue() {
|
||||||
if (this._ele.length) {
|
if (this._ele.length) {
|
||||||
|
|
||||||
if (this._call === null) {
|
if (this._call === null) {
|
||||||
@ -173,9 +179,9 @@ export class Animation {
|
|||||||
|
|
||||||
var clearCache = (this._aniType !== 'start');
|
var clearCache = (this._aniType !== 'start');
|
||||||
|
|
||||||
var promise = this._setupElements(clearCache, () => {
|
var promise = this._prepare(clearCache, () => {
|
||||||
this._aniType = 'start';
|
this._aniType = 'start';
|
||||||
this._queueAnimation();
|
this._queue();
|
||||||
});
|
});
|
||||||
|
|
||||||
promises.push(promise);
|
promises.push(promise);
|
||||||
@ -193,7 +199,7 @@ export class Animation {
|
|||||||
|
|
||||||
var clearCache = (this._aniType !== 'progress');
|
var clearCache = (this._aniType !== 'progress');
|
||||||
|
|
||||||
var promise = this._setupElements(clearCache, () => {
|
var promise = this._prepare(clearCache, () => {
|
||||||
this._aniType = 'progress';
|
this._aniType = 'progress';
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -212,7 +218,7 @@ export class Animation {
|
|||||||
this.children[i].progress(value);
|
this.children[i].progress(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._queueAnimation();
|
this._queue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +234,26 @@ export class Animation {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addStartClass(className) {
|
||||||
|
this._addStartClasses.push(className);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeStartClass(className) {
|
||||||
|
this._removeStartClasses.push(className);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addEndClass(className) {
|
||||||
|
this._addEndClasses.push(className);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeEndClass(className) {
|
||||||
|
this._removeEndClasses.push(className);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
isAnimating() {
|
isAnimating() {
|
||||||
var eleData;
|
var eleData;
|
||||||
if (this._ele) {
|
if (this._ele) {
|
||||||
|
@ -79,8 +79,15 @@ export let Collide = {
|
|||||||
rootPropertyValueCache: {},
|
rootPropertyValueCache: {},
|
||||||
|
|
||||||
/* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */
|
/* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */
|
||||||
transformCache: {}
|
transformCache: {},
|
||||||
|
|
||||||
|
startAddCls: null,
|
||||||
|
startRmvCls: null,
|
||||||
|
endAddCls: null,
|
||||||
|
endRmvCls: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return element.$collide;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* get/set element data */
|
/* get/set element data */
|
||||||
|
@ -46,6 +46,20 @@ export function completeCall(callIndex, isStopped) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eleData.endAddCls) {
|
||||||
|
for (var k = 0; k < eleData.endAddCls.length; k++) {
|
||||||
|
element.classList.add(eleData.endAddCls[k]);
|
||||||
|
}
|
||||||
|
eleData.endAddCls = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eleData.endRmvCls) {
|
||||||
|
for (var k = 0; k < eleData.endRmvCls.length; k++) {
|
||||||
|
element.classList.remove(eleData.endRmvCls[k]);
|
||||||
|
}
|
||||||
|
eleData.endRmvCls = null;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the element's queue is empty (if only the 'inprogress' item is left at position 0) or if its queue is about to run
|
/* If the element's queue is empty (if only the 'inprogress' item is left at position 0) or if its queue is about to run
|
||||||
a non-Collide-initiated entry, turn off the isAnimating flag. A non-Collide-initiatied queue entry's logic might alter
|
a non-Collide-initiated entry, turn off the isAnimating flag. A non-Collide-initiatied queue entry's logic might alter
|
||||||
an element's CSS values and thereby cause Collide's cached value data to go stale. To detect if a queue entry was initiated by Collide,
|
an element's CSS values and thereby cause Collide's cached value data to go stale. To detect if a queue entry was initiated by Collide,
|
||||||
|
@ -23,6 +23,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
|
|||||||
var elements = animation._ele;
|
var elements = animation._ele;
|
||||||
var elementsLength = elements.length;
|
var elementsLength = elements.length;
|
||||||
var element = elements[elementIndex];
|
var element = elements[elementIndex];
|
||||||
|
var eleData;
|
||||||
|
|
||||||
var opts = animation._options;
|
var opts = animation._options;
|
||||||
var propertiesMap = animation._properties;
|
var propertiesMap = animation._properties;
|
||||||
@ -50,9 +51,16 @@ export function processElement(action, animation, elementIndex, clearCache) {
|
|||||||
******************/
|
******************/
|
||||||
|
|
||||||
if (data(element) === undefined) {
|
if (data(element) === undefined) {
|
||||||
Collide.initData(element);
|
eleData = Collide.initData(element);
|
||||||
|
} else {
|
||||||
|
eleData = data(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (animation._addStartClasses.length) eleData.startAddCls = animation._addStartClasses.slice();
|
||||||
|
if (animation._removeStartClasses.length) eleData.startRmvCls = animation._removeStartClasses.slice();
|
||||||
|
if (animation._addEndClasses.length) eleData.endAddCls = animation._addEndClasses.slice();
|
||||||
|
if (animation._removeEndClasses.length) eleData.endRmvCls = animation._removeEndClasses.slice();
|
||||||
|
|
||||||
|
|
||||||
/******************
|
/******************
|
||||||
Option: Delay
|
Option: Delay
|
||||||
@ -236,7 +244,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
|
|||||||
/* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale)
|
/* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale)
|
||||||
to transfer over end values to use as start values. If it's set to true and there is a previous
|
to transfer over end values to use as start values. If it's set to true and there is a previous
|
||||||
Collide call to pull values from, do so. */
|
Collide call to pull values from, do so. */
|
||||||
var eleData = data(element);
|
eleData = data(element);
|
||||||
if (clearCache) {
|
if (clearCache) {
|
||||||
eleData.tweensContainer = undefined;
|
eleData.tweensContainer = undefined;
|
||||||
} else if (eleData.tweensContainer && eleData.isAnimating === true) {
|
} else if (eleData.tweensContainer && eleData.isAnimating === true) {
|
||||||
@ -345,7 +353,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
|
|||||||
Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */
|
Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */
|
||||||
/* Note: Since SVG elements have some of their properties directly applied as HTML attributes,
|
/* Note: Since SVG elements have some of their properties directly applied as HTML attributes,
|
||||||
there is no way to check for their explicit browser support, and so we skip skip this check for them. */
|
there is no way to check for their explicit browser support, and so we skip skip this check for them. */
|
||||||
if (!data(element).isSVG && rootProperty !== 'tween' && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) {
|
if (!eleData.isSVG && rootProperty !== 'tween' && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) {
|
||||||
if (Collide.debug) console.log('Skipping [' + rootProperty + '] due to a lack of browser support.');
|
if (Collide.debug) console.log('Skipping [' + rootProperty + '] due to a lack of browser support.');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -370,7 +378,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
|
|||||||
/* The previous call's rootPropertyValue is extracted from the element's data cache since that's the
|
/* The previous call's rootPropertyValue is extracted from the element's data cache since that's the
|
||||||
instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue
|
instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue
|
||||||
attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */
|
attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */
|
||||||
rootPropertyValue = data(element).rootPropertyValueCache[rootProperty];
|
rootPropertyValue = eleData.rootPropertyValueCache[rootProperty];
|
||||||
|
|
||||||
/* If values were not transferred from a previous Collide call, query the DOM as needed. */
|
/* If values were not transferred from a previous Collide call, query the DOM as needed. */
|
||||||
} else {
|
} else {
|
||||||
@ -607,8 +615,8 @@ export function processElement(action, animation, elementIndex, clearCache) {
|
|||||||
|
|
||||||
/* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */
|
/* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */
|
||||||
if (opts.queue === '') {
|
if (opts.queue === '') {
|
||||||
data(element).tweensContainer = tweensContainer;
|
eleData.tweensContainer = tweensContainer;
|
||||||
data(element).opts = opts;
|
eleData.opts = opts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +109,20 @@ function tick(timestamp) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eleData.startAddCls) {
|
||||||
|
for (var k = 0; k < eleData.startAddCls.length; k++) {
|
||||||
|
element.classList.add(eleData.startAddCls[k]);
|
||||||
|
}
|
||||||
|
eleData.startAddCls = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eleData.startRmvCls) {
|
||||||
|
for (var k = 0; k < eleData.startRmvCls.length; k++) {
|
||||||
|
element.classList.remove(eleData.startRmvCls[k]);
|
||||||
|
}
|
||||||
|
eleData.startRmvCls = null;
|
||||||
|
}
|
||||||
|
|
||||||
var transformPropertyExists = false;
|
var transformPropertyExists = false;
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,6 +76,10 @@ ion-toolbar {
|
|||||||
// by default .nav-item is hidden
|
// by default .nav-item is hidden
|
||||||
// and the transition animation will display it
|
// and the transition animation will display it
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
|
&.show-nav-item {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-content {
|
ion-content {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
import {View} from 'angular2/src/core/annotations_impl/view';
|
import {View} from 'angular2/src/core/annotations_impl/view';
|
||||||
|
|
||||||
import {NavController, NavParams, Header, Toolbar} from 'ionic/ionic';
|
import {NavController, NavParams, Header, Toolbar, ToolbarTitle} from 'ionic/ionic';
|
||||||
import {ThirdPage} from './third-page';
|
import {ThirdPage} from './third-page';
|
||||||
|
|
||||||
|
|
||||||
@Component()
|
@Component()
|
||||||
@View({
|
@View({
|
||||||
templateUrl: 'pages/second-page.html',
|
templateUrl: 'pages/second-page.html',
|
||||||
directives: [Header, Toolbar]
|
directives: [Header, Toolbar, ToolbarTitle]
|
||||||
})
|
})
|
||||||
export class SecondPage {
|
export class SecondPage {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
import {View} from 'angular2/src/core/annotations_impl/view';
|
import {View} from 'angular2/src/core/annotations_impl/view';
|
||||||
|
|
||||||
import {NavController, Header, Toolbar} from 'ionic/ionic';
|
import {NavController, Header, Toolbar, ToolbarTitle} from 'ionic/ionic';
|
||||||
|
|
||||||
|
|
||||||
@Component()
|
@Component()
|
||||||
@View({
|
@View({
|
||||||
templateUrl: 'pages/third-page.html',
|
templateUrl: 'pages/third-page.html',
|
||||||
directives: [Header, Toolbar]
|
directives: [Header, Toolbar, ToolbarTitle]
|
||||||
})
|
})
|
||||||
export class ThirdPage {
|
export class ThirdPage {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -39,6 +39,7 @@ $toolbar-ios-button-background-color: transparent !default;
|
|||||||
.toolbar [side="primary"] {
|
.toolbar [side="primary"] {
|
||||||
@include flex-order(map-get($toolbar-order-ios, 'primary'));
|
@include flex-order(map-get($toolbar-order-ios, 'primary'));
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar [side="secondary"] {
|
.toolbar [side="secondary"] {
|
||||||
@include flex-order(map-get($toolbar-order-ios, 'secondary'));
|
@include flex-order(map-get($toolbar-order-ios, 'secondary'));
|
||||||
}
|
}
|
||||||
@ -46,8 +47,10 @@ $toolbar-ios-button-background-color: transparent !default;
|
|||||||
ion-title {
|
ion-title {
|
||||||
@include flex-order(map-get($toolbar-order-ios, 'title'));
|
@include flex-order(map-get($toolbar-order-ios, 'title'));
|
||||||
font-size: $toolbar-ios-title-font-size;
|
font-size: $toolbar-ios-title-font-size;
|
||||||
|
font-weight: 500;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-back-button {
|
.toolbar-back-button {
|
||||||
@include flex-order(map-get($toolbar-order-ios, 'back-button'));
|
@include flex-order(map-get($toolbar-order-ios, 'back-button'));
|
||||||
}
|
}
|
||||||
|
@ -20,16 +20,20 @@ $toolbar-secondary-flex-order: 10;
|
|||||||
}
|
}
|
||||||
|
|
||||||
ion-toolbar {
|
ion-toolbar {
|
||||||
/*@include flex-display();
|
|
||||||
@include flex-direction(row);
|
@include flex-direction(row);
|
||||||
@include flex-align-items(center);
|
@include flex-align-items(center);
|
||||||
@include flex-justify-content(space-between);*/
|
@include flex-justify-content(space-between);
|
||||||
|
|
||||||
// by default ion-toolbar is hidden
|
// by default ion-toolbar is display:none and
|
||||||
// and the transition animation will display it
|
// the transition animation will add the show class
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
|
&.show-toolbar {
|
||||||
|
@include flex-display();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// buttons are primary by default
|
// buttons are primary by default
|
||||||
ion-toolbar .button,
|
ion-toolbar .button,
|
||||||
ion-toolbar [side="primary"] {
|
ion-toolbar [side="primary"] {
|
||||||
@ -40,7 +44,7 @@ ion-toolbar [side="secondary"] {
|
|||||||
@include flex-order(map-get($toolbar-order-core, 'secondary'));
|
@include flex-order(map-get($toolbar-order-core, 'secondary'));
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-title.toolbar-title {
|
ion-title {
|
||||||
// double selector to override the following
|
// double selector to override the following
|
||||||
@include flex-display();
|
@include flex-display();
|
||||||
@include flex(1);
|
@include flex(1);
|
||||||
|
@ -44,26 +44,26 @@ class IOSTransition extends Animation {
|
|||||||
// entering item moves to center
|
// entering item moves to center
|
||||||
// before starting, set enteringItem to display: block
|
// before starting, set enteringItem to display: block
|
||||||
enteringContent
|
enteringContent
|
||||||
.display('block')
|
.addStartClass('show-nav-item')
|
||||||
.to(TRANSLATE_X, 0)
|
.to(TRANSLATE_X, 0)
|
||||||
.to(OPACITY, 1);
|
.to(OPACITY, 1);
|
||||||
|
|
||||||
enteringToolbars
|
enteringToolbars
|
||||||
.display('block')
|
.addStartClass('show-toolbar')
|
||||||
.to(TRANSLATE_X, 0)
|
.to(TRANSLATE_X, 0)
|
||||||
.to(OPACITY, 1);
|
.to(OPACITY, 1);
|
||||||
|
|
||||||
// leaving view moves off screen
|
// leaving view moves off screen
|
||||||
// when completed, set leavingItem to display: none
|
// when completed, set leavingItem to display: none
|
||||||
leavingContent
|
leavingContent
|
||||||
|
.removeEndClass('show-nav-item')
|
||||||
.from(TRANSLATE_X, 0)
|
.from(TRANSLATE_X, 0)
|
||||||
.from(OPACITY, 1)
|
.from(OPACITY, 1);
|
||||||
.display('none');
|
|
||||||
|
|
||||||
leavingToolbars
|
leavingToolbars
|
||||||
|
.removeEndClass('show-toolbar')
|
||||||
.from(TRANSLATE_X, 0)
|
.from(TRANSLATE_X, 0)
|
||||||
.from(OPACITY, 1)
|
.from(OPACITY, 1);
|
||||||
.display('none');
|
|
||||||
|
|
||||||
// set properties depending on direction
|
// set properties depending on direction
|
||||||
if (opts.direction === 'back') {
|
if (opts.direction === 'back') {
|
||||||
|
@ -10,26 +10,26 @@ class NoneTransition {
|
|||||||
|
|
||||||
// show entering contet
|
// show entering contet
|
||||||
let enteringContent = enteringItem.getContent();
|
let enteringContent = enteringItem.getContent();
|
||||||
enteringContent.style.display = 'block';
|
enteringContent.classList.add('show-nav-item');
|
||||||
enteringContent.style.transform = 'translateX(0%)';
|
enteringContent.style.transform = 'translateX(0%)';
|
||||||
|
|
||||||
// show entering headers
|
// show entering headers
|
||||||
let toolbarElements = enteringItem.getToolbars();
|
let enteringToolbars = enteringItem.getToolbars();
|
||||||
for (let i = 0; i < toolbarElements.length; i++) {
|
for (let i = 0; i < enteringToolbars.length; i++) {
|
||||||
toolbarElements[i].style.display = 'block';
|
enteringToolbars[i].classList.add('show-toolbar');
|
||||||
toolbarElements[i].style.transform = 'translateX(0%)';
|
enteringToolbars[i].style.transform = 'translateX(0%)';
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide the leaving item
|
// hide the leaving item
|
||||||
if (leavingItem) {
|
if (leavingItem) {
|
||||||
let leavingContent = leavingItem.getContent();
|
let leavingContent = leavingItem.getContent();
|
||||||
if (leavingContent) {
|
if (leavingContent) {
|
||||||
leavingContent.style.display = '';
|
leavingContent.classList.remove('show-nav-item');
|
||||||
}
|
}
|
||||||
|
|
||||||
let leavingHeaderElements = leavingItem.getToolbars();
|
let leavingToolbars = leavingItem.getToolbars();
|
||||||
for (let i = 0; i < leavingHeaderElements.length; i++) {
|
for (let i = 0; i < leavingToolbars.length; i++) {
|
||||||
leavingHeaderElements[i].style.display = '';
|
leavingToolbars[i].classList.remove('show-toolbar');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user