【发布时间】:2015-07-13 15:44:57
【问题描述】:
我的问题与 UIScrollview 有关。让我们描述一下,
我有一个带有滚动视图的注册屏幕,最初滚动未启用。当键盘出现时,我将启用滚动视图,当键盘再次隐藏时,我将禁用滚动。我的滚动视图的宽度和高度与其默认视图相同,我在容器中应用了水平和垂直中心,并且顶部、底部、前缘和后缘为零(即它等于默认视图)。我有一个注册按钮,它导航到注册屏幕,并应用了底部约束(底部空间约束 = 0),我也在使用键盘通知来显示和隐藏。
实际问题: 当点击文本字段键盘出现时,滚动视图滚动,当我关闭键盘时,滚动视图下降,但这次注册按钮会向上移动一点(就像底部空间有 20 点限制)。
第一次它的类似滚动视图在状态栏之后启动,但是当键盘出现并隐藏它的类似滚动视图时,它会呈现包括状态栏在内的视图。
我需要在 IB 中添加与Top/Bottom Layout Guide 相关的任何约束吗?
还是我需要添加与viewDidLoad相关的任何约束
键盘通知代码。
-(void)keyboardWillShow:(NSNotification *)notification {
[self.navigationController.navigationBar setBackgroundImage:nil
forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = nil;
self.ContentScrollView.scrollEnabled=YES;
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardFrameInWindow;
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];
// the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
CGRect keyboardFrameInView = [self.ContentScrollView convertRect:keyboardFrameInWindow fromView:nil];
CGRect scrollViewKeyboardIntersection = CGRectIntersection(self.ContentScrollView.frame, keyboardFrameInView);
UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);
// this is an old animation method, but the only one that retains compatibility between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
[UIView animateWithDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0.0 options:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue] animations:^{
self.ContentScrollView.contentInset = newContentInsets;
self.ContentScrollView.scrollIndicatorInsets = newContentInsets;
/*
* Depending on visual layout, _activeField should either be the input field (UITextField,..) or another element
* that should be visible, e.g. a purchase button below an amount text field
* it makes sense to set _activeField in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
*/
if (_activeField) {
CGRect controlFrameInScrollView = [self.ContentScrollView convertRect:_activeField.bounds fromView:_activeField]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, 0); // replace 10 with any nice visual offset between control and keyboard or control and top of the scroll view.
CGFloat controlVisualOffsetToTopOfScrollview = (controlFrameInScrollView.origin.y - self.ContentScrollView.contentOffset.y)+10;
CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;
// this is the visible part of the scroll view that is not hidden by the keyboard
CGFloat scrollViewVisibleHeight = self.ContentScrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;
if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
// scroll up until the control is in place
CGPoint newContentOffset = self.ContentScrollView.contentOffset;
newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);
// make sure we don't set an impossible offset caused by the "nice visual offset"
// if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
CGFloat maxScrollViewHeight = MAX(self.ContentScrollView.frame.size.height, self.ContentScrollView.contentSize.height);
newContentOffset.y = MIN(newContentOffset.y, maxScrollViewHeight - scrollViewVisibleHeight);
[self.ContentScrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
} else if (controlFrameInScrollView.origin.y < self.ContentScrollView.contentOffset.y) {
// if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
CGPoint newContentOffset = self.ContentScrollView.contentOffset;
newContentOffset.y = controlFrameInScrollView.origin.y;
[self.ContentScrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
}
}
} completion:NULL];
}
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary *userInfo = [notification userInfo];
[UIView animateWithDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]doubleValue ] delay:0.01 options:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]intValue] animations:^{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.ContentScrollView.contentInset = contentInsets;
self.ContentScrollView.scrollIndicatorInsets = contentInsets;
CGPoint scrollPoint;
self.ContentScrollView.scrollEnabled=NO;
scrollPoint = CGPointMake(0.0, 0.0);
[self.ContentScrollView setContentOffset:scrollPoint animated:YES];
} completion:^(BOOL finished){
__weak typeof(self) weakSelf=self;
[weakSelf.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
weakSelf.navigationController.navigationBar.shadowImage = [UIImage new];
}];
}
图片
如果进一步需要,我将发送键盘通知前后的屏幕截图。
谢谢。
【问题讨论】:
-
将
self. automaticallyAdjustsScrollViewInsets=NO;写入viewDidLoad并尝试 -
谢谢,这是正确的,正如我所需要的。
-
欢迎。我已经回答了这个问题。您可以接受这一点,以便其他用户可以从中获得帮助。
标签: ios objective-c uiscrollview interface-builder uistatusbar