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

时间:2013-09-25 00:47:37

标签: ios objective-c uitableview uiscrollview

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

不正确的行为:当用户在桌面视图中向上和向下滚动,但是想要快速浏览到下一页时,水平轻弹/滑动最初不起作用 - 在桌面视图静止之前它将无法工作(即使滑动非常明显是水平的)。

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


如何更改此行为 - 最简单或最好的方法是什么?


注意由于各种原因,某些答案中所述的UIPageViewController不起作用。如何使用交叉方向UIScrollViews(/ one是一个表视图,但你明白了)?我几个小时以来一直撞在墙上 - 如果你认为你可以做到这一点,那么我会非常高兴地奖励赏金。

7 个答案:

答案 0 :(得分:18)

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

子类UITableViewUITableViewUIScrollView的子类。在UITableView子类上实现一个UIScrollView的{​​{1}}委托方法

UIGestureRecognizer

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

现在将所有'UITableView的类更改为新创建的tableViewSubClass并运行项目,在tableView滚动时滑动应该可以正常工作。 :

但是当tableView滚动时,滑动看起来有点过于敏感。让我们的滑动有点限制。

子类- (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 } 。在UIScrollView子类上实现另一个UIScrollView的委托方法UIGestureRecognizer

gestureRecognizerShouldBegin:

我们希望“滑动显然是水平的”。如果x轴上的手势速度是y轴上的手势速度,则上面的代码仅允许手势开始。 [如果您喜欢,请随意增加硬编码值“2”。滑动需要更高的水平值。]

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

enter image description here

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

答案 1 :(得分:3)

enter image description here

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

  

重要说明:您不应在UIScrollView对象中嵌入UIWebView或UITableView对象。如果这样做,可能会导致意外行为   因为两个对象的触摸事件可能混淆错误   处理。

我找到了实现这个目标的好方法。

这是该问题的完整解决方案。要在UIScrollView滚动时滚动UITableView,您需要停用相关的互动。

- (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。

答案 2 :(得分:0)

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

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

此外,您可能希望从UIPageViewControllerDataSource以及可能UIPageViewControllerDelegate中的一个或多个方法实施所需的方法。

答案 3 :(得分:0)

您是否尝试过表格和滚动的方法:directionalLockEnabled并将它们设置为水平为一个而垂直为另一个?

修改:

<强> 1) 您想要做的事情非常复杂,因为触摸会等待一段时间(如0.1秒)来了解您的动作。如果你的桌子正在移动,它将立即触摸你的任何东西(因为它假设它是反应性运动)。

我没有看到任何其他解决方案,但是从头开始覆盖触摸移动以立即检测到你想要的那种方式(例如,如果移动将是水平的),但要做到这一点将会非常困难。

<强> 2) 我可以建议你的另一个解决方案是让你的桌子有左右边距,你可以触摸父卷轴(这样的页面的东西)然后即使你的桌子滚动,如果你触摸这里,只会触摸你的分页滚动。它更简单,但可能不适合您的设计......

答案 4 :(得分:0)

使用UIPageViewController并使用-viewDidLoad方法(或任何其他最符合您需求或设计的方法)获取UIPageViewController的{​​{1}}子视图并指定一个代表它。请记住,它的委托属性不会是零。因此,您可以选择将其分配给另一个引用,然后将符合UIScrollView的对象分配给它。例如:

UIScrollViewDelegate

这样您就可以轻松实现id<UIScrollViewDelegate> originalPageScrollViewDelegate = ((UIScrollView *)[pageViewController.view.subviews objectAtIndex:0]).delegate; [((UIScrollView *)[pageViewController.view.subviews objectAtIndex:0]) setDelegate:self]; 方法。您的UIScrollViewDelegate会调用您委托的UIPageViewController方法。

顺便说一句,您可能不得不保留原始委托,并使用该对象响应委托方法。您可以在我的UI控件项目here

上的-scrollViewDidScroll:类中看到示例实现

答案 5 :(得分:0)

我最近遇到了同样的事情。我的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的一半。

答案 6 :(得分:0)

您可以将滚动视图和表格视图子类化,并将此手势识别器委托方法添加到每个视图中......

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

我不能确定这是完全你所追求的是什么,但它可能会接近。