1414
1515@interface TOPasscodeViewController () <UIViewControllerTransitioningDelegate>
1616
17+ /* State */
18+ @property (nonatomic , assign , readwrite ) TOPasscodeType passcodeType;
19+ @property (nonatomic , assign ) CGFloat keyboardHeight;
20+
21+ /* Views */
1722@property (nonatomic , strong , readwrite ) UIVisualEffectView *backgroundEffectView;
1823@property (nonatomic , strong , readwrite ) UIView *backgroundView;
1924@property (nonatomic , strong , readwrite ) TOPasscodeView *passcodeView;
2025@property (nonatomic , strong , readwrite ) UIButton *biometricButton;
2126@property (nonatomic , strong , readwrite ) UIButton *cancelButton;
22- @property (nonatomic , assign , readwrite ) TOPasscodeType passcodeType;
27+
28+
2329
2430@end
2531
@@ -47,6 +53,11 @@ - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibB
4753 return self;
4854}
4955
56+ - (void )dealloc
57+ {
58+ [[NSNotificationCenter defaultCenter ] removeObserver: self name: UIKeyboardWillChangeFrameNotification object: nil ];
59+ }
60+
5061#pragma mark - View Setup -
5162
5263- (void )setUp
@@ -61,6 +72,9 @@ - (void)setUp
6172 else {
6273 self.modalPresentationStyle = UIModalPresentationFullScreen;
6374 }
75+
76+ [[NSNotificationCenter defaultCenter ] addObserver: self selector: @selector (keyboardWillChangeFrame: )
77+ name: UIKeyboardWillChangeFrameNotification object: nil ];
6478}
6579
6680- (void )setUpBackgroundEffectViewForStyle : (TOPasscodeViewStyle)style
@@ -199,13 +213,37 @@ - (void)viewDidLayoutSubviews
199213 [self .passcodeView sizeToFitWidth: bounds.width];
200214
201215 // Re-center the pin view
202- self.passcodeView .center = self.view .center ;
216+ CGRect frame = self.passcodeView .frame ;
217+ frame.origin .x = (bounds.width - frame.size .width ) * 0 .5f ;
218+ frame.origin .y = ((bounds.height - self.keyboardHeight ) - frame.size .height ) * 0 .5f ;
219+ self.passcodeView .frame = CGRectIntegral (frame);
203220}
204221
205222- (void )viewWillAppear : (BOOL )animated
206223{
207224 [super viewWillAppear: animated];
208225 [self setNeedsStatusBarAppearanceUpdate ];
226+
227+ // Force an initial layout if the view hasn't been presented yet
228+ [UIView performWithoutAnimation: ^{
229+ [self .view setNeedsLayout ];
230+ [self .view layoutIfNeeded ];
231+ }];
232+
233+ // Show the keyboard if we're
234+ if (self.passcodeType == TOPasscodeTypeCustomAlphanumeric) {
235+ [self .passcodeView.inputField becomeFirstResponder ];
236+ }
237+ }
238+
239+ - (void )viewWillDisappear : (BOOL )animated
240+ {
241+ [super viewWillDisappear: animated];
242+
243+ // Dismiss the keyboard if it is visible
244+ if (self.passcodeView .inputField .isFirstResponder ) {
245+ [self .passcodeView.inputField resignFirstResponder ];
246+ }
209247}
210248
211249- (UIStatusBarStyle)preferredStatusBarStyle
@@ -331,6 +369,35 @@ - (void)didCompleteEnteringPasscode:(NSString *)passcode
331369 }
332370}
333371
372+ #pragma mark - Keyboard Handling -
373+ - (void )keyboardWillChangeFrame : (NSNotification *)notification
374+ {
375+ // Extract the keyboard information we need from the notification
376+ CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue ];
377+ CGFloat animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue ];
378+ UIViewAnimationOptions animationCurve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue ];
379+
380+ // Work out the on-screen height of the keyboard
381+ self.keyboardHeight = self.view .bounds .size .height - keyboardFrame.origin .y ;
382+ self.keyboardHeight = MAX (self.keyboardHeight , 0 .0f );
383+
384+ // Set that the view needs to be laid out
385+ [self .view setNeedsLayout ];
386+
387+ if (animationDuration < FLT_EPSILON) {
388+ return ;
389+ }
390+
391+ // Animate the content sliding up and down with the keyboard
392+ [UIView animateWithDuration: animationDuration
393+ delay: 0 .0f
394+ // usingSpringWithDamping:1.0f
395+ // initialSpringVelocity:1.0f
396+ options: animationCurve
397+ animations: ^{ [self .view layoutIfNeeded ]; }
398+ completion: nil ];
399+ }
400+
334401#pragma mark - Transitioning Delegate -
335402- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController : (UIViewController *)presented
336403 presentingController : (UIViewController *)presenting
0 commit comments