【问题标题】:Bounds automatically changes on UIScrollView with content insetsUIScrollView 上的边界自动更改,带有内容插图
【发布时间】:2014-06-22 15:04:40
【问题描述】:

我使用 UIScrollView 作为我的分页滚动视图,pagesScrollView。在其中,我放置了专门用于缩放的单个 UIScrollView。在其中的每一个中,我都有一个视图,它是应该可以缩放的页面项目。所有这些都在带有半透明导航栏的 UINavigationController 中。

我的pagesScrollViewcontentInset.top = 64bounds.origin.y = -64(这对我来说似乎很奇怪,但这是系统自动为我设置的),这很好用。我的屏幕看起来很棒!

但是,在我滚动pagesScrollView 哪怕一点点之后,只要调用scrollViewWillEndDraggingpagesScrollView 就会开始从bounds.origin.y = -64bounds.origin.y = 0 的动画变化,这会导致我的页面项目被遮挡通过导航栏。

左边是加载时的样子,右边是我拖动几个像素然后放开后的样子,它在导航栏下向上滑动(因为 bounds.origin.y 去了到 0)。

问题是我没有任何代码可以改变边界,并且我在各种滚动委托方法中没有任何代码可以做任何事情。我添加了一堆滚动委托方法,并且刚刚添加了 NSLog(),这样我就可以确定更改发生的时间/地点,但它并没有在我的代码中的任何地方发生。

所以,我不知道我可以向您展示什么代码来帮助您帮助我。

编辑:我从头开始构建了一个新项目以删除所有其他变量。我将一个裸 UIViewController 放入 UINavigationController。我将一个 UIScrollView 放入我的视图中,整个视图的大小。以下代码是整个项目。

事实证明,问题(如下所述)仅在 UIScrollView 上启用 PAGING 后才会出现!什么? :)

这里是一个下载基本项目的链接,其中只有几行代码来演示该问题。只需单击滚动视图,您就会看到它随着边界的变化而向上移动。 http://inadaydevelopment.com/stackoverflow/WeirdScrollViews.zip

如何在滚动视图上启用分页,而不会在滚动和移动导航栏下的所有内容时出现边界问题?

可以将导航栏设置为不透明并避免该问题,但理想的情况是具有标准的 iOS7 行为,以便在内容视图缩放后,允许内容位于导航栏下方并应通过半透明正常。

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    NSArray *colors = @[
                        [UIColor blueColor],
                        [UIColor orangeColor],
                        [UIColor magentaColor],
                        ];

    NSArray *zoomerColors = @[
                        [UIColor greenColor],
                        [UIColor yellowColor],
                        [UIColor purpleColor],
                        ];


    self.scroller.pagingEnabled = YES;

    [self.scroller setContentSize:CGSizeMake(self.scroller.frame.size.width*colors.count, self.scroller.frame.size.height)];

    CGRect subviewFrame = CGRectMake(0, 0, 160, 240);
    for (int index=0; index < colors.count; index++) {
        UIColor *color = [colors objectAtIndex:index];
        UIColor *zoomerColor = [zoomerColors objectAtIndex:index];

        UIView *subview = [[UIView alloc] initWithFrame:subviewFrame];
        subview.backgroundColor = color;

        CGRect zoomerFrame = CGRectMake(index*self.scroller.frame.size.width, 0, self.scroller.frame.size.width, self.scroller.frame.size.height);

        UIScrollView *zoomer = [[UIScrollView alloc] initWithFrame:zoomerFrame];
        [zoomer addSubview:subview];
        zoomer.backgroundColor = zoomerColor;

        [self.scroller addSubview:zoomer];

    }
}

【问题讨论】:

  • 如果你使用 bounds 它的 x 和 y 点是 0,0 你需要使用 frame。
  • 放置scrollViewWillEndDragging的代码或放置单个UIScrollViews的代码
  • @nitinkachhadiya,我根本没有改变界限,界限从 -64 开始......这对我来说看起来不对,但这是系统自己设置的。
  • @iPatel,我已经添加了您要求的代码,但正如我所说,它是空的。在我添加它之前,我什至没有在我的类中使用该代码方法,这样我就可以在其中放置一个 NSLog()。

