Logic For Moving Text Field Above Keyboard On Tap

前端 未结 3 1617
猫巷女王i
猫巷女王i 2020-12-05 09:10

Right now, I have basic code for moving the textfield above the keyboard when you start editing. However, the size of the textfield varies based on device and orientation. S

相关标签:
3条回答
  • 2020-12-05 09:22

    What you really want to do is observe the UIKeyboard(Did|Will)(Show|Hide) notifications. They contain in their userInfo dictionaries the beginning and ending frame, as well as the correct animation curve and durations.

    So after observing this notification, when it's posted move your text field based on the size of the frame passed in the notification, according to the animation hints provided.

    You can see more information in the UIWindow class reference's "notifications" section: https://developer.apple.com/library/ios/#documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html

    Below is a sample view controller implementation. The nib for this view controller was just a single text field, with an outlet connected to it, and the text field's delegate set to the view controller.

    @interface ViewController ()
    
    - (void)viewControllerInit;
    
    @end
    
    @implementation ViewController
    
    @synthesize textField;
    
    - (id)initWithCoder:(NSCoder *)coder {
        self = [super initWithCoder:coder];
        if (self) {
            [self viewControllerInit];
        }
        return self;
    }
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
        {
            [self viewControllerInit];
        }
        return self;
    }
    
    
    - (void)viewControllerInit
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    }
    
    
    - (void)dealloc {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    
    #pragma mark - Notification Handlers
    
    - (void)keyboardWillShow:(NSNotification *)notification
    {
        // I'll try to make my text field 20 pixels above the top of the keyboard
        // To do this first we need to find out where the keyboard will be.
    
        NSValue *keyboardEndFrameValue = [[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey];
        CGRect keyboardEndFrame = [keyboardEndFrameValue CGRectValue];
    
        // When we move the textField up, we want to match the animation duration and curve that
        // the keyboard displays. So we get those values out now
    
        NSNumber *animationDurationNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
        NSTimeInterval animationDuration = [animationDurationNumber doubleValue];
    
        NSNumber *animationCurveNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey];
        UIViewAnimationCurve animationCurve = [animationCurveNumber intValue];
    
        // UIView's block-based animation methods anticipate not a UIVieAnimationCurve but a UIViewAnimationOptions.
        // We shift it according to the docs to get this curve.
    
        UIViewAnimationOptions animationOptions = animationCurve << 16;
    
    
        // Now we set up our animation block.
        [UIView animateWithDuration:animationDuration 
                              delay:0.0 
                            options:animationOptions 
                         animations:^{
                             // Now we just animate the text field up an amount according to the keyboard's height,
                             // as we mentioned above.
                            CGRect textFieldFrame = self.textField.frame;
                            textFieldFrame.origin.y = keyboardEndFrame.origin.y - textFieldFrame.size.height - 40; //I don't think the keyboard takes into account the status bar
                            self.textField.frame = textFieldFrame;
                         } 
                         completion:^(BOOL finished) {}];
    
    }
    
    
    - (void)keyboardWillHide:(NSNotification *)notification
    {
    
        NSNumber *animationDurationNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
        NSTimeInterval animationDuration = [animationDurationNumber doubleValue];
    
        NSNumber *animationCurveNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey];
        UIViewAnimationCurve animationCurve = [animationCurveNumber intValue];
        UIViewAnimationOptions animationOptions = animationCurve << 16;
    
        [UIView animateWithDuration:animationDuration 
                              delay:0.0 
                            options:animationOptions 
                         animations:^{
                             self.textField.frame = CGRectMake(20, 409, 280, 31); //just some hard coded value
                         } 
                         completion:^(BOOL finished) {}];
    
    }
    #pragma mark - View lifecycle
    
    - (void)viewDidUnload
    {
        [self setTextField:nil];
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
    }
    
    #pragma mark - UITextFieldDelegate
    
    - (BOOL)textFieldShouldReturn:(UITextField *)textField
    {
        [self.textField resignFirstResponder];
        return YES;
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-05 09:42

    UIViewControllers have a property called interfaceOrientation and the function UIInterfaceOrientationIsPortrait/Landscape so essentially you can do:

    if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation){
    //portrait logic
    }
    else{
    //landcapeLogic
    }
    

    inside for each the iPhone and iPad in your view controller. From there you can do your pixel measurement way as you had done before, because as far as I know that's the simplest way to do it.

    P.S. There is a function to check for landscape checker too, but if the first if statement is false meaning the device is not in portrait, then it must be in landscape hence the plain else.

    0 讨论(0)
  • 2020-12-05 09:43

    Using notification keyboard register , you can place your textfield inside a scroll and manage the content offset of scroll to turn the actual first responder above keyboard if it's neccesary.

    so after register controller to keybard appear , you must to obtain the gap between keyboard origin and scroll origin relative to parent.

    you must know if an specific first responder can change content offset of scroll, therefore is neccesary to know the possible bounds between keyboard origin and first responder.

    by the way you need to know the gap betwen the scroll content offset and the first responder for place your first responder in specific position.

    @interface MainViewController : UIViewController
    
      @property (strong, nonatomic) IBOutlet UIScrollView *scroll;
    
    @end    
    
    @interface MainViewController ()
    {
       CGPoint scrollOffset;
    }
    @end 
    
    @implementation MainViewController
    
    @synthesize scroll
    
    -(void)viewWillAppear:(BOOL)animated
     {
        [[ NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardDidShowNotification object:nil];
    
        [[ NSNotificationCenter defaultCenter ] addObserver:self selector:@selector(keyboardWillDisAppear:) name:UIKeyboardDidHideNotification object:nil];
    
     }
    
    
    -(void)viewWillDisappear:(BOOL)animated
     {
        [[ NSNotificationCenter defaultCenter ] removeObserver:self ];
     }
    
    -(void)keyboardWillAppear:(NSNotification*) note
     {
       const CGFloat default_gap = 25.0f;
    
       NSValue *keyBoardEndFrameValue = [[ note userInfo ] objectForKey:UIKeyboardFrameEndUserInfoKey ];
    
       CGRect keyBoardFrame = [ keyBoardEndFrameValue CGRectValue ];
    
    
       offset = scroll.contentOffset;
    
       UIWindow *window = [[ UIApplication sharedApplication ] keyWindow];
       UITextField *textField = (UITextField*)[ window performSelector:@selector(firstResponder) ];
    
       //Gap between keyboard origin and the scroll origin, relative to parent.
       CGFloat distanceRelativeToParent = keyBoardFrame.origin.y - scroll.frame.origin.y; 
    
    
       //Distance between superview to textfield inside scroll. to determine if it's necesary to scroll.
       CGFloat bound = (textField.frame.origin.y + textField.frame.size.height)+scroll.frame.origin.y; 
    
       CGFloat gapScroll = textField.frame.size.height+default_gap;
    
      if( bound >= keyBoardFrame.origin.y )
       {
         [ UIView animateWithDuration:.3 delay:0.0 options:UIViewAnimationCurveEaseOut 
       animations:^{
    
            [ scroll setContentOffset:CGPointMake(0, textField.frame.origin.y - distanceRelativeToParent +  gapScroll  ) animated:YES ];
    
       }
      completion:^(BOOL finished){
    
       }];
    }
    
    }
    
    -(void) keyboardWillDisAppear:(NSNotification*) note
    {   
       [ scroll setContentOffset:offset animated:YES ];
    }
    @end
    
    0 讨论(0)
提交回复
热议问题