UIScrollView:水平分页,垂直滚动?

我怎样才能强制一个UIScrollView的分页和滚动只在一个给定的时刻垂直或水平移动?

我的理解是, directionalLockEnabledlocking启用属性应该实现这一点,但对angular线滑动仍然会导致视图对angular滚动,而不是限制运动到一个单一的轴。

编辑:要更清楚,我想让用户水平或垂直滚动​​,但不是两个同时。

我必须说,你处境非常艰难。

请注意,您需要使用具有pagingEnabled=YES的UIScrollView在页面之间进行切换,但需要pagingEnabled=NO才能垂直滚动。

有两种可能的策略。 我不知道哪个会工作/更容易实现,所以试试。

第一:嵌套的UIScrollViews。 坦率地说,我还没有看到有这个工作的人。 但是我个人还没有努力过,而且我的实践表明,当你努力的时候,你可以让UIScrollView做任何你想做的事情 。

所以策略是让外滚动视图只处理水平滚动,内滚动视图只处理垂直滚动。 要做到这一点,你必须知道如何UIScrollView内部工作。 它重写hitTest方法并始终返回自身,以便所有触摸事件进入UIScrollView。 然后在touchesBegantouchesMoved等内部检查它是否对事件感兴趣,并处理或传递给内部组件。

要决定触摸是要处理还是要转发,UIScrollView首先触摸它将启动一个计时器:

  • 如果你在150ms内没有明显的移动你的手指,它会把事件传递给内部视图。

  • 如果你已经在150ms内显着地移动了你的手指,它开始滚动(并且不会将事件传递给内部视图)。

    注意当你触摸一个表(它是滚动视图的一个子类)并且立即开始滚动时,触摸的那一行决不会突出显示。

  • 如果你在150ms内没有明显的移动你的手指,并且UIScrollView开始把事件传递给内部视图,但是你已经将手指移动了足够远以开始滚动,那么UIScrollView调用在内部视图上touchesCancelled并开始滚动。

    请注意,当你触摸一张桌子时,握住你的手指一下,然后开始滚动,你触摸的那一行首先被突出显示,然后被取消突出显示。

这些事件顺序可以通过configurationUIScrollView来改变:

  • 如果delaysContentTouches为NO,则不使用定时器 – 事件立即进入内部控制(但如果将手指移动得足够远,则会取消)
  • 如果cancelsTouches为NO,那么一旦事件发送到控件,滚动将永远不会发生。

请注意,它是UIScrollView,它接收来自CocoaTouch的所有 touchesBegintouchesMovedtouchesEndedtouchesCanceled事件(因为它的hitTest告诉它这样做)。 然后,只要它愿意,它就会将它们转发到内部视图。

现在你知道了关于UIScrollView的一切,你可以改变它的行为。 我敢打赌,你希望垂直滚动,所以一旦用户触摸视图,并开始移动他的手指(甚至轻微),视图开始滚动垂直方向; 但是当用户沿水平方向移动他的手指足够远时,您想要取消垂直滚动并开始水平滚动。

你想要为你的外部UIScrollView子类化(比如你命名你的类为RemorsefulScrollView),这样它就可以代替默认行为,立即将所有事件转发到内部视图,只有当检测到重大的水平移动时才会滚动。

