fix(keyboard): close keyboard before transition

Closes #616
This commit is contained in:
Adam Bradley
2015-11-23 12:21:44 -06:00
parent 12bdba0328
commit 103c183190
10 changed files with 77 additions and 45 deletions

View File

@@ -42,7 +42,7 @@
<ion-card>
<ion-input>
<ion-label>Username:<ion-label>
<ion-label>Username:</ion-label>
<input type="text">
</ion-input>
</ion-card>

View File

@@ -3,6 +3,7 @@ import {Compiler, ElementRef, Injector, provide, NgZone, DynamicComponentLoader,
import {Ion} from '../ion';
import {IonicApp} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {ViewController} from './view-controller';
import {Animation} from '../../animations/animation';
import {SwipeBackGesture} from './swipe-back';
@@ -105,6 +106,7 @@ export class NavController extends Ion {
parentnavCtrl: NavController,
app: IonicApp,
config: Config,
keyboard: Keyboard,
elementRef: ElementRef,
compiler: Compiler,
loader: DynamicComponentLoader,
@@ -117,6 +119,7 @@ export class NavController extends Ion {
this.parent = parentnavCtrl;
this.app = app;
this.config = config;
this.keyboard = keyboard;
this._compiler = compiler;
this._loader = loader;
@@ -437,14 +440,16 @@ export class NavController extends Ion {
* @returns {any} TODO
*/
_transition(enteringView, leavingView, opts, done) {
let self = this;
if (enteringView === leavingView) {
return done(enteringView);
}
if (!opts.animation) {
opts.animation = this.config.get('pageTransition');
opts.animation = self.config.get('pageTransition');
}
if (this.config.get('animate') === false) {
if (self.config.get('animate') === false) {
opts.animate = false;
}
@@ -454,17 +459,15 @@ export class NavController extends Ion {
enteringView.loaded();
}
// wait for the new view to complete setup
this._stage(enteringView, () => {
function beginTransition() {
if (enteringView.shouldDestroy) {
// already marked as a view that will be destroyed, don't continue
return done(enteringView);
}
this._setZIndex(enteringView.instance, leavingView.instance, opts.direction);
self._setZIndex(enteringView.instance, leavingView.instance, opts.direction);
this._zone.runOutsideAngular(() => {
self._zone.runOutsideAngular(() => {
enteringView.shouldDestroy = false;
enteringView.shouldCache = false;
@@ -480,10 +483,10 @@ export class NavController extends Ion {
leavingView.state = STAGED_LEAVING_STATE;
// init the transition animation
opts.renderDelay = opts.transitionDelay || this.config.get('pageTransitionDelay');
opts.renderDelay = opts.transitionDelay || self.config.get('pageTransitionDelay');
let transAnimation = Animation.createTransition(this._getStagedEntering(),
this._getStagedLeaving(),
let transAnimation = Animation.createTransition(self._getStagedEntering(),
self._getStagedLeaving(),
opts);
if (opts.animate === false) {
// force it to not animate the elements, just apply the "to" styles
@@ -495,8 +498,8 @@ export class NavController extends Ion {
if (duration > 64) {
// block any clicks during the transition and provide a
// fallback to remove the clickblock if something goes wrong
this.app.setEnabled(false, duration);
this.app.setTransitioning(true, duration);
self.app.setEnabled(false, duration);
self.app.setTransitioning(true, duration);
}
if (opts.pageType) {
@@ -518,16 +521,25 @@ export class NavController extends Ion {
}
// all done!
this._zone.run(() => {
this._transComplete();
self._zone.run(() => {
self._transComplete();
done(enteringView);
});
});
});
});
}
// wait for the new view to complete setup
if (self.keyboard.isOpen()) {
self._stage(enteringView, () => {
self.keyboard.onClose(beginTransition, 64);
});
} else {
self._stage(enteringView, beginTransition);
}
}
/**

View File

@@ -2,6 +2,7 @@ import {Component, Directive, ElementRef, Host, Optional, forwardRef, Inject, Ng
import {IonicApp} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {ConfigComponent} from '../../config/decorators';
import {NavController} from './nav-controller';
import {ViewController} from './view-controller';
@@ -113,6 +114,7 @@ export class Nav extends NavController {
@Optional() viewCtrl: ViewController,
app: IonicApp,
config: Config,
keyboard: Keyboard,
elementRef: ElementRef,
compiler: Compiler,
loader: DynamicComponentLoader,
@@ -120,7 +122,7 @@ export class Nav extends NavController {
zone: NgZone,
renderer: Renderer
) {
super(hostNavCtrl, app, config, elementRef, compiler, loader, viewManager, zone, renderer);
super(hostNavCtrl, app, config, keyboard, elementRef, compiler, loader, viewManager, zone, renderer);
if (viewCtrl) {
// an ion-nav can also act as an ion-page within a parent ion-nav

View File

@@ -2,6 +2,7 @@ import {Component, ElementRef, Compiler, DynamicComponentLoader, AppViewManager,
import {IonicApp} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {OverlayController} from './overlay-controller';
import {NavController} from '../nav/nav-controller';
@@ -16,6 +17,7 @@ export class OverlayNav extends NavController {
overlayCtrl: OverlayController,
app: IonicApp,
config: Config,
keyboard: Keyboard,
elementRef: ElementRef,
compiler: Compiler,
loader: DynamicComponentLoader,
@@ -23,7 +25,7 @@ export class OverlayNav extends NavController {
zone: NgZone,
renderer: Renderer
) {
super(null, app, config, elementRef, compiler, loader, viewManager, zone, renderer);
super(null, app, config, keyboard, elementRef, compiler, loader, viewManager, zone, renderer);
if (overlayCtrl.anchor) {
throw ('An app should only have one <ion-overlay></ion-overlay>');

View File

@@ -2,6 +2,7 @@ import {Component, Directive, Host, ElementRef, Compiler, DynamicComponentLoader
import {IonicApp} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {NavController} from '../nav/nav-controller';
import {ViewController} from '../nav/view-controller';
import {Tabs} from './tabs';
@@ -72,6 +73,7 @@ export class Tab extends NavController {
@Host() parentTabs: Tabs,
app: IonicApp,
config: Config,
keyboard: Keyboard,
elementRef: ElementRef,
compiler: Compiler,
loader: DynamicComponentLoader,
@@ -80,7 +82,7 @@ export class Tab extends NavController {
renderer: Renderer
) {
// A Tab is a NavController for its child pages
super(parentTabs, app, config, elementRef, compiler, loader, viewManager, zone, renderer);
super(parentTabs, app, config, keyboard, elementRef, compiler, loader, viewManager, zone, renderer);
this._isInitial = parentTabs.add(this);
this._panelId = 'tabpanel-' + this.id;

View File

@@ -1,26 +1,39 @@
import {RouteConfig, Location} from 'angular2/router';
import {App, Page, NavController} from 'ionic/ionic';
import {App, Page, NavController, Keyboard} from 'ionic/ionic';
@Page({
template: '' +
'<ion-navbar *navbar>' +
'<ion-title>Sign In</ion-title>' +
'</ion-navbar>' +
'<ion-content padding>' +
'<p><button id="signIn" (click)="push()">Go to tabs</button></p>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'</ion-content>'
template: `
<ion-navbar *navbar>
<ion-title>Sign In</ion-title>
</ion-navbar>
<ion-content padding>
<ion-card>
<ion-input>
<ion-label>Username:</ion-label>
<input type="text">
</ion-input>
<ion-input>
<ion-label>Password:</ion-label>
<input type="password">
</ion-input>
<ion-item>
<button block id="signIn" (click)="push()">Sign In</button>
</ion-item>
</ion-card>
</ion-content>
`
})
class SignIn {
constructor(nav: NavController) {
constructor(nav: NavController, keyboard: Keyboard) {
this.nav = nav;
this.keyboard = keyboard;
}
push() {
this.nav.push(TabsPage);
//this.keyboard.close();
}
}

View File

@@ -77,8 +77,9 @@ function touchCancel(ev) {
function mouseDown(ev) {
if (isDisabledNativeClick()) {
console.debug('mouseDown prevent');
ev.preventDefault();
console.debug('mouseDown prevent', ev.target.tagName);
// does not prevent default on purpose
// so native blur events from inputs can happen
ev.stopPropagation();
} else if (lastTouch + disableNativeClickAmount < Date.now()) {
@@ -88,7 +89,7 @@ function mouseDown(ev) {
function mouseUp(ev) {
if (isDisabledNativeClick()) {
console.debug('mouseUp prevent');
console.debug('mouseUp prevent', ev.target.tagName);
ev.preventDefault();
ev.stopPropagation();
}

View File

@@ -524,11 +524,11 @@ class InputScrollAssist {
}
const SCROLL_ASSIST_SPEED = 0.5;
const SCROLL_ASSIST_SPEED = 0.4;
function getScrollAssistDuration(distanceToScroll) {
//return 3000;
distanceToScroll = Math.abs(distanceToScroll);
let duration = distanceToScroll / SCROLL_ASSIST_SPEED;
return Math.min(380, Math.max(80, duration));
return Math.min(400, Math.max(100, duration));
}

View File

@@ -13,6 +13,7 @@ export * from './platform/storage'
export * from './util/click-block'
export * from './util/events'
export * from './util/keyboard'
export * from './animations/animation'
export * from './animations/builtins'

View File

@@ -2,7 +2,7 @@ import {Injectable, NgZone} from 'angular2/angular2';
import {Config} from '../config/config';
import {Form} from './form';
import * as dom from './dom';
import {hasFocusedTextInput, raf} from './dom';
@Injectable()
@@ -18,10 +18,10 @@ export class Keyboard {
}
isOpen() {
return dom.hasFocusedTextInput();
return hasFocusedTextInput();
}
onClose(callback) {
onClose(callback, pollingInternval=KEYBOARD_CLOSE_POLLING) {
const self = this;
let promise = null;
@@ -41,20 +41,19 @@ export class Keyboard {
});
} else {
setTimeout(checkKeyboard, KEYBOARD_CLOSE_POLLING);
setTimeout(checkKeyboard, pollingInternval);
}
}
setTimeout(checkKeyboard, KEYBOARD_CLOSE_POLLING);
setTimeout(checkKeyboard, pollingInternval);
});
return promise;
}
close() {
dom.raf(() => {
if (dom.hasFocusedTextInput()) {
raf(() => {
if (hasFocusedTextInput()) {
// only focus out when a text input has focus
this.form.focusOut();
}
@@ -78,7 +77,7 @@ export class Keyboard {
let isKeyInputEnabled = false;
function cssClass() {
dom.raf(() => {
raf(() => {
document.body.classList[isKeyInputEnabled ? 'add' : 'remove']('focus-outline');
});
}