我猜你想要这样的东西:
or this:
我将表格视图放在地图视图上。我设置了表视图的contentInset
and contentOffset
像这样:
- (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);
}
请注意,虽然默认行高为 44,tableView.rowHeight
返回 -1 除非您明确设置它。 (在故事板中将其设置为 44 不会改变这一点。)
我使用了一个子类UITableView
其中我做了两件事:
我明确设置self.backgroundColor = [UIColor clearColor]
。我发现在故事板中将背景颜色设置为清除不起作用。
-
我推翻了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 项。
我通过让我的视图控制器充当表视图的委托并实现这个委托方法来做到这一点,该方法继承自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;
}
}
}
该方法经过精心编写,适用于太短而无法垂直填满屏幕的表格,以及可以垂直填满屏幕的表格。
我已经在这里上传了我的测试项目:https://github.com/mayoff/tableView-over-mapview https://github.com/mayoff/tableView-over-mapview
并排表格的更新
我不认为并排表格会成为一个好的用户界面。我认为这会令人困惑。但具体方法如下。
视图层次结构如下所示:
- Root view
MKMapView
-
MyScrollView
-
ScrollContentView
-
MyTableView
对于第一张表
-
MyTableView
对于第二个表
-
MyTableView
对于第三个表
- etc.
地图视图和滚动视图具有相同的框架。滚动视图处理横向滚动,每个表视图都可以独立地垂直滚动。
由于滚动视图应该只捕获落在表视图之一中的触摸,因此它需要一个自定义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 存储库 https://github.com/mayoff/tableView-over-mapview与这个版本。