@@ -21,6 +21,7 @@ import {OverlayReference} from '../overlay-reference';
21
21
import { isElementScrolledOutsideView , isElementClippedByScrolling } from './scroll-clip' ;
22
22
import { coerceCssPixelValue } from '@angular/cdk/coercion' ;
23
23
import { Platform } from '@angular/cdk/platform' ;
24
+ import { OverlayContainer } from '../overlay-container' ;
24
25
25
26
// TODO: refactor clipping detection into a separate thing (part of scrolling module)
26
27
// TODO: doesn't handle both flexible width and height when it has to scroll along both axis.
@@ -131,8 +132,9 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
131
132
connectedTo : ElementRef | HTMLElement ,
132
133
private _viewportRuler : ViewportRuler ,
133
134
private _document : Document ,
134
- // @deletion -target 7.0.0 `_platform` parameter to be made required.
135
- private _platform ?: Platform ) {
135
+ // @deletion -target 7.0.0 `_platform` and `_overlayContainer` parameters to be made required.
136
+ private _platform ?: Platform ,
137
+ private _overlayContainer ?: OverlayContainer ) {
136
138
this . setOrigin ( connectedTo ) ;
137
139
}
138
140
@@ -169,6 +171,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
169
171
*/
170
172
apply ( ) : void {
171
173
// We shouldn't do anything if the strategy was disposed or we're on the server.
174
+ // @deletion -target 7.0.0 Remove `_platform` null check once it's guaranteed to be defined.
172
175
if ( this . _isDisposed || ( this . _platform && ! this . _platform . isBrowser ) ) {
173
176
return ;
174
177
}
@@ -839,6 +842,18 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
839
842
overlayPoint = this . _pushOverlayOnScreen ( overlayPoint , this . _overlayRect ) ;
840
843
}
841
844
845
+ // @deletion -target 7.0.0 Currently the `_overlayContainer` is optional in order to avoid a
846
+ // breaking change. The null check here can be removed once the `_overlayContainer` becomes
847
+ // a required parameter.
848
+ let virtualKeyboardOffset = this . _overlayContainer ?
849
+ this . _overlayContainer . getContainerElement ( ) . getBoundingClientRect ( ) . top : 0 ;
850
+
851
+ // Normally this would be zero, however when the overlay is attached to an input (e.g. in an
852
+ // autocomplete), mobile browsers will shift everything in order to put the input in the middle
853
+ // of the screen and to make space for the virtual keyboard. We need to account for this offset,
854
+ // otherwise our positioning will be thrown off.
855
+ overlayPoint . y -= virtualKeyboardOffset ;
856
+
842
857
// We want to set either `top` or `bottom` based on whether the overlay wants to appear
843
858
// above or below the origin and the direction in which the element will expand.
844
859
if ( position . overlayY === 'bottom' ) {
0 commit comments