mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
keyboard scroll updates
This commit is contained in:
@ -65,6 +65,29 @@ export class Content extends Ion {
|
|||||||
return this._scrollTo.start(x, y, duration, tolerance);
|
return this._scrollTo.start(x, y, duration, tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDimensions() {
|
||||||
|
let scrollElement = this.scrollElement;
|
||||||
|
let parentElement = scrollElement.parentElement;
|
||||||
|
|
||||||
|
return {
|
||||||
|
height: parentElement.offsetHeight,
|
||||||
|
top: parentElement.offsetTop,
|
||||||
|
bottom: parentElement.offsetTop + parentElement.offsetHeight,
|
||||||
|
|
||||||
|
width: parentElement.offsetWidth,
|
||||||
|
left: parentElement.offsetLeft,
|
||||||
|
right: parentElement.offsetLeft + parentElement.offsetWidth,
|
||||||
|
|
||||||
|
scrollHeight: scrollElement.scrollHeight,
|
||||||
|
scrollTop: scrollElement.scrollTop,
|
||||||
|
scrollBottom: scrollElement.scrollTop + scrollElement.scrollHeight,
|
||||||
|
|
||||||
|
scrollWidth: scrollElement.scrollWidth,
|
||||||
|
scrollLeft: scrollElement.scrollLeft,
|
||||||
|
scrollRight: scrollElement.scrollLeft + scrollElement.scrollWidth,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get scrollPadding() {
|
get scrollPadding() {
|
||||||
return this._sp;
|
return this._sp;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import {Ion} from '../ion';
|
|||||||
import {IonicApp} from '../app/app';
|
import {IonicApp} from '../app/app';
|
||||||
import {Content} from '../content/content';
|
import {Content} from '../content/content';
|
||||||
import {ClickBlock} from '../../util/click-block';
|
import {ClickBlock} from '../../util/click-block';
|
||||||
|
import {Platform} from '../../platform/platform';
|
||||||
import * as dom from '../../util/dom';
|
import * as dom from '../../util/dom';
|
||||||
|
|
||||||
|
|
||||||
@ -157,9 +158,16 @@ export class TextInput extends Ion {
|
|||||||
|
|
||||||
if (scrollView && this.scrollAssist) {
|
if (scrollView && this.scrollAssist) {
|
||||||
// this input is inside of a scroll view
|
// this input is inside of a scroll view
|
||||||
// scroll the input to the top
|
|
||||||
let inputY = (this.elementRef.nativeElement.offsetTop - SCROLL_Y_PADDING);
|
|
||||||
|
|
||||||
|
// find out if text input should be manually scrolled into view
|
||||||
|
let scrollToY = this.getScollToY();
|
||||||
|
if (scrollToY === 0) {
|
||||||
|
// the text input is in a safe position that doesn't require
|
||||||
|
// it to be scrolled into view, just set focus now
|
||||||
|
return this.setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// manually scroll the text input to the top
|
||||||
// do not allow any clicks while it's scrolling
|
// do not allow any clicks while it's scrolling
|
||||||
ClickBlock(true, SCROLL_INTO_VIEW_DURATION + 200);
|
ClickBlock(true, SCROLL_INTO_VIEW_DURATION + 200);
|
||||||
|
|
||||||
@ -168,12 +176,13 @@ export class TextInput extends Ion {
|
|||||||
|
|
||||||
// temporarily move the focus to the focus holder so the browser
|
// temporarily move the focus to the focus holder so the browser
|
||||||
// doesn't freak out while it's trying to get the input in place
|
// doesn't freak out while it's trying to get the input in place
|
||||||
|
// at this point the native text input still does not have focus
|
||||||
this.tempFocusMove();
|
this.tempFocusMove();
|
||||||
|
|
||||||
// scroll the input into place
|
// scroll the input into place
|
||||||
scrollView.scrollTo(0, inputY, SCROLL_INTO_VIEW_DURATION, 8).then(() => {
|
scrollView.scrollTo(0, scrollToY, SCROLL_INTO_VIEW_DURATION, 8).then(() => {
|
||||||
// the scroll view is in the correct position now
|
// the scroll view is in the correct position now
|
||||||
// give the native input the focus
|
// give the native text input focus
|
||||||
this.setFocus();
|
this.setFocus();
|
||||||
|
|
||||||
// all good, allow clicks again
|
// all good, allow clicks again
|
||||||
@ -187,6 +196,69 @@ export class TextInput extends Ion {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getScollToY() {
|
||||||
|
let ele = this.elementRef.nativeElement;
|
||||||
|
let viewDimensions = this.scrollView.getDimensions();
|
||||||
|
|
||||||
|
// get the inputs Y position relative to the scroll view
|
||||||
|
let inputOffsetTop = ele.offsetTop;
|
||||||
|
|
||||||
|
// compute offset values relative to the body
|
||||||
|
let contentTop = viewDimensions.top;
|
||||||
|
let inputTop = inputOffsetTop + contentTop - viewDimensions.scrollTop;
|
||||||
|
let inputBottom = (inputTop + ele.offsetHeight);
|
||||||
|
|
||||||
|
// compute the safe area which is the viewable
|
||||||
|
// content area when the soft keyboard is up
|
||||||
|
let safeTop = contentTop - 1;
|
||||||
|
let safeBottom = (Platform.height() * 0.6);
|
||||||
|
|
||||||
|
// Text Input Scroll To Scenarios
|
||||||
|
// ---------------------------------------
|
||||||
|
// 1) Input top within safe area, bottom within safe area
|
||||||
|
// 2) Input top within safe area, bottom below safe area
|
||||||
|
// 3) Input top and bottom below safe area
|
||||||
|
// 4) Input top above safe area, bottom within safe area
|
||||||
|
// 5) Input top above safe area, bottom below safe area
|
||||||
|
|
||||||
|
if (inputTop >= safeTop && inputTop <= safeBottom) {
|
||||||
|
// Input top within safe area
|
||||||
|
|
||||||
|
if (inputBottom <= safeBottom) {
|
||||||
|
// 1) Input top within safe area, bottom within safe area
|
||||||
|
// no need to scroll to a position, it's good as-is
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Input top within safe area, bottom below safe area
|
||||||
|
// TODO: What if the input is still taller than safe area?
|
||||||
|
return inputOffsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputTop > safeBottom) {
|
||||||
|
// 3) Input top and bottom below safe area
|
||||||
|
// TODO: What if the input is still taller than safe area?
|
||||||
|
return inputOffsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputTop < safeTop) {
|
||||||
|
// Input top above safe area
|
||||||
|
|
||||||
|
if (inputBottom <= safeTop) {
|
||||||
|
// 4) Input top above safe area, bottom within safe area
|
||||||
|
// TODO: What if the input is still taller than safe area?
|
||||||
|
return inputOffsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) Input top above safe area, bottom below safe area
|
||||||
|
// TODO: What if the input is still taller than safe area?
|
||||||
|
return inputOffsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback for whatever reason
|
||||||
|
return inputOffsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
deregListeners() {
|
deregListeners() {
|
||||||
this.deregScroll && this.deregScroll();
|
this.deregScroll && this.deregScroll();
|
||||||
}
|
}
|
||||||
@ -232,4 +304,3 @@ export class TextInput extends Ion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SCROLL_INTO_VIEW_DURATION = 500;
|
const SCROLL_INTO_VIEW_DURATION = 500;
|
||||||
const SCROLL_Y_PADDING = 6;
|
|
||||||
|
Reference in New Issue
Block a user