Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c UIC键盘避免和自动布局_Objective C_Ios_Cocoa Touch_Uiviewcontroller_Ios6 - Fatal编程技术网

Objective c UIC键盘避免和自动布局

Objective c UIC键盘避免和自动布局,objective-c,ios,cocoa-touch,uiviewcontroller,ios6,Objective C,Ios,Cocoa Touch,Uiviewcontroller,Ios6,考虑到iOS 6中对自动布局的关注,以及苹果工程师的建议(见WWDC 2012视频),即我们不再直接操作视图的框架,如何避免仅使用自动布局和NSLAYOUTSCONSTRAINT来使用键盘 更新 这看起来是一个合理的解决方案:(但我看到的一个潜在问题是,当用户旋转设备并且键盘已经在屏幕上时会发生什么?对于键盘外壳的自动布局,我使用静态表格视图。这使代码更简单,不需要跟踪键盘高度。关于表格视图,我学到的一件事是使每个表格行尽可能窄。)le.如果在一行中垂直放置太多UI,可能会出现键盘重叠。我的想法

考虑到iOS 6中对自动布局的关注,以及苹果工程师的建议(见WWDC 2012视频),即我们不再直接操作视图的框架,如何避免仅使用自动布局和NSLAYOUTSCONSTRAINT来使用键盘

更新


这看起来是一个合理的解决方案:(但我看到的一个潜在问题是,当用户旋转设备并且键盘已经在屏幕上时会发生什么?

对于键盘外壳的自动布局,我使用静态表格视图。这使代码更简单,不需要跟踪键盘高度。关于表格视图,我学到的一件事是使每个表格行尽可能窄。)le.如果在一行中垂直放置太多UI,可能会出现键盘重叠。

我的想法是创建一个
UIView
,我们称之为键盘视图,并将其放置到视图控制器的视图中。然后观察键盘帧更改通知
UIKeyboardDidChangeFrameNotification
,并将键盘帧与ke匹配yboard视图(我建议设置更改的动画)。观察此通知可以处理您提到的旋转,还可以在iPad上移动键盘

然后简单地创建与此键盘视图相关的约束。不要忘记将约束添加到它们的公共superview


要将键盘框架正确地转换和旋转到视图坐标,请查看
UIKeyboardFrameEndUserInfoKey

的文档。我创建了这样一个视图,当键盘打开/关闭屏幕时,它可以观察键盘并更改自身的约束

@interface YMKeyboardLayoutHelperView ()
@property (nonatomic) CGFloat desiredHeight;
@property (nonatomic) CGFloat duration;
@end

@implementation YMKeyboardLayoutHelperView

- (id)init
{
    self = [super init];
    if (self) {
        self.translatesAutoresizingMaskIntoConstraints = NO;

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:@"UIKeyboardWillShowNotification" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:@"UIKeyboardWillHideNotification" object:nil];
    }
    return self;
}

- (void)keyboardWillShow:(NSNotification *)notification
{
    // Save the height of keyboard and animation duration
    NSDictionary *userInfo = [notification userInfo];
    CGRect keyboardRect = [userInfo[@"UIKeyboardBoundsUserInfoKey"] CGRectValue];
    self.desiredHeight = CGRectGetHeight(keyboardRect);
    self.duration = [userInfo[@"UIKeyboardAnimationDurationUserInfoKey"] floatValue];

    [self setNeedsUpdateConstraints];
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    // Reset the desired height (keep the duration)
    self.desiredHeight = 0.0f;

    [self setNeedsUpdateConstraints];
}

- (void)updateConstraints
{
    [super updateConstraints];

    // Remove old constraints
    if ([self.constraints count]) {
        [self removeConstraints:self.constraints];
    }

    // Add new constraint with desired height
    NSString *constraintFormat = [NSString stringWithFormat:@"V:[self(%f)]", self.desiredHeight];
    [self addVisualConstraints:constraintFormat views:@{@"self": self}];

    // Animate transition
    [UIView animateWithDuration:self.duration animations:^{
        [self.superview layoutIfNeeded];
    }];

}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

这篇博文很棒,但我想对它提出一些改进建议。首先,你可以注册来观察帧的变化,所以你不需要注册来观察显示和隐藏通知。其次,你应该将键盘的CGRECT从屏幕坐标转换为视图坐标。最后,你可以复制iOS f使用的精确动画曲线或者键盘本身,因此键盘和跟踪视图同步移动

综上所述,您可以得到以下结果:

@interface MyViewController ()
// This IBOutlet holds a reference to the bottom vertical spacer
// constraint that positions the "tracking view",i.e., the view that
// we want to track the vertical motion of the keyboard
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomVerticalSpacerConstraint;
@end


