绑定会自动更改UIScrollView上的内容插入 [英] Bounds automatically changes on UIScrollView with content insets

查看:249
本文介绍了绑定会自动更改UIScrollView上的内容插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using a UIScrollView as my paging scroll view, pagesScrollView. Inside that, I put individual UIScrollViews which are used exclusively for zooming. Inside each of those, I have one view which is the page item which should be zoomable. All of that is inside a UINavigationController with a translucent navbar.

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

My pagesScrollView has contentInset.top = 64 and bounds.origin.y = -64 (that seems weird to me, but that's what the system is setting automatically for me), and this works just fine. My screen looks great!

然而,在我滚动 pagesScrollView 后,即使只是一点点,只要<$调用c $ c> scrollViewWillEndDragging , pagesScrollView 开始动画更改bounds.origin.y = -64 bounds.origin.y = 0 这会导致我的页面项目被导航条遮挡。

However, after I scroll the pagesScrollView even a tiny bit, as soon as scrollViewWillEndDragging is called, the pagesScrollView begins an animated change from bounds.origin.y = -64 to bounds.origin.y = 0 which causes my page items to be obscured by the navbar.

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

On the left is what it looks like when it loads, on the right is what it looks like after I drag just a few pixels and then let go, it slides up under the navbar (because the bounds.origin.y goes to 0).

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

The problem is that I don't have any code that is altering the bounds and I don't have any code in the various scroll delegate methods that do anything. I've added a bunch of scroll delegate methods and just added NSLog()s so I can figure out when/where the change is happening, but it's not happening anywhere in my code.

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

So, I don't know what code I can show you to help you help me.

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

I built a new project from scratch to remove all other variables.. I put a bare UIViewController into a UINavigationController. I put a UIScrollView into my View the entire size of the view. The following code is the entire project.

事实证明,只有在UIScrollView上启用PAGING后才会出现问题(如下所述)!跆拳道? :)

It turns out the issue (described below) only appears once PAGING IS ENABLED on the UIScrollView! Wtf? :)

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

Here is a link to download a basic project with only a few lines of code which demonstrates the problem. Just click in the scrollview and you'll see it shift up as the bounds change. http://inadaydevelopment.com/stackoverflow/WeirdScrollViews.zip

如何在我的滚动视图中启用分页而不会在滚动期间将所有内容移动并将所有内容移动到导航栏下?

How can I have paging enabled on my scrollview without the bounds freaking out during scrolling and shifting everything under the nav bar?

可以设置导航栏变为不透明并且避免了问题,但理想的是具有标准的iOS7行为,以便在内容视图被缩放之后,然后允许内容在导航栏下并且应该通过半透明正常显示。

It's possible to set the navbar to opaque and the problem is avoided, but the ideal is to have standard iOS7 behavior so that after the content view is zoomed, THEN the content is allowed to be under the navbar and should show through the translucency normally.

- (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错误。我创建了以下 UIScrollView 的子类来获取 y 随着时间的推移以及推送它的人的日志:

It's an iOS bug. I created the following subclass of UIScrollView to get a log of what happens to y over time and who was pushing it:

@implementation CSScrollView

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

@end

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

(and changed the view class in the storyboard)

释放手指时,一个名为 UIScrollView _smoothScrollDisplayLink:的方法开始动画滚动视图到它的最终位置。根据第二个日志,没有涉及 CAAnimation ,滚动视图使用自己的显示链接进行自己的转换。该自定义代码似乎犯了从 y =无论 y = 0 的动画错误,未能获取内容抵消考虑。

When you release your finger, a method called UIScrollView _smoothScrollDisplayLink: starts animating the scroll view to its final position. As per the second log, there's no CAAnimation involved, the scroll view uses its own display link to do its own transition. That custom code appears to make the mistake of animating from y = whatever to y = 0, failing to take the content offset into account.

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

As a proof-of-concept hack I changed the code to:

@implementation CSScrollView

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

@end

而且,不出所料,这个问题离开。

And, unsurprisingly, the problem went away.

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

You probably don't want to hard code the -64.0f but I'd conclude:


  • 这是一个iOS错误;

  • 通过<的子类拒绝无意义的值来解决它code> UIScrollView ,合适的自定义实现 - setContentOffset:

  • it's an iOS bug;
  • work around it by rejecting nonsensical values via a subclass of UIScrollView with a suitable custom implementation of - setContentOffset:.

明智的通用方法可能是检查 self.panGestureRecognizer - 这将允许您区分用户负责的滚动和其他滚动,而不依赖于任何未记录的API或复杂的委托事件捕获。然后,如果需要,从当前值中取出正确的 contentOffset.y ,而不是硬编码。

A sensible generic means might be to check the state of self.panGestureRecognizer — that'll allow you to differentiate between scrolls the user is responsible for and other scrolls without relying on any undocumented API or complicated capturing of delegate events. Then if necessary crib the correct contentOffset.y from the current value rather than hardcoding it.

这篇关于绑定会自动更改UIScrollView上的内容插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