如何强制UIScrollView
启用分页和滚动功能的a在给定时刻仅垂直或水平移动?
我的理解是该directionalLockEnabled
属性应该可以实现这一点,但是对角滑动仍会导致视图向对角滚动,而不是将运动限制在单个轴上。
编辑:更清楚地说,我想允许用户水平或垂直滚动,但不能同时滚动。
如何强制UIScrollView
启用分页和滚动功能的a在给定时刻仅垂直或水平移动?
我的理解是该directionalLockEnabled
属性应该可以实现这一点,但是对角滑动仍会导致视图向对角滚动,而不是将运动限制在单个轴上。
编辑:更清楚地说,我想允许用户水平或垂直滚动,但不能同时滚动。
Answers:
我必须说,你处境非常艰难。
注意,您需要使用带有的UIScrollViewpagingEnabled=YES
在页面之间进行切换,但是需要pagingEnabled=NO
垂直滚动。
有两种可能的策略。我不知道哪个会工作/更容易实现,因此请同时尝试。
首先:嵌套的UIScrollViews。坦白说,我还没有看到一个能做到这一点的人。但是,我个人还没有足够努力,而实践表明,当您足够努力时,可以使UIScrollView做任何您想做的事情。
因此,策略是让外部滚动视图仅处理水平滚动,让内部滚动视图仅处理垂直滚动。为此,您必须知道UIScrollView如何在内部工作。它重写hitTest
方法并始终返回自身,以便所有触摸事件都进入UIScrollView。然后在touchesBegan
,touchesMoved
等内部,它检查是否对该事件感兴趣,然后处理该事件或将其传递给内部组件。
要确定是要处理还是要转发触摸,UIScrollView在您首次触摸时会启动一个计时器:
如果您在150毫秒内没有明显移动手指,它将把事件传递到内部视图。
如果您在150毫秒内大大移动了手指,它将开始滚动(并且永远不会将事件传递到内部视图)。
请注意,当您触摸表(滚动视图的子类)并立即开始滚动时,所触摸的行始终不会突出显示。
如果你还没有150毫秒内显著移动你的手指的UIScrollView开始传递事件内视图,但随后您移动手指远远不够的滚动开始,UIScrollView的要求touchesCancelled
在内部视图和开始滚动。
请注意,当您触摸表格时,先稍稍按住手指然后开始滚动,所触摸的行会先突出显示,然后再取消突出显示。
这些事件的顺序可以通过配置UIScrollView来更改:
delaysContentTouches
为“否”,则不使用计时器-事件立即进入内部控件(但是如果您将手指移到足够远的位置,事件将被取消)cancelsTouches
为“否”,则一旦将事件发送到控件,就永远不会发生滚动。需要注意的是的UIScrollView接收所有 touchesBegin
,touchesMoved
,touchesEnded
和touchesCanceled
从CocoaTouch事件(因为它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
为“否”,这样就不会有其他意外计时器受到干扰。
(Offtopic-与您不同,UIScrollView可以正确存储触摸,并且以后可以重现和转发原始touchesBegan
事件。使用未发布的API具有不公平的优势,因此可以在触摸对象突变之前克隆它们。)
考虑到你一直向前touchesBegan
,你也必须向前touchesCancelled
和前进touchesEnded
。但是,您必须转touchesEnded
成touchesCancelled
,因为UIScrollView会将touchesBegan
,touchesEnded
序列解释为触摸式单击,并将其转发到内部视图。您已经自己转发了适当的事件,因此您永远不希望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无法正常工作或证明难以正确使用,则可以尝试与一个UIScrollView相处,pagingEnabled
从scrollViewDidScroll
委托方法中即时切换其属性。
为防止对角线滚动,您应该首先尝试记住中的contentOffset scrollViewWillBeginDragging
,并在scrollViewDidScroll
检测到对角线移动时在内部检查并重置contentOffset 。尝试的另一种策略是,一旦确定用户的手指往哪个方向移动,就将contentSize重置为仅允许在一个方向上滚动。(UIScrollView对于从其委托方法摆弄contentSize和contentOffset似乎很宽容。)
如果这不起作用或导致草率的视觉效果,则必须覆盖touchesBegan
,touchesMoved
等等,并且不将对角线移动事件转发到UIScrollView。(但是,在这种情况下,用户体验将不是最佳的,因为您将不得不忽略对角线移动,而不是将其强制向单个方向移动。如果您真的很冒险,则可以编写自己的UITouch,类似于RevengeTouch。) -C是普通的旧C,并且世界上没有比C更令人沮丧的类型;只要没有人检查对象的真实类(我相信没人会这样做),您就可以使任何类看起来像任何其他类。可以将所需的任何触摸与所需的坐标进行合成。)
备份策略: TTScrollView是Three20库中UIScrollView的明智重新实现。不幸的是,对于用户而言,这感觉非常不自然且不友好。但是,如果每次使用UIScrollView的尝试均失败,则可以退回到自定义编码的滚动视图。我建议尽量不要这样做。使用UIScrollView可以确保您获得本机的外观,无论它在将来的iPhone OS版本中如何发展。
好的,这篇小文章太长了。几天前在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;
}
我使用以下方法解决此问题,希望对您有所帮助。
首先在控制器头文件中定义以下变量。
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;
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if (decelerate) { scrollDirection=3; } }
更改为- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if (!decelerate) { scrollDirection=0; } }
和- (void)scrollViewDidEndDecelerating{ scrollDirection=0; }
我可能在这里挖墓,但是今天我在尝试解决相同的问题时偶然发现了这个帖子。这是我的解决方案,似乎效果很好。
我想显示一屏内容,但允许用户上下左右滚动到其他4屏之一。我有一个UIScrollView,尺寸为320x480,contentSize为960x1440。内容偏移量从320,480开始。在scrollViewDidEndDecelerating:中,我重绘了5个视图(中心视图和周围的4个视图),并将内容偏移量重置为320,480。
这是我的解决方案的内容,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 Tarantsov)的答案肯定有很多有用的信息可帮助您理解UIScrollViews
工作原理,但我认为该解决方案有些复杂。我的解决方案不涉及任何子类化或触摸转发,如下所示:
UIPanGestureRecognizers
,每个方向再创建一个。UIScrollViews
'panGestureRecognizer属性和与UIPanGestureRecognizer
垂直于UIScrollView所需滚动方向的垂直方向相对应的虚拟对象之间创建故障依赖关系UIGestureRecognizer's
-requireGestureRecognizerToFail:
。-gestureRecognizerShouldBegin:
您的虚拟UIPanGestureRecognizers的回调中,使用手势的-translationInView:选择器(您的UIPanGestureRecognizers
您的触摸足够平移以注册为平移之前,您不会调用此委托回调)。允许或禁止手势识别器根据所计算的方向开始,而方向又应控制是否允许垂直UIScrollView平移手势识别器开始。-gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
,不允许您的假人UIPanGestureRecognizers
与滚动同时运行(除非您想添加一些额外的行为)。我要做的是创建一个分页UIScrollView,其边框大小为视图屏幕的大小,并将内容大小设置为所有内容所需的宽度,并将其高度设置为1(感谢Tonetel)。然后,我创建了菜单UIScrollView页面,并在每个页面上设置了框架,查看屏幕的大小,并将每个页面的内容大小设置为屏幕的宽度和每个页面的必要高度。然后,我简单地将每个菜单页面添加到分页视图中。确保在页面滚动视图上启用了页面调度,但在菜单视图上已禁用了页面调度(默认情况下应禁用),您应该一切顺利。
现在,分页滚动视图将水平滚动,但由于内容高度而不能垂直滚动。每个页面也由于其内容大小限制而垂直滚动而不是水平滚动。
如果该说明有欠缺之处,请参见以下代码:
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;
}
这是icompot的改进解决方案,对我来说这是非常不稳定的。这个很好用,很容易实现:
- (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;
}
为了将来参考,我基于Andrey Tanasov的答案,提出了以下可行的解决方案。
首先定义一个变量来存储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
}
}
}
希望这可以帮助。
我的视图由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];
现在,为了防止对角线滚动,请执行以下操作:
-(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
在touchesEnded
和中将其重置为NO touchesCancelled
。
如果您的滚动视图很大...并且您想限制对角线滚动http://chandanshetty01.blogspot.in/2012/07/restricting-diagonal-scrolling-in.html
对于那些在Swift中寻找@AndreyTarantsov第二个解决方案的人,其代码如下:
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
}
}
我们在这里所做的是在拖动scrollview之前保持当前位置,然后检查x与x的当前位置相比是增加还是减少。如果是,则将pagingEnabled设置为true,如果否(y增加/减少),则将pagingEnabled设置为false
希望对新来者有用!
我设法通过实现scrollViewDidBeginDragging(_ :)并查看了底层UIPanGestureRecognizer的速度来解决此问题。
注意:使用此解决方案时,scrollView将忽略每个对角平底锅。
override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
super.scrollViewWillBeginDragging(scrollView)
let velocity = scrollView.panGestureRecognizer.velocity(in: scrollView)
if velocity.x != 0 && velocity.y != 0 {
scrollView.panGestureRecognizer.isEnabled = false
scrollView.panGestureRecognizer.isEnabled = true
}
}
如果您正在使用界面构建器来设计界面,则可以轻松完成。
在界面生成器中,只需单击UIScrollView并选择(在检查器中)将其限制为仅一种滚动方式的选项。