【问题标题】:iOS 7 Table view fail to auto adjust content insetiOS 7 表格视图无法自动调整内容插入
【发布时间】:2013-10-06 04:04:27
【问题描述】:

我正在将我的项目转移到 iOS7。我面临一个与半透明导航栏相关的奇怪问题。

我有一个视图控制器,它有一个表视图作为子视图(我们称之为 ControllerA)。我用 controllerA 初始化了一个新的 uinavigationcontroller,并使用 presentviewcontroller 以模态方式呈现它。呈现的视图控制器的表格视图被导航栏挡住了。我将 automaticallyAdjustsScrollViewInsets 设置为 YES 但结果没有改变。 我知道我可以将 edgesForExtendedLayout 设置为 UIRectEdgeNone,但它会使导航栏不再透明。

之后,我尝试创建一个新的视图控制器进行测试。它包含几乎相同的元素。但结果却大不相同。表格视图内容不会被阻止。

结论

  1. 两个视图控制器的自动AdjustsScrollViewInsets 设置为YES
  2. 项目未使用情节提要
  3. 第一个是在 Xcode 4.6 上创建的,第二个是在 Xcode 5 上新创建的
  4. 我对比了xib和code两个类,差别不大

【问题讨论】:

    标签: iphone objective-c uitableview ios7


    【解决方案1】:

    Swift 2 中的@Christopher Pickslay 解决方案:

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        let topInset = topLayoutGuide.length
        inTableView.contentInset.top = topInset
        inTableView.contentOffset.y = -topInset
        inTableView.scrollIndicatorInsets.top = topInset
    }
    

    【讨论】:

      【解决方案2】:

      可能已经有太多答案了,但我不得不采用 Christopher 的解决方案并稍微修改它以支持视图调整大小允许在 UIViewController 的子类中更改内容插入.

      @interface MyViewController ()
      
      @property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
      @property (assign, nonatomic) UIEdgeInsets scrollViewInitialContentInset;
      
      @end
      
      
      @implementation MyViewController
      
      - (void)viewDidLoad {
          [super viewDidLoad];
      
          [self setScrollViewInitialContentInset:UIEdgeInsetsZero];
      }
      
      - (void)viewWillLayoutSubviews {
          [super viewWillLayoutSubviews];
      
          if (UIEdgeInsetsEqualToEdgeInsets([self scrollViewInitialContentInset], UIEdgeInsetsZero)) {
              [self setScrollViewInitialContentInset:[self.scrollView contentInset]];
          }
      }
      
      - (void)viewDidLayoutSubviews {
          [super viewDidLayoutSubviews];
      
          UIEdgeInsets scrollViewInset = [self scrollViewInitialContentInset];
      
          if (UIEdgeInsetsEqualToEdgeInsets(scrollViewInset, UIEdgeInsetsZero) {
      
              if ([self respondsToSelector:@selector(topLayoutGuide)]) {
                  scrollViewInset.top = [self.topLayoutGuide length];
              }
      
              if ([self respondsToSelector:@selector(bottomLayoutGuide)]) {
                  scrollViewInset.bottom = [self.bottomLayoutGuide length];
              }
      
              [self.scrollView setContentInset:scrollViewInset];
          }
      }
      
      @end
      

      解释一下:

      MyViewController 的任何子类现在都可以在viewDidLoad 中修改scrollViewcontentInset 并且将得到尊重。但是,如果scrollViewcontentInsetUIEdgeInsetsZero:它将扩展为topLayoutGuidebottomLayoutGuide

      【讨论】:

      • 美丽实用的答案!如果 Apple 提前考虑到这一点,并且以某种方式为 UITableViewController 或视图控制器的最顶层视图(如果它是可滚动的)提供此功能,而且还为滚动视图可以深入视图层次结构的任何可能场景提供此功能,那就太好了。
      【解决方案3】:

      如果您希望视图位于导航栏下方,但也希望将其定位,以便滚动视图内容的顶部默认位于导航栏下方,您可以在布局视图后手动添加顶部插图。这本质上就是顶层视图是滚动视图时视图布局系统所做的。

      -(void)viewDidLayoutSubviews {
          if ([self respondsToSelector:@selector(topLayoutGuide)]) {
              UIEdgeInsets currentInsets = self.scrollView.contentInset;
              self.scrollView.contentInset = (UIEdgeInsets){
                  .top = self.topLayoutGuide.length,
                  .bottom = currentInsets.bottom,
                  .left = currentInsets.left,
                  .right = currentInsets.right
              };
          }
      }
      

      【讨论】:

      • 谢谢,这对我的特殊情况很有用:我在UIPageViewController 中有一个UICollectionViewController,后者被推到UINavigationController 上。 pageViewController 的内部 scrollView 会阻止 automaticallyAdjustsScrollviewInsets 正常工作。不幸的是,topLayoutGuide 也没有正确设置,但我仍然可以手动获取导航栏的偏移量:CGFloat topOffset = self.navigationController.navigationBar.frame.origin.y + self.navigationController.navigationBar.frame.size.height
      • 我有这个问题大概 2 天,但无法弄清楚.. 这应该是 50+
      • 不应该也叫[super viewDidLayoutSubviews];吗?
      • @Koen 在技术上我想是的。默认实现是无操作的,所以只有当你有一个也实现它的自定义中间超类时才重要。
      【解决方案4】:

      根据 Tony 的回答,我能够以编程方式解决这个问题,暂时将表格视图发送到后面,进行调整,然后将背景视图发送回后面。就我而言,这种方法没有闪烁。

      在视图控制器中:

      
      - (void)viewWillLayoutSubviews {
          [super viewWillLayoutSubviews];
      
          [self.view sendSubviewToBack:self.tableView];
      }
      
      - (void)viewDidLayoutSubviews {
          [super viewDidLayoutSubviews];
      
          [self.view sendSubviewToBack:self.backgroundView];
      }
      

      显然,如果self.view 上还有其他子视图,您可能也需要重新排序。

      【讨论】:

      • 这对我不起作用。首先出现一个错误,需要我在 DidLayoutSubviews 中调用 - (void) layoutSubviews,之后,我的 tableView 插入仍然不正确。甚至尝试在您的方法中切换视图,但仍然无效。
      • 这看起来很有希望和鼓舞人心,但它对我也不起作用。
      • 它可以工作,但可能取决于您将代码放在哪里。起初我把它放在 viewdidload 中并没有工作。现在它在数据到来后稍后被调用。我在 tableview 下的视图是空表的占位符。不确定是否有更好的做法,但我需要拉动刷新功能和背景保持原位,这就是这个设置的原因。
      【解决方案5】:
      [self.navigationController setNavigationBarHidden:YES animated:YES]; 
      

      在:

      - (void)viewDidLoad 
      

      【讨论】:

        【解决方案6】:

        是的 - 有点烦人。

        我在主视图中有一个带有单个表视图的笔尖,不使用自动布局。有一个标签栏、导航栏和一个状态栏,应用程序需要恢复到 5.0。在界面生成器中,整洁的“在 iOS7 和 iOS6.1 中并排查看”的东西可以正常工作,显示表格整齐合适(一旦 iOS6/7 增量设置正确)。

        但是在设备或模拟器上运行时,表格顶部有一个很大的差距,这是由于内容插入(与 iOS6/7 垂直增量几乎匹配)在笔尖。

        我得到的唯一解决方案是在 viewWillAppear 中放入 [_tableView setContentInset:UIEdgeInsetsZero]。

        另一个丑陋的 hack,屏幕上的结果很漂亮.....

        【讨论】:

        • 你尝试设置 self.edgesForExtendedLayout = UIRectEdgeNone;它可以禁用内容插入自动填充。
        【解决方案7】:

        我在苹果开发者论坛上找到了答案。 有两种不同的情况。

        第一个,添加的视图控制器是一个UITableViewController。 而且这个问题不应该出现,因为苹果会自动填充它。

        第二个,视图控制器不是 UITableViewController。 在视图层次结构中,它包含一个 UITableView。在这种情况下,如果 UITableview(或 ScrollView)是 viewController 的主视图或主视图的第一个子视图,它将起作用。否则,视图控制器不知道要填充哪个滚动视图,就会出现问题。

        在我的例子中,视图控制器是第二个。并且有一个背景图像视图作为主视图的第一个子视图。所以,它失败了。

        这是 Apple 开发者论坛链接(需要开发者帐户才能访问): https://devforums.apple.com/message/900138#900138

        【讨论】:

        • 我有同样的问题,由于背景图像视图,滚动视图是主视图中的第二个子视图。您找到解决方法了吗?
        • 那你为什么不分享修复?
        • 注意:如果您以编程方式进行自动布局,您可能会有类似 id topGuide = self.topLayoutGuide; 的内容,我发现在将 UITableView 作为第一个子视图添加到我的 UIViewController 之前有该行(在viewDidLoad) 停止了自动填充工作...
        • 并非总是如此。您可以在非UITableViewController 中获得自动填充(至少我知道了)。子视图顺序在那里很有意义。如果您的tableView 是控制器view 中的子视图#0,它将自动调整。否则,它将保持原样。
        • @Cemen 当我设置navigationBar.translucent = NO; 时,即使tableView 是subview#0 我也有问题。我工作的时候navigationBar.translucent = YES;
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-24
        • 2017-07-16
        • 2019-04-13
        • 2016-07-07
        • 2013-10-12
        • 2013-06-23
        相关资源
        最近更新 更多