Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- **Android**: Fixed dead state after rapid present/dismiss cycles. ([#593](https://github.com/lodev09/react-native-true-sheet/pull/593) by [@lodev09](https://github.com/lodev09))
- **iOS**: Fixed position change not emitting when detent or index changed. ([#584](https://github.com/lodev09/react-native-true-sheet/pull/584) by [@lodev09](https://github.com/lodev09))
- **Android**: Use RN `BackHandler` for back press detection for reliability across Android versions. ([#580](https://github.com/lodev09/react-native-true-sheet/pull/580) by [@lodev09](https://github.com/lodev09))
- **iOS**: Fixed sheet snapping instead of animating back to detent on keyboard dismiss. ([#604](https://github.com/lodev09/react-native-true-sheet/pull/604) by [@TheOmran](https://github.com/TheOmran))

### 💡 Others

Expand Down
1 change: 1 addition & 0 deletions ios/TrueSheetContainerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
@optional

- (void)containerViewHeaderDidChangeSize:(CGSize)newSize;
- (void)containerViewKeyboardWillHide;

@end

Expand Down
22 changes: 20 additions & 2 deletions ios/TrueSheetContainerView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ - (instancetype)init {

@interface TrueSheetContainerView () <TrueSheetContentViewDelegate,
TrueSheetHeaderViewDelegate,
TrueSheetFooterViewDelegate>
@end
TrueSheetFooterViewDelegate,
TrueSheetKeyboardObserverDelegate>

@implementation TrueSheetContainerView {
TrueSheetContentView *_contentView;
Expand Down Expand Up @@ -257,9 +257,27 @@ - (void)setupKeyboardObserverWithViewController:(UIViewController *)viewControll
[_keyboardObserver addDelegate:_footerView];
}

// Register self to handle keyboard hide for animated detent reconfiguration
[_keyboardObserver addDelegate:self];

[_keyboardObserver start];
}

#pragma mark - TrueSheetKeyboardObserverDelegate (Container)

- (void)keyboardWillShow:(CGFloat)height duration:(NSTimeInterval)duration curve:(UIViewAnimationOptions)curve {
// No-op — content view and footer handle their own show logic
}

- (void)keyboardWillHide:(NSTimeInterval)duration curve:(UIViewAnimationOptions)curve {
// Notify delegate so the sheet can force an animated detent reconfiguration.
// Without this, UISheetPresentationController snaps back to the custom detent
// instead of animating when the keyboard dismisses.
if ([self.delegate respondsToSelector:@selector(containerViewKeyboardWillHide)]) {
[self.delegate containerViewKeyboardWillHide];
}
}

- (void)cleanupKeyboardObserver {
if (_keyboardObserver) {
[_keyboardObserver stop];
Expand Down
9 changes: 9 additions & 0 deletions ios/TrueSheetView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,15 @@ - (void)containerViewScrollViewDidChange {
[self setupScrollable];
}

- (void)containerViewKeyboardWillHide {
// Force an animated detent reconfiguration when the keyboard dismisses.
// Without this, UISheetPresentationController snaps back to the custom detent
// (especially 'auto') instead of smoothly animating the transition.
if (_controller.isPresented && !_controller.isBeingDismissed) {
[_controller setupSheetDetentsForSizeChange];
}
}

#pragma mark - TrueSheetViewControllerDelegate

- (void)viewControllerWillPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
Expand Down
20 changes: 16 additions & 4 deletions ios/core/TrueSheetKeyboardObserver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
@implementation TrueSheetKeyboardObserver {
NSHashTable<id<TrueSheetKeyboardObserverDelegate>> *_delegates;
CGFloat _currentHeight;
BOOL _wasShowingForSheet;
}

- (CGFloat)currentHeight {
Expand Down Expand Up @@ -64,10 +65,6 @@ - (void)keyboardWillChangeFrame:(NSNotification *)notification {
return;
}

if (![self isFirstResponderWithinSheet]) {
return;
}

NSDictionary *userInfo = notification.userInfo;
CGRect keyboardFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
Expand All @@ -81,6 +78,21 @@ - (void)keyboardWillChangeFrame:(NSNotification *)notification {
CGRect keyboardFrameInWindow = [window convertRect:keyboardFrame fromWindow:nil];
CGFloat keyboardHeight = MAX(0, window.bounds.size.height - keyboardFrameInWindow.origin.y);

if (keyboardHeight > 0) {
// Keyboard is showing — require first responder to be within this sheet
if (![self isFirstResponderWithinSheet]) {
return;
}
_wasShowingForSheet = YES;
} else {
// Keyboard is hiding — allow if we previously tracked it as showing for this sheet
// (first responder may have already resigned by the time this notification fires)
if (!_wasShowingForSheet) {
return;
}
_wasShowingForSheet = NO;
}

_currentHeight = keyboardHeight;

for (id<TrueSheetKeyboardObserverDelegate> delegate in _delegates) {
Expand Down
Loading