@@ -1356,6 +1356,11 @@ - (void)handleKeyboardNotification:(NSNotification*)notification {
1356
1356
self.keyboardAnimationIsShowing = keyboardWillShow;
1357
1357
1358
1358
if (!keyboardAnimationIsCompounding) {
1359
+ // Match the begin frame of the keyboard notification to ensure spring interpolation accuracy.
1360
+ self.originalViewInsetBottom =
1361
+ ([self mainScreenIfViewLoaded ].bounds .size .height - beginKeyboardFrame.origin .y ) *
1362
+ [self mainScreenIfViewLoaded ].scale ;
1363
+
1359
1364
[self startKeyBoardAnimation: duration];
1360
1365
}
1361
1366
}
@@ -1524,7 +1529,7 @@ - (void)startKeyBoardAnimation:(NSTimeInterval)duration {
1524
1529
return ;
1525
1530
}
1526
1531
1527
- // When call this method first time,
1532
+ // When this method is called for the first time,
1528
1533
// initialize the keyboardAnimationView to get animation interpolation during animation.
1529
1534
if ([self keyboardAnimationView ] == nil ) {
1530
1535
UIView* keyboardAnimationView = [[UIView alloc ] init ];
@@ -1543,7 +1548,6 @@ - (void)startKeyBoardAnimation:(NSTimeInterval)duration {
1543
1548
[self keyboardAnimationView ].frame =
1544
1549
CGRectMake (0 , _viewportMetrics.physical_view_inset_bottom , 0 , 0 );
1545
1550
self.keyboardAnimationStartTime = fml::TimePoint ().Now ();
1546
- self.originalViewInsetBottom = _viewportMetrics.physical_view_inset_bottom ;
1547
1551
1548
1552
// Invalidate old vsync client if old animation is not completed.
1549
1553
[self invalidateKeyboardAnimationVSyncClient ];
@@ -1619,8 +1623,23 @@ - (void)setupKeyboardAnimationVsyncClient {
1619
1623
flutterViewController.get ().keyboardAnimationStartTime ;
1620
1624
double keyboardAnimationStop =
1621
1625
[[flutterViewController keyboardSpringCurve ] curveFunc: timeElapsed.ToSecondsF ()];
1622
- flutterViewController.get ()->_viewportMetrics .physical_view_inset_bottom =
1623
- start + (end - start) * keyboardAnimationStop;
1626
+ double newY = start + (end - start) * keyboardAnimationStop;
1627
+
1628
+ // When a running animation is interrupted with the opposite animation (e.g. show interrupted
1629
+ // with hide), adjust the spring curve until the model catches up with the current
1630
+ // bottomInset.
1631
+ double currentViewInsetBottom =
1632
+ flutterViewController.get ()->_viewportMetrics .physical_view_inset_bottom ;
1633
+ double keyboardSpringFrameAdjustment = 0 ;
1634
+ while ((start > end && currentViewInsetBottom < newY) ||
1635
+ (end > start && currentViewInsetBottom > newY)) {
1636
+ keyboardSpringFrameAdjustment += 1.0 / [DisplayLinkManager displayRefreshRate ];
1637
+ keyboardAnimationStop = [[flutterViewController keyboardSpringCurve ]
1638
+ curveFunc: timeElapsed.ToSecondsF () + keyboardSpringFrameAdjustment];
1639
+ newY = start + (end - start) * keyboardAnimationStop;
1640
+ }
1641
+
1642
+ flutterViewController.get ()->_viewportMetrics .physical_view_inset_bottom = newY;
1624
1643
[flutterViewController updateViewportMetrics ];
1625
1644
}
1626
1645
};
0 commit comments