带有内容插入的UIScrollView自动更改边界

我使用UIScrollView作为分页滚动视图pagesScrollView 。 里面,我把个别UIScrollViews专门用于缩放。 在每个内部,我有一个视图,这是应该是可缩放的页面项目。 所有这一切都在一个带有半透明导航栏的UINavigationController中。

pagesScrollViewcontentInset.top = 64bounds.origin.y = -64 (这似乎很奇怪,但这就是系统自动设置为我),这工作得很好。 我的屏幕看起来不错!

然而,在scrollViewWillEndDragging调用scrollViewWillEndDragging之后, scrollViewWillEndDragging会从bounds.origin.y = -64开始animation变化为bounds.origin.y = 0 ,这会导致我的页面项目被遮挡由导航栏。

左边是加载时的样子,右边是拖动几个像素后的样子,然后放开,在导航栏下滑动(因为bounds.origin.y会变成0) 。

在这里输入图像说明

问题是,我没有任何代码正在改变的界限,我没有任何代码在各种滚动委托方法做任何事情。 我已经添加了一堆滚动委托方法,只是添加了NSLog(),所以我可以找出更改发生的时间/地点,但是这不会发生在我的代码中的任何地方。

所以,我不知道我可以告诉你什么样的代码来帮助你。

编辑:我从头开始build立一个新的项目,删除所有其他variables..我把一个裸UIViewController到一个UINavigationController。 我把一个UIScrollView放到我的View中,查看整个视图的大小。 以下代码是整个项目。

事实certificate,这个问题(下面描述)只有在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]; } } 

这是一个iOS的错误。 我创build了UIScrollView的以下子类,以获得随着时间推移发生的事情的日志以及谁在推动它:

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

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

当释放你的手指时,一个名为UIScrollView _smoothScrollDisplayLink:的方法UIScrollView _smoothScrollDisplayLink:开始将滚动视图animation到其最终位置。 根据第二个日志,不涉及CAAnimation ,滚动视图使用自己的显示链接进行自己的转换。 这个自定义代码看起来会导致animation从y = whatevery = 0的错误,而不考虑内容偏移量。

作为一个概念certificate黑客我改变了代码:

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

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

你可能不想硬编码-64.0f但我可以得出结论:

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

一个明智的通用手段可能是检查self.panGestureRecognizerstate – 这将允许您区分用户负责的滚动和其他滚动,而不依赖任何未公开的API或复杂的委托事件捕获。 然后,如果有必要,从当前值contentOffset.y正确的contentOffset.y而不是硬编码它。

只需closures调整滚动查看插图

在这里输入图像说明

我已经检查你在viewController.m文件中使用下面的代码

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

它工作正常…

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

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

 -(UIRectEdge)edgesForExtendedLayout { return UIRectEdgeNone; 

}

我检查了你的例子项目。