@@ -17,6 +17,7 @@ @interface SeafCustomInputAlertViewController () <UITextFieldDelegate>
1717
1818// For keyboard-aware animation
1919@property (nonatomic , strong ) NSLayoutConstraint *alertViewBottomConstraint;
20+ @property (nonatomic , strong ) NSLayoutConstraint *alertViewCenterYConstraint; // Center Y constraint for iPad keyboard adjustments
2021@property (nonatomic , assign ) BOOL isBeingDismissedProgrammatically;
2122@property (nonatomic , strong ) id finalCompletionHandler; // To store either confirm or cancel block
2223
@@ -155,12 +156,15 @@ - (void)viewDidLoad {
155156
156157 if (IsIpad ()) {
157158 self.view .backgroundColor = [UIColor clearColor ]; // The form sheet content is alertView
158- self.preferredContentSize = CGSizeMake (450 , 240 ); // Set preferredContentSize BEFORE setupViews/setupConstraints
159+ self.preferredContentSize = CGSizeMake (450 , 800 ); // Increase default height to avoid clipping
159160
160161 [self setupViews ]; // alertView needs to be created
161162 [self setupConstraints ]; // alertView needs to be constrained
162163 self.alertView .alpha = 1.0 ; // Visible by default for form sheet
163164 // Estimate height: title(20) + space(20) + field(40) + space(25) + button(44) + padding(30+30) = 209. Let's use 240.
165+
166+ // Register for keyboard notifications so we can move the alert if it would be covered.
167+ [self registerForKeyboardNotifications ];
164168 } else {
165169 [self setupViews ];
166170 [self setupConstraints ]; // Constraints are set up here
@@ -189,15 +193,11 @@ - (void)viewWillAppear:(BOOL)animated {
189193
190194- (void )viewWillDisappear : (BOOL )animated {
191195 [super viewWillDisappear: animated];
192- if (!IsIpad ()) {
193- [self unregisterForKeyboardNotifications ];
194- }
196+ [self unregisterForKeyboardNotifications ];
195197}
196198
197199- (void )dealloc {
198- if (!IsIpad ()) {
199- [self unregisterForKeyboardNotifications ]; // Just in case
200- }
200+ [self unregisterForKeyboardNotifications ]; // Ensure removed for all device types
201201}
202202
203203- (void )setupViews {
@@ -222,13 +222,13 @@ - (void)setupViews {
222222- (void )setupConstraints {
223223 // alertView constraints (leading/trailing for full width, bottom constraint for vertical positioning)
224224 if (IsIpad ()) {
225- // Center alertView and set its size based on preferredContentSize
225+ // Keep a reference to the center-Y constraint so we can move the alert when the keyboard shows up.
226+ self.alertViewCenterYConstraint = [self .alertView.centerYAnchor constraintEqualToAnchor: self .view.centerYAnchor];
226227 [NSLayoutConstraint activateConstraints: @[
227228 [self .alertView.centerXAnchor constraintEqualToAnchor: self .view.centerXAnchor],
228- [self .alertView.centerYAnchor constraintEqualToAnchor: self .view.centerYAnchor],
229- [self .alertView.widthAnchor constraintEqualToConstant: self .preferredContentSize.width],
230- [self .alertView.heightAnchor constraintEqualToConstant: self .preferredContentSize.height]
231- ]];
229+ self .alertViewCenterYConstraint,
230+ [self .alertView.widthAnchor constraintEqualToConstant: self .preferredContentSize.width]
231+ ]]; // Do not fix height so it can expand with content
232232 } else {
233233 self.alertViewBottomConstraint = [self .alertView.bottomAnchor constraintEqualToAnchor: self .view.bottomAnchor constant: kInitialOffScreenBottomConstant ];
234234 [NSLayoutConstraint activateConstraints: @[ // Full width, bottom constraint set above for iPhone
@@ -292,55 +292,70 @@ - (void)unregisterForKeyboardNotifications {
292292}
293293
294294- (void )keyboardWillShow : (NSNotification *)notification {
295- if (IsIpad ()) return ; // Only for iPhone
296295 NSDictionary *userInfo = notification.userInfo ;
297- CGRect keyboardFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue ];
296+ CGRect keyboardFrameInScreen = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue ];
297+ CGRect keyboardFrame = [self .view convertRect: keyboardFrameInScreen fromView: nil ];
298298 NSTimeInterval animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue ];
299- UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue ];
300-
301- self.alertViewBottomConstraint .constant = -keyboardFrame.size .height ;
302-
303- [UIView animateWithDuration: animationDuration
304- delay: 0.0
305- options: (animationCurve << 16 ) | UIViewAnimationOptionBeginFromCurrentState
306- animations: ^{
307- self.alertView .alpha = 1.0 ;
308- self.backgroundDimmingView .alpha = 1.0 ;
309- [self .view layoutIfNeeded ];
310- } completion: nil ];
299+ UIViewAnimationOptions options = (([userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue ]) << 16 ) | UIViewAnimationOptionBeginFromCurrentState;
300+
301+ if (IsIpad ()) {
302+ // Move the alert view up by 30% of the keyboard height so it stays visible
303+ CGFloat keyboardHeight = keyboardFrame.size .height ;
304+ self.alertViewCenterYConstraint .constant = -keyboardHeight * 0.3 ; // leave smaller gap
305+
306+ [UIView animateWithDuration: animationDuration delay: 0.0 options: options animations: ^{
307+ [self .view layoutIfNeeded ];
308+ } completion: nil ];
309+ } else {
310+ self.alertViewBottomConstraint .constant = -keyboardFrame.size .height ;
311+ [UIView animateWithDuration: animationDuration
312+ delay: 0.0
313+ options: options
314+ animations: ^{
315+ self.alertView .alpha = 1.0 ;
316+ self.backgroundDimmingView .alpha = 1.0 ;
317+ [self .view layoutIfNeeded ];
318+ } completion: nil ];
319+ }
311320}
312321
313322- (void )keyboardWillHide : (NSNotification *)notification {
314- if (IsIpad ()) return ; // Only for iPhone
315323 NSDictionary *userInfo = notification.userInfo ;
316324 NSTimeInterval animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue ];
317- UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue ];
318-
319- self.alertViewBottomConstraint .constant = kInitialOffScreenBottomConstant ;
320-
321- [UIView animateWithDuration: animationDuration
322- delay: 0.0
323- options: (animationCurve << 16 ) | UIViewAnimationOptionBeginFromCurrentState
324- animations: ^{
325- self.alertView .alpha = 0.0 ;
326- self.backgroundDimmingView .alpha = 0.0 ;
327- [self .view layoutIfNeeded ];
328- } completion: ^(BOOL finished) {
329- if (self.isBeingDismissedProgrammatically ) {
330- [self dismissViewControllerAnimated: NO completion: ^{
331- if (self.finalCompletionHandler ) {
332- // Check which handler it is (void vs void(^)(NSString*))
333- if (self.cancelHandler == self.finalCompletionHandler && [self .finalCompletionHandler respondsToSelector: @selector (description )]) { // crude check for block type
334- ((void (^)(void ))self.finalCompletionHandler )();
335- } else if (self.completionHandler == self.finalCompletionHandler && [self .finalCompletionHandler respondsToSelector: @selector (description )]) {
336- ((void (^)(NSString *))self.finalCompletionHandler )(self.inputTextField .text );
325+ UIViewAnimationOptions options = (([userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue ]) << 16 ) | UIViewAnimationOptionBeginFromCurrentState;
326+
327+ if (IsIpad ()) {
328+ self.alertViewCenterYConstraint .constant = 0 ; // Reset back to center
329+ [UIView animateWithDuration: animationDuration delay: 0.0 options: options animations: ^{
330+ [self .view layoutIfNeeded ];
331+ } completion: nil ];
332+ } else {
333+ self.alertViewBottomConstraint .constant = kInitialOffScreenBottomConstant ;
334+
335+ [UIView animateWithDuration: animationDuration
336+ delay: 0.0
337+ options: options
338+ animations: ^{
339+ self.alertView .alpha = 0.0 ;
340+ self.backgroundDimmingView .alpha = 0.0 ;
341+ [self .view layoutIfNeeded ];
342+ } completion: ^(BOOL finished) {
343+ if (self.isBeingDismissedProgrammatically ) {
344+ [self dismissViewControllerAnimated: NO completion: ^{
345+ if (self.finalCompletionHandler ) {
346+ // Determine which handler to call
347+ if (self.cancelHandler == self.finalCompletionHandler ) {
348+ ((void (^)(void ))self.finalCompletionHandler )();
349+ } else if (self.completionHandler == self.finalCompletionHandler ) {
350+ ((void (^)(NSString *))self.finalCompletionHandler )(self.inputTextField .text );
351+ }
337352 }
338- }
339- self.isBeingDismissedProgrammatically = NO ;
340- self. finalCompletionHandler = nil ;
341- }];
342- }
343- }];
353+ self. isBeingDismissedProgrammatically = NO ;
354+ self.finalCompletionHandler = nil ;
355+ }] ;
356+ }
357+ }];
358+ }
344359}
345360
346361#pragma mark - Actions
0 commit comments