ios - UIScrollview 是否与 UIStatusbar 一起正常工作?

标签 ios objective-c uiscrollview interface-builder uistatusbar

我的问题与 UIScrollview 有关。让我们描述一下,

我有一个带有 ScrollView 的注册屏幕,最初没有启用滚动。当键盘出现时,我将启用 ScrollView ,当键盘再次隐藏时,我将禁用滚动。我的 ScrollView 的宽度和高度与其默认 View 相同,我在容器中应用了水平和垂直中心以及顶部、底部、前导和尾部边缘为零(即它等于默认 View )。我有一个导航到注册屏幕的注册按钮,并应用了底部约束(底部空间约束 = 0),我还使用键盘通知来显示和隐藏。

实际问题: 当点击文本字段键盘出现时, ScrollView 滚动,当我关闭键盘时, ScrollView 下降,但这次注册按钮会向上移动一点点(比如底部空间有 20 点限制)。

第一次它像 scrollview 在状态栏之后启动,但是当键盘出现和隐藏时它像 scrollview 是在包括状态栏的 View 上呈现。

我是否需要在 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];
    }];

}

图片 IB Screen shot

如果进一步需要,我将发送键盘通知前后的屏幕截图。

谢谢。

最佳答案

来自 Documentation

A Boolean value that indicates whether the view controller should automatically adjust its scroll view insets.

声明

@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets

讨论

Default value is YES, which allows the view controller to adjust its scroll view insets in response to the screen areas consumed by the status bar, navigation bar, and toolbar or tab bar. Set to NO if you want to manage scroll view inset adjustments yourself, such as when there is more than one scroll view in the view hierarchy.

自己写。 automaticallyAdjustsScrollViewInsets=NO;viewDidLoad 中尝试

关于ios - UIScrollview 是否与 UIStatusbar 一起正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30027037/

相关文章:

ios - 使用 Swift 和 CoreGraphics 定位图像

objective-c - 操作完成后更改页面

ios - 从 UINavigationController 堆栈转出到 UITabBarController

iphone - 如何像 UITableView 一样重新排序 UIScrollView 行

ios - 推送通知在分发中不起作用

objective-c - 模态 segue 无过渡

ios - 如何从 for 循环创建多个 UIButton

iphone - IOS帮助修改代码片段

ios - 如何以编程方式显示图像水平 UIscrollView

iphone - 实现自定义动画以在 iPad 上从指定 View 呈现模态视图