如何做RemorsefulScrollView的行为呢?

  • 它看起来像禁用垂直滚动和设置delaysContentTouches为NO应该使嵌套的UIScrollViews工作。 不幸的是,事实并非如此。 UIScrollView似乎为快速运动(不能被禁用)做了一些额外的过滤,所以即使UIScrollView只能水平滚动,它总是会消耗(并忽略)足够快的垂直运动。

    效果非常严重,嵌套滚动视图内的垂直滚动不可用。 (看起来你已经得到了这个设置,所以试试吧:按住一个手指150ms,然后在垂直方向上移动 – 嵌套UIScrollView按预期工作!)

  • 这意味着你不能使用UIScrollView的代码来处理事件。 您必须重写RemorsefulScrollView中的所有四个触摸处理方法,并首先执行您自己的处理,如果您决定使用水平滚动,则只将该事件转发到super (UIScrollView)。

  • 然而,你必须将touchesBegan传递给UIScrollView,因为你希望它记住未来水平滚动的基本坐标(如果以后确定它水平滚动的话)。 之后您将无法发送touchesBegan到UIScrollView,因为您无法存储touches参数:它包含在下一个touchesMoved事件之前将被突变的对象,并且无法重现旧状态。

    所以你必须立即将touchesBegan传递给UIScrollView,但是直到你决定水平滚动,你将隐藏任何进一步的touchesMoved事件。 没有touchesMoved意味着没有滚动,所以这个初始touchesBegan将没有任何伤害。 但是将delaysContentTouches设置为NO,这样就不会有额外的delaysContentTouches定时器的干扰。

    (Offtopic – 与你不同的是,UIScrollView 可以正确存储触摸,并可以在之后重现和转发原始的touchesBegan事件,它具有使用未公布的API的不公平优势,因此可以在触摸对象发生变异之前将其克隆。

  • 鉴于你总是前进touchesBegan ,你也必须前进touchesCancelledtouchesEnded 。 但是,您必须将touchesEnded转换为touchesCancelled ,因为UIScrollView会将touchesBegantouchesEnded序列解释为触摸点击,并将其转发到内部视图。 你已经自己转发正确的事件,所以你永远不希望UIScrollView转发任何东西。

基本上这里是你需要做的伪代码。 为了简单起见,在发生多点触摸事件之后,我从不允许水平滚动。

 // RemorsefulScrollView.h @interface RemorsefulScrollView : UIScrollView { CGPoint _originalPoint; BOOL _isHorizontalScroll, _isMultitouch; UIView *_currentChild; } @end // RemorsefulScrollView.m // the numbers from an example in Apple docs, may need to tune them #define kThresholdX 12.0f #define kThresholdY 4.0f @implementation RemorsefulScrollView - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.delaysContentTouches = NO; } return self; } - (id)initWithCoder:(NSCoder *)coder { if (self = [super initWithCoder:coder]) { self.delaysContentTouches = NO; } return self; } - (UIView *)honestHitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *result = nil; for (UIView *child in self.subviews) if ([child pointInside:point withEvent:event]) if ((result = [child hitTest:point withEvent:event]) != nil) break; return result; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; // always forward touchesBegan -- there's no way to forward it later if (_isHorizontalScroll) return; // UIScrollView is in charge now if ([touches count] == [[event touchesForView:self] count]) { // initial touch _originalPoint = [[touches anyObject] locationInView:self]; _currentChild = [self honestHitTest:_originalPoint withEvent:event]; _isMultitouch = NO; } _isMultitouch |= ([[event touchesForView:self] count] > 1); [_currentChild touchesBegan:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if (!_isHorizontalScroll && !_isMultitouch) { CGPoint point = [[touches anyObject] locationInView:self]; if (fabsf(_originalPoint.x - point.x) > kThresholdX && fabsf(_originalPoint.y - point.y) < kThresholdY) { _isHorizontalScroll = YES; [_currentChild touchesCancelled:[event touchesForView:self] withEvent:event] } } if (_isHorizontalScroll) [super touchesMoved:touches withEvent:event]; // UIScrollView only kicks in on horizontal scroll else [_currentChild touchesMoved:touches withEvent:event]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if (_isHorizontalScroll) [super touchesEnded:touches withEvent:event]; else { [super touchesCancelled:touches withEvent:event]; [_currentChild touchesEnded:touches withEvent:event]; } } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; if (!_isHorizontalScroll) [_currentChild touchesCancelled:touches withEvent:event]; } @end 

我还没有尝试运行甚至编译这个(并在纯文本编辑器中键入整个类),但是你可以从上面开始,希望能够工作。

我看到的唯一隐藏的捕获是,如果您将任何非UIScrollView子视图添加到RemorsefulScrollView,您转发给孩子的触摸事件可能会通过响应链返回给您,如果孩子不总是处理像UIScrollView一样的触摸。 防弹RemorsefulScrollView实施将防止touchesXxx重新进入。

第二个策略:如果由于某种原因嵌套的UIScrollViews不能解决问题或者certificate太难以正确解决问题,那么可以尝试仅使用一个UIScrollView,从scrollViewDidScroll委托方法中即时切换其pagingEnabled属性。

为了防止对angular线滚动,您应该先尝试记住scrollViewWillBeginDragging contentOffset,然后检查并重置scrollViewDidScroll contentOffset(如果检测到对angular线移动)。 另一个尝试的方法是重置contentSize,以便只在一个方向上滚动,一旦你决定了用户手指的方向。 (UIScrollView似乎很容易从它的委托方法中调用contentSize和contentOffset。)

如果这不起作用或导致马虎的视觉效果,你必须重写touchesBegantouchesMoved等,而不是转发对angular线移动事件到UIScrollView。 (在这种情况下,用户体验并不理想,因为你不得不忽视对angular线的移动,而不是强迫他们进入单一的方向,如果你觉得真的很冒险,你可以编写你自己的UITouch外观,像RevengeTouch。 -C是一个普通的老C,世上没有什么比C更傻的东西了;只要没有人检查真正的对象的类别,我相信没有人会这样做,你可以让任何类别看起来像其他任何类别一样。可以用任何你想要的坐标合成你想要的任何触摸。)

备份策略:有TTScrollView,一个在Three20库中的UIScrollView的重新实现。 不幸的是,用户感觉非常不自然和不易触及。 但是,如果每次使用UIScrollView的尝试都失败,则可以回退到自定义编码的滚动视图。 如果可能,我build议不要这样做; 使用UIScrollView可以确保您获得原生的外观,无论它在未来的iPhone操作系统版本中如何发展。

好的,这篇小文章太长了。 在几天前在ScrollingMadness上工作之后,我还只是进入了UIScrollView游戏。

PS如果你有这些工作,感觉像分享,请给我发电子邮件相关的代码在andreyvit@gmail.com,我很乐意把它包括到我的ScrollingMadness袋子的技巧 。

PPS添加这个小文章到ScrollingMadness自述文件。

这对我来说每次都有效

 scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * NumberOfPages, 1); 

