交叉定向UIScrollViews – 我可以修改滚动行为吗?

以下是滚动视图的工作方式:一个滚动视图在水平方向上启用分页。 这个滚动视图的每个“页面”都包含一个垂直滚动的UITableView。 没有修改,这工作正常,但不完美。

不正确的行为:当用户在桌面上上下滚动,但想要快速翻到下一页时,水平轻扫/轻扫将不会起作用 – 直到桌面视图静止(即使滑动非常清晰)。

它应该如何工作:如果滑动明显水平,即使表视图仍然在滚动/弹跳,我希望页面可以改变,因为这也是用户期望的。

我怎样才能改变这种行为 – 什么是最简单或最好的方式?

注意由于各种原因,某些答案中所述的UIPageViewController将不起作用。 我怎样才能做到这一点横向UIScrollViews(/一个是表视图,但你明白了)? 我已经把我的头撞墙了几个小时 – 如果你认为你可以做到这一点,那么我会高兴地奖励赏金。

根据我对这个问题的理解,只有在tableView正在滚动的时候,我们才想改变默认行为。 所有其他的行为将是相同的。

子类UITableViewUITableViewUIScrollView的子类。 在UITableView实现一个UIScrollViewUIGestureRecognizer的委托方法

 - (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UISwipeGestureRecognizer *)otherGestureRecognizer { //Edit 1 //return self.isDecelerating; //return self.isDecelerating | self.bounces; //If we want to simultaneous gesture on bounce and scrolling //Edit 2 return self.isDecelerating || self.contentOffset.y < 0 || self.contentOffset.y > MAX(0, self.contentSize.height - self.bounds.size.height); // @Jordan edited - we don't need to always enable simultaneous gesture for bounce enabled tableViews } 

因为我们只想在tableView减速时更改默认的手势行为。

现在将所有'UITableView的类更改为新创build的tableViewSubClass并运行该项目,刷新应该在tableView滚动时工作。 :]

但是当tableView正在滚动时,滑动看起来有点过于敏感。 让我们轻扫一下。

子类UIScrollView 。 在UIScrollView子类上实现另一个UIGestureRecognizer的委托方法gestureRecognizerShouldBegin:

 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) { CGPoint velocity = [(UIPanGestureRecognizer *)gestureRecognizer velocityInView:self]; if (abs(velocity.y) * 2 < abs(velocity.x)) { return YES; } } return NO; } 

我们想让“轻扫明显水平”。 上面的代码只允许在x轴上的手势速度是y轴上的手势速度的情况下开始手势。 [如果你喜欢,可以随意增加硬编码值“2”。 滑动的值越高,水平越高。]

现在将`UiScrollView'类(有多个TableViews)更改为ScrollViewSubClass。 运行该项目。 :]

在这里输入图像说明

我在gitHub上做了一个项目https://github.com/rishi420/SwipeWhileScroll

在这里输入图像说明

虽然苹果不太喜欢这个方法:

重要说明:您不应该在UIS​​crollView对象中embeddedUIWebView或UITableView对象。 如果这样做,可能会导致意外的行为,因为两个对象的触摸事件可能会混淆并被错误地处理。

我发现了一个很好的方法来实现这一点。

这是一个完整的解决scheme。 为了在UITableView滚动的时候滚动UIScrollView ,你需要禁用你所拥有的交互。

 - (void)viewDidLoad { [super viewDidLoad]; _myScrollView.contentSize = CGSizeMake(2000, 0); data = [[NSMutableArray alloc]init]; for(int i=0;i<30;i++) { [data addObject:[NSString stringWithFormat:@"%d",i]]; } UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; [self.view addGestureRecognizer:tap]; } - (void)handleTap:(UITapGestureRecognizer *)recognizer { [_myTableView setContentOffset:_myTableView.contentOffset animated:NO]; } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { scrollView.userInteractionEnabled = NO; } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { scrollView.userInteractionEnabled = YES; } 

总结上面的代码,如果UITableView正在滚动,请将userInteractionEnabled设置为NO这样UIScrollView将检测到滑动。 如果UITableView正在滚动,并且用户在屏幕上点击, userInteractionEnabled将被设置为YES。

而不是使用UIScrollView作为这些多个表视图的容器,请尝试使用UIPageViewController

您甚至可以将其作为child view controller (直接replaceUIScrollView )集成到您现有的视图控制器设置中。

另外,你可能想从UIPageViewControllerDataSource实现所需的方法,也可能需要从UIPageViewControllerDataSource实现一个或多个方法。

你有没有尝试方法: directionalLockEnabledlocking启动你的表和滚动,并将其设置为一个水平为一个和另一个垂直?

编辑:

1)你想要做的是非常复杂的,因为触摸等一段时间(如0.1s)知道你的动作将是什么。 如果你的桌子正在移动,它会马上接触到你的任何东西(因为它被认为是react native的运动)。

我没有看到任何其他的解决scheme,而是从头开始重写触摸移动,以便立即检测到你想要的移动types(比如移动是水平的),但是要做到这一点很难。

2)我可以build议你的另一个解决scheme是让你的表有左右边距,你可以触摸父滚动(页面的东西),然后即使你的表滚动,如果你触摸这里,只有你的分页滚动将被感动。 这很简单,但不适合你的devise也许…

使用UIPageViewController-viewDidLoad方法(或任何其他最适合您的需求或devise的方法)获取UIPageViewControllerUIScrollView子视图并为其分配一个委托。 请记住,它的代表财产不会是零。 因此,可以select将其分配给另一个引用,然后将符合UIScrollViewDelegate对象分配给它。 例如:

 id<UIScrollViewDelegate> originalPageScrollViewDelegate = ((UIScrollView *)[pageViewController.view.subviews objectAtIndex:0]).delegate; [((UIScrollView *)[pageViewController.view.subviews objectAtIndex:0]) setDelegate:self]; 

这样你就可以轻松实现UIScrollViewDelegate方法。 而你的UIPageViewController会调用你的委托的-scrollViewDidScroll:方法。

顺便说一句,您可能有义务保留原始代表,并用该对象回应代表方法。 你可以在我的UI控制项目的ViewPagerController类中看到一个示例实现

我最近面对同样的事情。 我的UIScrollview处于分页模式,每个页面都包含一个UITableView ,就像你描述的那样工作,但不像你预期的那样工作。 这是如何解决它。

首先,我禁用了UIScrollview的滚动

然后,我将UISwipeGestureRecognizer添加到实际的UITableView左右滑动。

这些动作是:

 [scroll setContentOffset:CGPointMake(currentPointX + 320, PointY) animated:YES]; //Or [scroll setContentOffset:CGPointMake(currentPointX - 320 , PointY) animated:YES]; 

这完美地工作,唯一的缺点是,如果用户在UITableVIew上拖动他的手指,将被视为一个滑动。 他将无法在同一屏幕上看到屏幕A的一半和屏幕B的一半。

你可以子类化你的滚动视图和你的表视图,并将这个手势识别器委托方法添加到他们每个…

  - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer: (UIGestureRecognizer *)otherGestureRecognizer { return YES; } 

我不能确定这是你究竟是什么,但它可能会接近。