刷UITableView到屏幕上,保持刷卡?

我想要一个从屏幕开始的桌面视图,可以在屏幕上滚动,到达顶部,并保持滚动。 我已经做了下面的期望的交互的视觉。

我已经尝试过两件事,而且两件事情都不像我需要的那样工作。

我做的第一件事是把tableview放在滚动视图中,当在tableview中检测到平移时移动滚动视图。 这阻止了桌面视图中的触摸,即使我可以检测到tableview在屏幕的顶部时,我不知道如何继续滚动。

我尝试的第二件事是将scrollview的内容大小设置为tableview的高度。 这让tableview滚动,但我似乎只能在标签为“List Item 1”的最初的小矩形中接触到。 随着tableview的滚动,我不能抓住中间,再滚动它。

build立这种交互的最佳方式是什么? 编辑 :地图围绕这个底部视图的左侧,右侧,主要是顶部。 当底视图被拉起时,地图在左侧和右侧可见。

1.)
1

2.)
2

3.)(并保持滚动列表中的项目数量。
3

我想你想要这样的东西:

小名单

或这个:

大名单

我在地图视图上布置了我的桌子视图。 我设置表视图的contentInsetcontentOffset像这样:

 - (void)viewDidLoad { [super viewDidLoad]; self.tableView.rowHeight = 44; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.tableView.contentInset = (UIEdgeInsets){ .top = self.view.bounds.size.height - self.tableView.rowHeight }; self.tableView.contentOffset = CGPointMake(0, -self.tableView.contentInset.top); } 

请注意,尽pipe默认行高是44,但tableView.rowHeight返回-1,除非您明确设置它。 (在故事板中将其设置为44并不会改变这一点。)

我使用了UITableView一个子类,其中我做了两件事:

  1. 我明确地设置了self.backgroundColor = [UIColor clearColor] 。 我发现在故事板中设置背景颜色清除不起作用。

  2. 我覆盖pointInside:withEvent: ::

     - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { return point.y >= 0 && [super pointInside:point withEvent:event]; } 

请注意,您并不关心contentInset 。 表视图的contentOffset.y (与bounds.origin.y相同)在其顶级内容插图公开时被设置为负数。 当项目0的顶部位于表格视图的顶部边缘时,它被设置为0,而当位于屏幕底部边缘的项目不是这种情况。

另一件你可能想要的是防止桌子停在屏幕上的一半。 如果用户拖动屏幕上半部分的项目0,则需要滚动表格以使项目0完全位于屏幕的顶部(如果有足够的项目),并且如果用户在屏幕中间拖动项目0,你希望表格滚动,只是项目0显示。

我通过使我的视图控制器作为表视图的委托,并实现这个inheritance自UIScrollViewDelegate委托方法:

 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { CGFloat yMin = -self.tableView.contentInset.top; CGFloat yMax = MIN(0, self.tableView.contentSize.height - self.tableView.bounds.size.height); if (targetContentOffset->y < yMax) { if (velocity.y < 0) { targetContentOffset->y = yMin; } else { targetContentOffset->y = yMax; } } } 

该方法是精心编写的,因此它适用于表格太短而不能垂直填充屏幕,以及可以垂直填充屏幕的表格。

我上传了我的testing项目: https : //github.com/mayoff/tableView-over-mapview

更新并排表格

我不认为并排桌将是一个很好的用户界面。 我认为这会令人困惑。 但是,这是你如何做到的。

视图层次结构如下所示:

  • 根视图
    • MKMapView
    • MyScrollView
      • ScrollContentView
        • MyTableView第一个表
        • MyTableView的第二个表
        • MyTableView为第三个表
        • 等等

地图视图和滚动视图具有相同的框架。 滚动视图处理横向滚动,每个表视图可以独立地垂直滚动。

由于滚动视图应该只捕获在某个表视图中的触摸,所以它需要一个自定义的hitTest:withEvent:在任何表视图之外返回nil触摸:

 @implementation MyScrollView - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; return hitView == self ? nil : hitView; } @end 

但是这不会真的做这个工作,因为(在我的实现中)滚动视图只有一个大的子视图ScrollContentView 。 所以我们需要在ScrollContentView做同样的事情:

 @implementation ScrollContentView - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; return hitView == self ? nil : hitView; } 

如果它们落在表格之外,则足以将触摸传递到地图视图。

我也使用ScrollContentView来布置表格并设置滚动视图的内容大小:

 - (void)layoutSubviews { [super layoutSubviews]; // Layout of subviews horizontally: // [gutter/2][gutter][subview][gutter][subview][gutter][subview][gutter][gutter/2] // where 3 * gutter + subview = width of superview CGSize superSize = self.superview.bounds.size; CGFloat x = kGutterWidth * 3 / 2; CGFloat subWidth = superSize.width - kGutterWidth * 3; for (UITableView *subview in self.subviews) { subview.frame = CGRectMake(x, 0, subWidth, superSize.height); x += subWidth + kGutterWidth; CGFloat topInset = superSize.height - subview.rowHeight; subview.contentInset = (UIEdgeInsets){ .top = topInset }; subview.contentOffset = CGPointMake(0, -topInset); } x += kGutterWidth / 2; self.frame = CGRectMake(0, 0, x, superSize.height); ((UIScrollView *)self.superview).contentSize = self.bounds.size; _pageWidth = subWidth + kGutterWidth; } 

我也让我的视图控制器滚动视图的委托,并实施委托方法强制滚动视图停止“页”(表)的边界:

 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { CGFloat pageWidth = contentView.pageWidth; // Force scroll view to stop on a page boundary. CGFloat pageNumber = targetContentOffset->x / pageWidth; if (velocity.x < 0) { pageNumber = floor(pageNumber); } else { pageNumber = ceil(pageNumber); } pageNumber = MAX(0, MIN(pageNumber, contentView.subviews.count - 1)); targetContentOffset->x = pageNumber * pageWidth; } 

结果:

多个表并排

我用这个版本更新了git仓库 。

你应该能够很容易地做到这一点,通过设置你的表视图的顶级contentInset到一个很高的位置(如评论中的沙),然后使你的UITableView的子类,所以你可以覆盖-pointInside:withEvent: 使用这个和当前的contentOffset ,你可以确定传入的事件是否在你想要滚动的区域内,并相应地返回YES或NO; 如果您返回NO,那么触摸应该按照预期进入地图视图。

为什么不完全改变这一点。 你说你有一个地图“下面”的tableview。 所以当向上滚动时,地图会被表格视图隐藏。 我想当你再次向下滚动时,地图会显示出来?

您应该能够通过使用UITableView标头来完成此操作。 节标题或表视图标题。 滚动时,他们的performance稍有不同。

我也许会这样做…

table view header上使用table view header 。 在这个标题你放置你的地图视图。

默认情况下,这将被固定到桌面的顶部,所以如果您向上滚动表格,地图会随着滑动到屏幕的顶部。

但是,如果你然后拦截滚动视图的委托方法- (void)scrollViewDidScroll:(UIScrollView *)scrollView; 那么你可以计算出表格是否向上滚动并偏移地图视图,以便它保持在原来的位置。

即如果表格滚动到(0,10),然后将地图偏移到(0,-10),看起来它没有移动。

这会给你tableview的滚动和滚动function,并保持地图的视图和响应触摸。