对于像我这样的懒惰的人来说:

scrollview.directionalLockEnabled设置为YES

 - (void) scrollViewWillBeginDragging: (UIScrollView *) scrollView { self.oldContentOffset = scrollView.contentOffset; } - (void) scrollViewDidScroll: (UIScrollView *) scrollView { if (scrollView.contentOffset.x != self.oldContentOffset.x) { scrollView.pagingEnabled = YES; scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, self.oldContentOffset.y); } else { scrollView.pagingEnabled = NO; } } - (void) scrollViewDidEndDecelerating: (UIScrollView *) scrollView { self.oldContentOffset = scrollView.contentOffset; } 

我用下面的方法来解决这个问题,希望能帮到你。

首先在您的控制器头文件中定义以下variables。

 CGPoint startPos; int scrollDirection; 

当委托收到scrollViewWillBeginDragging消息时, startPos将保持contentOffset值。 所以在这个方法中我们这样做;

 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ startPos = scrollView.contentOffset; scrollDirection=0; } 

那么我们使用这些值来确定用户在scrollViewDidScroll消息中预期的滚动方向。

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ if (scrollDirection==0){//we need to determine direction //use the difference between positions to determine the direction. if (abs(startPos.x-scrollView.contentOffset.x)<abs(startPos.y-scrollView.contentOffset.y)){ NSLog(@"Vertical Scrolling"); scrollDirection=1; } else { NSLog(@"Horitonzal Scrolling"); scrollDirection=2; } } //Update scroll position of the scrollview according to detected direction. if (scrollDirection==1) { [scrollView setContentOffset:CGPointMake(startPos.x,scrollView.contentOffset.y) animated:NO]; } else if (scrollDirection==2){ [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x,startPos.y) animated:NO]; } } 

最后,我们不得不停止所有的更新操作,当用户结束拖动;

  - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if (decelerate) { scrollDirection=3; } } 