@implementation MyViewController
-(void)viewDidLoad
{
  [super viewDidLoad];
  // register for notifications about the keyboard changing frame
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(keyboardWillChangeFrame:)
                                               name:UIKeyboardWillChangeFrameNotification
                                             object:self.view.window];
}

-(void)keyboardWillChangeFrame:(NSNotification*)notification
{
  NSDictionary * userInfo = notification.userInfo;
  UIViewAnimationCurve animationCurve  = [userInfo[UIKeyboardAnimationCurveUserInfoKey] intValue];
  NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

  // convert the keyboard's CGRect from screen coords to view coords
  CGRect kbEndFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]
                                    fromView:self.view.window];
  CGRect kbBeginFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]
                                      fromView:self.view.window];
  CGFloat deltaKeyBoardOrigin = kbEndFrame.origin.y - kbBeginFrame.origin.y;

  // update the constant factor of the constraint governing your tracking view
  self.bottomVerticalSpacerConstraint.constant -= deltaKeyBoardOrigin;
  // tell the constraint solver it needs to re-solve other constraints.
  [self.view setNeedsUpdateConstraints];

  [UIView beginAnimations:nil context:NULL];
  [UIView setAnimationDuration:duration];
  [UIView setAnimationCurve:animationCurve];
  [UIView setAnimationBeginsFromCurrentState:YES];
  // within this animation block, force the layout engine to apply 
  // the new layout changes immediately, so that we
  // animate to that new layout. We need to use old-style
  // UIView animations to pass the curve type.
  [self.view layoutIfNeeded];
  [UIView commitAnimations];
}

-(void)dealloc {
  [[NSNotificationCenter defaultCenter] removeObserver:self
                                                  name:UIKeyboardWillChangeFrameNotification
                                                object:nil];
}
@end
只要你在键盘打开时不改变方向,这就行了

这是一个关于如何正确模拟键盘动画曲线的答案


对于所有这些基于通知的解决方案,最后要注意的一点是:如果应用程序中的其他屏幕也使用了键盘,它们可能会产生意外的效果,因为只要视图控制器尚未解除分配,即使其视图已卸载,视图控制器仍将接收通知。解决此问题的一个方法是通知处理程序中的一个条件,以确保它仅在视图控制器在屏幕上时运行。

我编写了一个库,可以为您完成所有操作(支持自动布局和Springs&Struts)

键盘回避

只需调用[IHKeyboardAvoidingView:self.myView];

在框架中使用是迄今为止我找到的最简单的解决方案。

以链接中的示例为例,我将重构代码以计算
键盘高度
,并添加
willRotateToInterfaceOrientation:
和/或
WillAnimateRotationInterfaceOrientation:
根据需要调用以更新键盘高度约束。
UIKeyboard将显示通知
notif当键盘的大小因旋转而改变时,也会发布通知,因此您不必担心。+1对于有趣的链接,以这种方式使用代理视图效果非常好;好主意!我已经实现了这样一个视图,请免费使用:3我编写了一个库,可以为您完成所有操作(支持自动布局和Springs&Struts)这是一个使用自动布局处理编辑表单的优雅解决方案。许多通知应该在ViewWillDisplay中注册,而在ViewWillEnglishe中取消注册。@StevenCramer我的印象是(1)ViewWillDisplay和ViewWillEnglish不是可靠的平衡调用,以及(2)在许多情况下,当视图可见时(应用程序恢复活动等),视图将特别显示。因此,我不确定如何最好地使用它们来管理通知。你有什么具体的想法吗?过去经常发生这种情况,但现在(iOS 5+)并没有这样的问题。事实上,如果您仍然有不平衡的外观消息,我建议您立即修复。或者解决它,如果它是一个框架问题。哦,wrt到“应用程序恢复活动”。事实上,不获取
viewWill(Dis)显示
消息是正确的。“外观”提到的是视图在应用程序窗口中的外观,而不是在设备屏幕上。对于我来说,我使用的是iOS 8,消息出现两次。一次是框架进入我的视图,另一次是通知我它进入视图外的位置。因此-=正在将其丢弃。我必须添加一个位置检查,以查看它是否正确远距视图/屏幕的大小[code]!(kbbeginrame.origin.y>self.window.frame.size.height | | kbEndFrame.origin.y>self.window.frame.size.height);[code]+1,不是因为这是所有情况下的最佳解决方案,而是如果您的项目已经在使用Spring框架,那么这就是最好的解决方案。无需使用该框架,只需将KeyboardLayoutConstraint.swift文件复制到您的项目中,并随意使用它。提醒使用此策略的人,KeyboardLayoutConstraint不能处理bluetooth keyb正确发送通知。请参阅此处了解解决方案: