iOS 7 -- navigationController正在设置我的UIScrollView的contentInset和ContentOffset

69
我有一个UIScrollView(实际上是一个UICollectionView,但这可能并不重要)。 在iOS 7中,当出现导航控制器时,它会设置contentInset和contentOffset的值,而我并不想要这些值。 它似乎试图调整状态栏和导航栏。 我希望它能保持原样。 我通过覆盖contentInset和contentOffset的getter和setter方法,并使用一个标志来告诉对象是否应接受设置来解决了这个问题。 但是有没有更好的方法呢?
7个回答

206

尝试在主视图控制器中设置 self.automaticallyAdjustsScrollViewInsets = NO

这是在 iOS 7 中引入的,所以如果您支持 iOS 6 及以下版本,则可能需要将其包装在 iOS 版本检查中。


更新

如果您正在使用故事板,则可以通过选中控制器并检查 '调整滚动视图插页' 来在界面构建器中执行此操作。

enter image description here


7
只有在使用故事板时,你才能在IB上进行设置。 - jerrygdm
残酷的是,IB显示这个配置不正确;即使打开了这个标志,它在IB中仍然显示为关闭状态...如果你启动模拟器,标志会按预期工作,这让你完全困惑-.- 这是一个恶意设置!:-) - Ursin Brunner
我花了一天的时间来弄清楚为什么我的ImageView与我的scrollView不在左上角居中。在关闭这个选项后,所有的问题都解决了! - Zhenyi Zhang
1
这个“调整滚动视图插图”选项到底是做什么的? - Yakiv Kovalskyi
@KDaker - 我和Yakiv一样...这解决了我的问题(谢谢!!!),但我想知道那个选项首先是在做什么,而且在其他地方也没有找到任何好的信息。谢谢! - Spencer

25

我也遇到了类似的问题,当我关闭一个viewController后,我的tableView的contentOffset被改变为(0,-64)。

我试过所有其他的答案,但都没有成功,唯一解决我的问题的方法是在.xib文件中切换tableView在控件树中的位置。

之前tableView是父视图中的第一个控件,如下所示:

before

我将tableView移动到ImageView之后即可,如下所示:

after

看起来将tableView放在第一位引起了问题,而将tableView移动到其他位置则解决了问题。

P.S. 我没有使用autoLayout和storyboards。

希望这可以帮助到别人!


我的问题也是iOS 7的bug吗? - Cyril
2
你真是个明星!从没想过scrollview的顺序可能是问题所在。 - Andrew L.
4
发生这种情况的原因可以从已接受的答案中得到提示。UIViewController将自动设置第一个UIView的contentInset。通过将UITableView放置在第二个视图,就不会自动设置其contentInset。 - Michael McGuire
Michael,很遗憾不是这样的。在我的情况下,控制器属性没有被选中(false),但我仍然得到了奇怪的插图。在viewWillAppear中更改插图为0也没有帮助。但将其移动到视图层次结构中有所帮助。真的是一个非常奇怪的错误。 - Michał Hernas
谢谢!我永远不会发现这个问题,实际上我必须为ViewController添加一个空视图来解决它。 - Buyin Brian
哇,这很奇怪,我也遇到了同样的问题,通过添加一个虚拟视图可以解决。 - user1055568

5
我可以提供两个解决方案:
1.

第一个方案:

self.view = scrollView;

2.

[self.navigationController.toolbar setTranslucent:NO];

1
谢谢您,我需要在第二个示例中使用NavigationBar而不是toolbar,例如navigationController.NavigationBar.Translucent = false;(注意:Xamarin),这样可以正常工作。 - ta.speot.is

2
我遇到了同样的问题。
  1. Setting self.automaticallyAdjustsScrollViewInsets = NO solved the issue for some of the view but not everywhere.

  2. Second solution is to set the content-offset of tableview/view/scrollview in viewWillLayoutSubviews:

    - (void)viewWillLayoutSubviews {
        //Arrange the view
        CGRect tempViewFrame = self.view.frame;
    
        if (tempViewFrame.origin.y == 64.0f) {
            tempViewFrame.origin.y = 0;
            self.view.frame = tempViewFrame;
        }
    }
    

0

这就足够了

- (void)viewDidLoad {

    [super viewDidLoad];

    self.automaticallyAdjustsScrollViewInsets = NO;

0
其他答案可能对你有用,但对我却没用。对我有用的是手动设置viewDidLayoutSubviewsviewWillAppear中的contentOffsety属性:
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Set the offset to go below the status bar
    collectionView.contentOffset.y = -UIApplication.shared.statusBarFrame.height
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Set the offset to go below the status bar
    collectionView.contentOffset.y = -UIApplication.shared.statusBarFrame.height
}

在我的情况下,我的控制器有一个子集合视图,有时会调整contentOffset,有时不会。我规范化的方法是每次手动调整它。我希望内容偏移至状态栏下方,因此我使用状态栏高度作为值(负数,因为我希望内容向下推)。

0

这将在以下两种情况下解决问题:

  1. 显示状态栏
  2. 显示状态栏和导航栏

    override func viewDidLayoutSubviews() {
            NSLog("ORIGIN: \(self.view.frame.origin.y)")
    
        if self.view.frame.origin.y == 0 {
            if let rect = self.navigationController?.navigationBar.frame {
                let y = rect.size.height + rect.origin.y
                self.tableView.contentInset = UIEdgeInsetsMake(y, 0, 0, 0)
            }
        } else if self.view.frame.origin.y == 44 || self.view.frame.origin.y == 64 {
            self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
        }
    }
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接