我可能会在这里埋头苦干,但今天我试图解决同样的问题,我偶然发现了这个post。 这是我的解决scheme,似乎工作得很好。

我想显示一个屏幕的内容,但允许用户滚动到其他4个屏幕之一,向左和向右。 我有一个单一的UIScrollView大小为320×480和contentSize为960×1440。 内容偏移量从320,480开始。 在scrollViewDidEndDecelerating:中,我重绘了5个视图(中心视图和它周围的4个视图),并将内容偏移重置为320,480。

这是我的解决scheme的肉,scrollViewDidScroll:方法。

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (!scrollingVertically && ! scrollingHorizontally) { int xDiff = abs(scrollView.contentOffset.x - 320); int yDiff = abs(scrollView.contentOffset.y - 480); if (xDiff > yDiff) { scrollingHorizontally = YES; } else if (xDiff < yDiff) { scrollingVertically = YES; } } if (scrollingHorizontally) { scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, 480); } else if (scrollingVertically) { scrollView.contentOffset = CGPointMake(320, scrollView.contentOffset.y); } } 

伙计们就像使滚动视图高度和内容大小高度一样简化子视图的高度。 然后,垂直滚动被禁用。

这是我的分页UIScrollView ,只允许正交滚动。 确保将pagingEnabled设置为YES

PagedOrthoScrollView.h

 @interface PagedOrthoScrollView : UIScrollView @end 

PagedOrthoScrollView.m

 #import "PagedOrthoScrollView.h" typedef enum { PagedOrthoScrollViewLockDirectionNone, PagedOrthoScrollViewLockDirectionVertical, PagedOrthoScrollViewLockDirectionHorizontal } PagedOrthoScrollViewLockDirection; @interface PagedOrthoScrollView () @property(nonatomic, assign) PagedOrthoScrollViewLockDirection dirLock; @property(nonatomic, assign) CGFloat valueLock; @end @implementation PagedOrthoScrollView @synthesize dirLock; @synthesize valueLock; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self == nil) { return self; } self.dirLock = PagedOrthoScrollViewLockDirectionNone; self.valueLock = 0; return self; } - (void)setBounds:(CGRect)bounds { int mx, my; if (self.dirLock == PagedOrthoScrollViewLockDirectionNone) { // is on even page coordinates, set dir lock and lock value to closest page mx = abs((int)CGRectGetMinX(bounds) % (int)CGRectGetWidth(self.bounds)); if (mx != 0) { self.dirLock = PagedOrthoScrollViewLockDirectionHorizontal; self.valueLock = (round(CGRectGetMinY(bounds) / CGRectGetHeight(self.bounds)) * CGRectGetHeight(self.bounds)); } else { self.dirLock = PagedOrthoScrollViewLockDirectionVertical; self.valueLock = (round(CGRectGetMinX(bounds) / CGRectGetWidth(self.bounds)) * CGRectGetWidth(self.bounds)); } // show only possible scroll indicator self.showsVerticalScrollIndicator = dirLock == PagedOrthoScrollViewLockDirectionVertical; self.showsHorizontalScrollIndicator = dirLock == PagedOrthoScrollViewLockDirectionHorizontal; } if (self.dirLock == PagedOrthoScrollViewLockDirectionHorizontal) { bounds.origin.y = self.valueLock; } else { bounds.origin.x = self.valueLock; } mx = abs((int)CGRectGetMinX(bounds) % (int)CGRectGetWidth(self.bounds)); my = abs((int)CGRectGetMinY(bounds) % (int)CGRectGetHeight(self.bounds)); if (mx == 0 && my == 0) { // is on even page coordinates, reset lock self.dirLock = PagedOrthoScrollViewLockDirectionNone; } [super setBounds:bounds]; } @end 