标签: ios objective-c ios7 uiscrollview uiedgeinsets


【解决方案1】:

事实证明,问题(如下所述)仅在 UIScrollView 上启用 PAGING 时才会出现!什么? :)

正如你所说,如果启用滚动分页,UIScrollView 将在拖动或任何移动后停止在分页边缘,这是框架承诺的。 Bounds.origin.y 设置为零意味着第一页边缘与滚动视图框架边缘匹配,因为那里有 64 个 contentInsets。所以这不是错误,就是这样。由于您的栏是半透明的,请记住滚动视图的框架边缘在哪里,它在栏下方。总而言之,我认为这不是一个错误,而是滚动分页的效果。

【讨论】:

    【解决方案2】:

    我已经检查了您在 viewController.m 文件中使用以下代码的示例

    -(void)viewDidLoad
    {
        if ([[UIDevice currentDevice] systemVersion].floatValue>=7.0) {
            self.edgesForExtendedLayout = UIRectEdgeNone;
        }
    }
    

    一切正常……

    【讨论】:

    • 它确实阻止了该错误的出现,但那是因为它禁用了iOS7 ui的核心功能。扩展 UI 时,它也应该正常运行。
    【解决方案3】:

    只需关闭调整滚动视图插图

    【讨论】:

      【解决方案4】:

      这是一个 iOS 错误。我创建了UIScrollView 的以下子类,以记录y 随着时间的推移发生了什么以及谁在推动它:

      @implementation CSScrollView
      
      - (void)setContentOffset:(CGPoint)contentOffset
      {
          NSLog(@"%0.0f %@", contentOffset.y, [NSThread callStackSymbols]);
          NSLog(@"[%@]", self.layer.animationKeys);
          [super setContentOffset:contentOffset];
      }
      
      @end
      

      (并更改了故事板中的视图类)

      当您松开手指时,名为UIScrollView _smoothScrollDisplayLink: 的方法开始将滚动视图动画化到其最终位置。根据第二个日志,没有涉及CAAnimation,滚动视图使用自己的显示链接进行自己的转换。该自定义代码似乎犯了从y = whatevery = 0 的动画错误,没有考虑到内容偏移。

      作为概念验证黑客,我将代码更改为:

      @implementation CSScrollView
      
      - (void)setContentOffset:(CGPoint)contentOffset
      {
          contentOffset.y = -64.0f;
          [super setContentOffset:contentOffset];
      }
      
      @end
      

      不出所料,问题就消失了。

      您可能不想对-64.0f 进行硬编码,但我的结论是:

      • 这是一个 iOS 错误;
      • 通过UIScrollView 的子类和- setContentOffset: 的适当自定义实现拒绝无意义的值来解决此问题。

      一种合理的通用方法可能是检查self.panGestureRecognizerstate — 这将允许您区分用户负责的滚动和其他滚动,而无需依赖任何未记录的 API 或复杂的委托事件捕获。然后,如有必要,从当前值中删除正确的contentOffset.y,而不是对其进行硬编码。

      【讨论】:

      • 这太棒了!我不知道出了什么问题,尽管我确实怀疑这是 iOS 8 中的一个错误。与您的解决方案完美配合,谢谢
      【解决方案5】:

      我的 pagesScrollView 有 contentInset.top = 64 和 bounds.origin.y = -64(这对我来说似乎很奇怪,但这是系统自动为我设置的),这很好用。我的屏幕看起来很棒!

      这是因为 iOS 7 在所有滚动视图上将 contentInset.top 设置为 64。 只需将这行代码添加到您的视图控制器中,一切都会按预期工作:

      -(UIRectEdge)edgesForExtendedLayout {
      return UIRectEdgeNone;
      

      }

      我检查了您的示例项目。

      【讨论】:

      • 感谢您的回复。不幸的是,这个答案只是避免了问题,而不是真正解决问题。当内容视图被缩放和平移时,理想情况下,内容应该位于导航栏下方,并以标准的 iOS7 方式显示。我可以使导航栏不透明并很好地避免该问题,但这并不是真正的理想。这实际上可能是一个 iOS 错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 2012-09-27
      • 2011-11-24
      • 1970-01-01
      相关资源
      最近更新 更多