动画 UIView 在 TextField 焦点更改后更改框架位置

Animating UIView changes frame position after TextField focus change

重构我的代码后出现了一个奇怪的问题,值得发布并获得反馈,让我疯狂了一整天。

我有一个可重复使用的自定义控件,它的 XIB 包含一个带有子视图 3 UITextField(用户名、密码、电子邮件)的 UIView,假设它是一个注册输入框。我符合 UITextFieldDelegate 作用于键盘 接下来,Return 键盘按钮按下。

在我所有的观点中,我都非常谨慎地使用 AutoLayout 约束。

我在文件的所有者 UIView 后代自定义中初始化我的笔尖 class (SignUpInputView.m)。

- (void) setupView
    {
    self.view = [self loadViewFromNib];
    self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.bounds = self.view.bounds;
    _intrinsicContentSize = self.bounds.size;
    [self setTranslatesAutoresizingMaskIntoConstraints:NO];
    self.view.layer.borderWidth = 1.0f;
    self.view.layer.borderColor = [self greyColor];
    [self setupOutlets]; // I set the UITextFields delegate
    [self addSubview:self.view];
    }

// Override the intrinsicContectSize method

- (CGSize)intrinsicContentSize
    {
    return _intrinsicContentSize;
    }

在派生自 BaseViewController 的 LoginViewController 中,我将我的自定义控件与 属性 设置 getter 方法一起使用。

@property (strong, nonatomic, getter=getSignUpInputView) SignUpInputView* signUpInputView;

- (SignUpInputView*) getSignUpInputView
    {
    if (!_signUpInputView)
        {
        _signUpInputView = [SSESignUpInputView new];
        _signUpInputView.hidden = YES;
        _signUpInputView.alpha = 0.0f;
        [self.view addSubview:_signUpInputView];
        [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_signUpInputView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f]];
        [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_signUpInputView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0f constant:0.0f]];
        [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_signUpInputView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0.0f]];
        [_signUpInputView addConstraint:[NSLayoutConstraint constraintWithItem:_signUpInputView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_signUpInputView attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f]];
        }
    return _signUpInputView;
    }

我根据用户执行的操作(按下注册按钮、取消按钮)在 SignUpViewController 中处理隐藏属性和 alpha 属性。

在 SignUpViewController 中,当用户按下 SignUp 按钮时,我有一个方法。

- (IBAction)signupButtonTouchUpInside:(UIButton*)sender
    {
    // Call a method that sets some animations

    // Set some other animations here.
    [self.view layoutIfNeeded];
    [UIView transitionWithView:self.uploadPhotoButton duration:1.0f options:UIViewAnimationOptionTransitionFlipFromRight animations:
        ^{
        self.aView.alpha = 1.0f;
        self.anotherView.alpha = 0.0f;
        [self.view layoutIfNeeded];
        }
    completion:nil];

    SignUpInputView* signUpView = self.signUpInputView;
    signUpView.hidden = NO;
    [signUpView fullNameBecomeFirstResponder];
    // This is a method from the BaseViewController
    [super animateViewFromLeftOffsetOnTopOfKeyboard:signUpView];
    }

BaseViewController animateViewFromLeftOffsetOnTopOfKeyboard: 实现。

- (void) animateViewFromLeftOffsetOnTopOfKeyboard:(UIView*)view
    {
    // Execute with some delay to make sure I have the keyboard's height from the UIKeyboardDidChangeFrameNotification
    [self executeBlock:
        ^{
        CGFloat yInputView = self.view.bounds.size.height - [self keyboardHeight] - view.bounds.size.height/2;
        view.center = CGPointMake(-view.bounds.size.width, yInputView);
        view.alpha = 1.0f;
        [self.view layoutIfNeeded];
        [UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.8f initialSpringVelocity:0.0f options:UIViewAnimationOptionCurveEaseOut animations:
            ^{
            view.center = CGPointMake(view.bounds.size.width/2, yInputView);
            [self.view layoutIfNeeded];
            }
        completion:nil];
        }
    withDelay:0.7];
    }

一切正常,但现在我遇到了这个错误,好像它没有在 animateViewFromLeftOffsetOnTopOfKeyboard: 方法的 [UIView animateWithDuration:] 代码块中保留 view.center = CGPointMake(view.bounds.size.width/2, yInputView);

问题是,您点击初始 UITextField 以外的文本字段(全名,请参阅上面 signupButtonTouchUpInside: 方法中的代码)并且 SignUpInputView 立即移动到屏幕顶部。

我错过了一些东西,但事情是在将 NSLayoutConstraints 从 BaseController 重构到 getter 属性方法之前它正在工作,因为两次添加约束的崩溃,以及其他一般隐藏的 alpha 属性操作。

在这种情况下,您根本不应该设置任何框架。添加子视图,并为其设置约束以设置其初始位置;为您要修改的任何约束设置属性。要为视图设置动画,请将这些约束的常量值更改为您想要的值,然后在动画块中调用 layoutIFNeeded。