我也必须解决这个问题,虽然Andrey Tarantov的回答肯定有很多有用的信息来理解UIScrollViews如何工作,但我觉得这个解决scheme有点太复杂了。 我的解决scheme,不涉及任何子类或接触转发,如下所示:

  1. 创build两个嵌套滚动视图,每个方向一个。
  2. 创build两个虚拟的UIPanGestureRecognizers ,每个方向也是一个。
  3. 通过使用UIGestureRecognizer's -requireGestureRecognizerToFail:select器,在UIScrollViews的panGestureRecognizer属性和与UIScrollView所需的滚动方向垂直的方向对应的虚拟UIPanGestureRecognizer之间创build失败依赖关系。
  4. 在您的虚拟UIPanGestureRecognizers的-gestureRecognizerShouldBegin:callback函数中,使用手势的UIPanGestureRecognizers :selector(您的UIPanGestureRecognizers不会调用此UIPanGestureRecognizerscallback,直到您的触摸已足够翻译以注册为平移)计算平移的初始方向。 允许或禁止您的手势识别器开始取决于计算的方向,而这又应该控制垂直UIScrollView平移手势识别器是否将被允许开始。
  5. in -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:不要让你的虚拟UIPanGestureRecognizers一起滚动(除非你有一些额外的行为,你想添加)。

我所做的是创build一个分页UIScrollView与视图屏幕的大小框架,并将内容大小设置为我所有的内容所需的宽度和1(谢谢Tonetel)的高度。 然后,我创build了菜单UIScrollView页面,每个页面都设置了框架,视图屏幕的大小,并将每个页面的内容大小设置为屏幕宽度和每个页面的必要高度。 然后,我只是将每个菜单页面添加到分页视图。 确保在分页滚动视图上启用了分页function,但在菜单视图上禁用了分页function(默认情况下应该禁用),您应该很好。

分页滚动视图现在水平滚动,但不是由于内容高度而垂直滚动。 由于内容大小的限制,每个页面都会垂直滚动,但不会水平滚动。

下面是代码,如果解释留下了一些需要的东西:

 UIScrollView *newPagingScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; [newPagingScrollView setPagingEnabled:YES]; [newPagingScrollView setShowsVerticalScrollIndicator:NO]; [newPagingScrollView setShowsHorizontalScrollIndicator:NO]; [newPagingScrollView setDelegate:self]; [newPagingScrollView setContentSize:CGSizeMake(self.view.bounds.size.width * NumberOfDetailPages, 1)]; [self.view addSubview:newPagingScrollView]; float pageX = 0; for (int i = 0; i < NumberOfDetailPages; i++) { CGRect pageFrame = (CGRect) { .origin = CGPointMake(pageX, pagingScrollView.bounds.origin.y), .size = pagingScrollView.bounds.size }; UIScrollView *newPage = [self createNewPageFromIndex:i ToPageFrame:pageFrame]; // newPage.contentSize custom set in here [pagingScrollView addSubview:newPage]; pageX += pageFrame.size.width; } 

谢谢Tonetel。 我略微修改了你的方法,但正是我需要防止水平滚动。

 self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, 1); 

这是改进的icompot解决scheme,这对我来说是相当不稳定的。 这个工作正常,很容易实现:

 - (void) scrollViewWillBeginDragging: (UIScrollView *) scrollView { self.oldContentOffset = scrollView.contentOffset; } - (void) scrollViewDidScroll: (UIScrollView *) scrollView { float XOffset = fabsf(self.oldContentOffset.x - scrollView.contentOffset.x ); float YOffset = fabsf(self.oldContentOffset.y - scrollView.contentOffset.y ); if (scrollView.contentOffset.x != self.oldContentOffset.x && (XOffset >= YOffset) ) { scrollView.pagingEnabled = YES; scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, self.oldContentOffset.y); } else { scrollView.pagingEnabled = NO; scrollView.contentOffset = CGPointMake( self.oldContentOffset.x, scrollView.contentOffset.y); } } - (void) scrollViewDidEndDecelerating: (UIScrollView *) scrollView { self.oldContentOffset = scrollView.contentOffset; } 

从文档:

“默认值为NO,这意味着在水平和垂直两个方向上都允许滚动,如果值为YES并且用户在一个普通方向(水平或垂直)开始拖动,则滚动视图禁止在另一个方向滚动。 “

我认为重要的部分是“如果…用户开始在一个大方向上拖动”。 所以,如果他们开始斜着拖,这就不会起作用了。不是说这些文档在解释时总是可靠的 – 但是这似乎与您所看到的一致。

