【问题标题】:table view slides up under navigation bar when user taps row当用户点击行时,表格视图在导航栏下向上滑动
【发布时间】:2014-01-20 11:52:59
【问题描述】:

我有一个 UINavigationController (NC),其中包含一个 UITableViewController (TVC0)。当用户点击一行时,它会加载一个UIPageViewController (PVC),它会在其他UITableViewControllers (TVC1) 之间来回翻页。

TVC0 显示在 NC 内部(意味着它不会隐藏在顶部的导航栏或底部的标签栏后面)。当它推动 PVC 时,第一个 TVC1 出现在导航栏和标签栏的边界内。但是,当我滑动时,里面的 TVC1 隐藏在导航栏和标签栏后面。我可以拉动以显示内容,但当我松开时,它会弹回栏杆后面。

如何强制所有内容出现在两个栏之间?我不能使用故事板(因为它是一个旧版应用程序)并且嵌入... 选项不可用。

[编辑]

我添加了一些日志记录,发现我的嵌入式 TVC1s 帧的绝对原点为 0、64,但我一点击,它就变为 0、0。如果我无法找到真正的解决方案,我可以总是通过添加 64 来伪造它,但我更愿意弄清楚实际上是什么问题。

[/编辑]

[更多编辑]

我在 iOS 6 模拟器中测试了另一个区域,发现此分页在 iOS 6 中完美运行。所以我看到的问题是 iOS 7 特定的。

[/更多编辑]

这是我的 TVC0 viewDidLoad、PVC pageViewController:viewControllerBeforeViewController: 和一个助手 viewControllerAtIndex:

- (void) viewDidLoad
{
    [super viewDidLoad];
    NSDictionary* options = [NSDictionary dictionaryWithObject:
                             [NSNumber numberWithInteger: UIPageViewControllerSpineLocationMin]
                                                        forKey:
                             UIPageViewControllerOptionSpineLocationKey];
    self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:
                           UIPageViewControllerTransitionStyleScroll
                                                          navigationOrientation:
                           UIPageViewControllerNavigationOrientationHorizontal
                                                                        options: options];

    self.pageController.dataSource = self;
    self.pageController.view.frame = self.view.frame;
    NSArray* viewControllers =
            [NSArray arrayWithObject: [self viewControllerAtIndex: self.initialIndex]];

    [self.pageController setViewControllers: viewControllers
                                  direction: UIPageViewControllerNavigationDirectionForward
                                   animated: NO
                                 completion: nil];

    [self addChildViewController: self.pageController];
    [self.view addSubview: self.pageController.view];
    [self.pageController didMoveToParentViewController: self];

    for (UIGestureRecognizer* recognizer in self.pageController.gestureRecognizers)
    {
        if ([recognizer isKindOfClass: [UITapGestureRecognizer class]])
        {
            recognizer.enabled = NO;
        }
    }
}

// SearchResultsList is TVC1
- (SearchResultsList*) viewControllerAtIndex: (NSUInteger) index
{
    if (index >= self.items.count)
    {
        return nil;
    }

    SearchResultsList* retVal = [[SearchResultsList alloc]
                                    initWithNibName: @"SearchResultsList" bundle: nil];

    MyListItem* myItem = [self.items objectAtIndex: index];
    MyMatchesRequest* matches = [[MyMatchesRequest alloc] initWithItemId: myItem.itemId];
    [matches execute: ^(MySearchResults* results)
     {
         retVal.tableData = [NSMutableArray arrayWithArray: results.items];
         retVal.view.frame = self.view.frame;
         retVal.myItem = myItem;
         retVal.index = index;
         self.title = myItem.displayText;
         [[retVal tableView] reloadData];
     }];

    return retVal;
}

- (UIViewController*) pageViewController: (UIPageViewController*) pageViewController
      viewControllerBeforeViewController: (UIViewController*) viewController
{
    SearchResultsList* vc = (SearchResultsList*)viewController;
    if (vc.index == 0)
    {
        [self.navigationController popViewControllerAnimated: YES];
        return nil;
    }

    return [self viewControllerAtIndex: vc.index - 1];
}

【问题讨论】:

  • 每个视图控制器的自动布局是打开还是关闭?
  • @foundry:关闭。我尝试了两种方法,但没有任何帮助。
  • 我遇到了完全相同的问题,我花了 +100 赏金,但我得到了它的工作:stackoverflow.com/questions/20258933/…。基本上尼克格拉索所说的有效。你在那个屏幕上也有一个 UINavigationBar 吗?如果您确实查看是否可以更改不透明度。如果它没有被看穿,它似乎也可以解决这个问题。

标签: ios uinavigationcontroller uitableview uipageviewcontroller


【解决方案1】:

