如何在 ios 运行时禁用约束?

Posted

技术标签:

【中文标题】如何在 ios 运行时禁用约束?【英文标题】:How to disable constraint at run time in ios? 【发布时间】:2015-07-08 11:48:40 【问题描述】:

我有一个视图,其中还有一些文本字段。我已经用 self 及其超级视图设置了视图的纵横比。现在,当我单击文本字段时,会出现键盘,我正在调整视图大小并设置其 y 位置,以便键盘不会覆盖文本字段。我正在使用下面的代码。

- (void)textFieldDidBeginEditing:(UITextField *)textField

    /* keyboard is visible, move views */
    if([textField isEqual:self.txt_twitter] || [textField isEqual:self.txt_linkedin])
    
        [UIView animateWithDuration:0.1f animations:^
         
             CGRect rect = self.view.frame;

             // 1. move the view's origin up so that the text field that will be hidden come above the keyboard
             // 2. increase the size of the view so that the area behind the keyboard is covered up.
             rect.origin.y -= 130;
            rect.size.height += 130;
             self.view.frame = rect;



         ];
    



- (void)textFieldDidEndEditing:(UITextField *)textField


    /* resign first responder, hide keyboard, move views */
    /* keyboard is visible, move views */
    if([textField isEqual:self.txt_twitter] || [textField isEqual:self.txt_linkedin])
    
        [UIView animateWithDuration:0.1f animations:^
         
             CGRect rect = self.view.frame;

             // revert back to the normal state.
             rect.origin.y += 130;
             rect.size.height -= 130;


             self.view.frame = rect;


         ];

    


现在,当我的视图高度增加时,它的宽度也会增加,因为我已经为此设置了约束。请告诉我如何解决这个问题。在这种情况下,我不想增加视图的宽度。

【问题讨论】:

要么完全使用自动布局,要么根本不使用它。您不应该手动编辑由自动布局控制的视图框架。 如果对您有帮助,请考虑接受我的回答。 【参考方案1】:

混合自动布局约束和直接帧操作通常是一个坏主意,您可能应该避免这种情况。我建议您为要移动/调整大小的视图的高度或位置约束制作一些 IBOutlets,并在委托回调中更改 constraint.constant 而不是更改帧。

此外,在处理键盘事件时,最好监听键盘通知 (UIKeyboardWillShowNotification),而不是使用文本字段委托方法。

添加了一个 gif 以更好地说明 -

项目中的一些代码:

- (void)viewDidLoad 
    [super viewDidLoad];

    [self addKeyboardNotificationsObserver];
    // Do any additional setup after loading the view, typically from a nib.


- (void)addKeyboardNotificationsObserver 

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];



- (void)handleKeyboardWillShow:(NSNotification *)paramNotification



    NSDictionary* info = [paramNotification userInfo];

    //when switching languages keyboard might change its height (emoji keyboard is higher than most keyboards).
    //You can get both sizes of the previous keyboard and the new one from info dictionary.

    // size of the keyb that is about to disappear
    __unused CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    // size of the keyb that is about to appear
    CGSize kbSizeNew = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    //make adjustments to constraints here...

    self.redSquareBottomConstraint.constant = kbSizeNew.height;

    //and this is where magic happens!

    [self.view layoutIfNeeded];



- (void)handleKeyboardWillHide:(NSNotification *)paramNotification


    //adjust constraints

    self.redSquareBottomConstraint.constant = 0;

    [self.view layoutIfNeeded];



- (void)dealloc 

    [[NSNotificationCenter defaultCenter] removeObserver:self];


从代码中可以看出,我们从通知附带的 userInfo 字典中提取键盘的大小。正如 nhgrif 所指出的,您可以从中提取一些其他有价值的信息,例如键盘出现/分散器时动画的持续时间(key - UIKeyboardAnimationDurationUserInfoKey)或曲线(key - UIKeyboardAnimationCurveUserInfoKey) .文档here。如果您想要特定的动画行为,您可以将布局调用包装在动画块中,如下所示:

[UIView animateWithDuration:duration
                 animations:^

    [self.view layoutIfNeeded];

];

【讨论】:

最佳答案。这正是我的做法。我们不需要添加或删除任何约束或设置任何内容插入(就像某些与滚动视图和滚动视图子类一样)。只需为底部边缘设置一个约束,并在键盘出现/消失时设置其常量。我对这个答案的唯一抱怨是我们没有像我们应该的那样用他们的键盘来动画变化。 这就是我要说的。我们还没有从通知信息中提取动画持续时间或动画曲线,这是我们应该做的。这是我对这个答案的唯一抱怨。 @nhgrif 用有关此事的更多信息更新了我的答案。由于某种原因,即使没有动画块,键盘动画也会使用精确的动画参数进行布局。这是我不小心注意到但仍在使用的东西。不知道为什么会这样。【参考方案2】:

只需为宽度约束创建 IBOutlet 并在更改框架高度时重新分配它!

【讨论】:

这个问题是在问如何这样做。 这就是我所说的,我认为我的回答对@deepk kumar 来说非常清楚

以上是关于如何在 ios 运行时禁用约束?的主要内容,如果未能解决你的问题,请参考以下文章

如何在按钮单击时在一个视图控制器中正确启用和禁用约束

如何以编程方式禁用主键约束?

如何在单击按钮时在一个视图控制器中正确启用和禁用约束

在 iOS 运行时禁用 crashlytics/Fabric

如何在智能手机中运行网络应用程序时禁用任何来电?

XCUITest - 如何在应用程序运行时禁用 Wi Fi?