这实际上似乎是明智的。 我不得不问 – 为什么你想限制在任何时候只有水平或只有垂直? 也许UIScrollView不是你的工具?

我的视图由10个水平视图组成,其中一些视图由多个垂直视图组成,所以你会得到这样的东西:

 1.0 2.0 3.1 4.1 2.1 3.1 2.2 2.3 

在水平轴和垂直轴上启用分页

该视图还具有以下属性:

 [self setDelaysContentTouches:NO]; [self setMultipleTouchEnabled:NO]; [self setDirectionalLockEnabled:YES]; 

现在要防止对angular线滚动这样做:

 -(void)scrollViewDidScroll:(UIScrollView *)scrollView { int pageWidth = 768; int pageHeight = 1024; int subPage =round(self.contentOffset.y / pageHeight); if ((int)self.contentOffset.x % pageWidth != 0 && (int)self.contentOffset.y % pageHeight != 0) { [self setContentOffset:CGPointMake(self.contentOffset.x, subPage * pageHeight]; } } 

对我来说就像一个迷人的工作!

需要将_isHorizontalScroll重置为NO, touchesEndedtouchesCancelled

如果你有一个很大的滚动视图…你想限制对angular线滚动http://chandanshetty01.blogspot.in/2012/07/restricting-diagonal-scrolling-in.html

为了将来的参考,我build立在安德烈Tanasov的答案,并提出了以下解决scheme,工作正常。

首先定义一个variables来存储contentOffset并将其设置为0,0坐标

 var positionScroll = CGPointMake(0, 0) 

现在在scrollView委托中实现以下内容:

 override func scrollViewWillBeginDragging(scrollView: UIScrollView) { // Note that we are getting a reference to self.scrollView and not the scrollView referenced passed by the method // For some reason, not doing this fails to get the logic to work self.positionScroll = (self.scrollView?.contentOffset)! } override func scrollViewDidScroll(scrollView: UIScrollView) { // Check that contentOffset is not nil // We do this because the scrollViewDidScroll method is called on viewDidLoad if self.scrollView?.contentOffset != nil { // The user wants to scroll on the X axis if self.scrollView?.contentOffset.x > self.positionScroll.x || self.scrollView?.contentOffset.x < self.positionScroll.x { // Reset the Y position of the scrollView to what it was BEFORE scrolling started self.scrollView?.contentOffset = CGPointMake((self.scrollView?.contentOffset.x)!, self.positionScroll.y); self.scrollView?.pagingEnabled = true } // The user wants to scroll on the Y axis else { // Reset the X position of the scrollView to what it was BEFORE scrolling started self.scrollView?.contentOffset = CGPointMake(self.positionScroll.x, (self.scrollView?.contentOffset.y)!); self.collectionView?.pagingEnabled = false } } } 

希望这可以帮助。

如果你还没有尝试在3.0 beta版本中这样做,我build议你试试看。 我正在使用滚动视图内的一系列表视图,它正常工作。 (好吧,滚动,无论如何,当find一个完全不同的问题的修复时发现这个问题…)

对于那些在@AndreyTarantsov第二个解决scheme在Swift中查看代码如下:

  var positionScroll:CGFloat = 0 func scrollViewWillBeginDragging(scrollView: UIScrollView) { positionScroll = self.theScroll.contentOffset.x } func scrollViewDidScroll(scrollView: UIScrollView) { if self.theScroll.contentOffset.x > self.positionScroll || self.theScroll.contentOffset.x < self.positionScroll{ self.theScroll.pagingEnabled = true }else{ self.theScroll.pagingEnabled = false } } 

我们在这里做的是在滚动视图被拖动之前保持当前位置,然后检查x是否比x的当前位置增加或减less。 如果是的话,那么设置pagingEnabled为true,如果否(y增加/减less),则设置为pagingEnabled为false

希望对新来者有用!

如果您使用界面生成器来devise界面 – 这可以很容易地完成。

在界面生成器中,只需单击UIScrollView并select(在检查器中)将其限制为只有一种方式滚动的选项。