您的代码似乎有点混乱。您说它是您的页面视图控制器的viewDidLoad,但它创建了一个新的 PVC 并将其作为子视图控制器添加到自身作为父视图控制器。如果您真的这样做,那么您就是在另一个 PVC 中创建一个 PVC。我怀疑这是你想要的。

这段代码确实属于 TVC0,它在用户点击一行时调用 PVC。这个调用在viewDidLoad 中是不正确的,但在didSelectRowAtIndexPath 方法中可能很好。我们可以简单地将其推送到我们的 navigationController 的堆栈中,而不是将其作为子控制器引入。 (我希望你在最外面的 PVC 中无论如何都会这样做)。

但以防万一,我会删除这三行:

    [self addChildViewController: self.pageController];
    [self.view addSubview: self.pageController.view];
    [self.pageController didMoveToParentViewController:self];

并将它们替换为

    [self.navigationController pushViewController:self.pageController 
                                         animated:YES];

(这是从您的 TVC0 调用的 - 您显示的所有代码都可以存在于 TVC0 中)

然后为了防止您描述的行为,当您创建 UINavigationController 时,将其 navigationBartranslucent 属性设置为 NO 就足够了。

更新

我已经对这个问题进行了足够详细的研究,可以看到一些您描述的错误行为发生在一些情况下,但它很难复制。

“跳跃”行为的原因很明确。如果您有一个半透明的导航栏,并且它的 automaticallyAdjustsScrollViewInsets 设置为 YES,在某些情况下,这可能会导致 pageViewController (_UIQueuingScrollView) 的私有子视图将其 contentOffset.y 设置为 -64首次加载 pageViewController 时。然而,一旦 pageVC 有机会更新自身(例如通过滑动或其他触摸手势),它就会重置其内部子视图状态,从而丢失该流氓 contentOffset。因此,当您触摸第一页时,它会跳起来。然后它停留在哪里。这可能被认为是一个错误,尽管它可能是滥用 pageViewController 的结果。

仅将automaticallyAdjustsScrollViewInsets 设置为 NO 并不能治愈您的弊病,因为您的页面都位于导航栏后面。您需要做的是调整 pageViewController 本身的框架。

我可以更详细地介绍,但由于您的应用设计看起来有点奇怪,因此很难将答案应用到您的具体案例中,这可能是导致问题的原因。

  • 如果您可以将导航控制器的导航栏的 translucent 属性设置为 NO,问题应该会消失。

  • 正如我之前提到的,我无法完全按照您的描述复制您的问题,所以我认为您没有对您的应用设计给出完整而清晰的描述

  • 将 pageViewController 作为 tableViewController 的子项加载,并使其成为 tableView 的子视图,这是一种非常奇怪的方法,无疑会导致您的问题。

  • viewControllerBeforeViewController 中,pageViewController 子项似乎弹出了它的 parentViewController(tableViewController)——所以你永远不会看到它的表格内容?要么有更多与应用相关的细节,要么你没有准确地描述它。

我建议您首先处理这些问题。你的问题很可能会消失。

【讨论】:

  • @kwiqsilver - 如果这段代码已经在 TVCO 的 viewDidLoad 中,我不太明白 TVCO 如何在您的 navigationController 的导航栏上将 PVC, as you are adding it as a child on viewDidLoad. In terms of your problem, either way should work - the essence is to set translucent 推为 NO。但是,如果我使用 pushViewController 而不是父/子,我只能重现完全按照您描述的问题。
  • 我试过了,它所做的只是让我的页面视图控制器的内容变为空白。
  • @kwiqsilver,您是否尝试过只是将导航栏的translucent 属性更改为NO? (不改变其他任何东西)
【解决方案2】:

因为您在容器中呈现视图控制器,该容器小于您需要设置的屏幕的完整尺寸

self.pageViewController.definesPresentationContext = YES; 

 viewControllerWhichIsApageInPageController.modalPresentationStyle = UIModalPresentationCurrentContext

【讨论】:

    【解决方案3】:

    我有类似行为的非常痛苦的学习经历:(

    把它放在你的视图控制器的 init 中:

    self.automaticallyAdjustsScrollViewInsets = NO;
    

    这是一个新的 UIViewController 属性,在 iOS 7 中默认为 YES

    UIViewController Docs

    【讨论】:

    • 所做的只是将顶部表格视图项隐藏在导航栏后面。
    • 为我工作,谢谢。在带有 UIPageViewController 和 NavigationBar 的 iOS9 和 iOS10 中仍然需要:第一个图像垂直错位,触摸它并滑入到位。在触摸视图之前,_UIQueueingScrollView contentOffset 不正确。
    猜你喜欢
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    相关资源
    最近更新 更多