UITableView 带有侧面部分标题图像
-
25-09-2019 - |
题
iPad 上的音乐应用程序有很多有趣的自定义 UI 功能,其中之一就是查看时显示的表格视图 特定艺术家的专辑.
它在每个部分的侧面都有图像,几乎以与部分标题视图非常相似的方式运行。如果我向下滚动,顶部图像会保留在那里,直到下一个图像出现将其撞掉,反之亦然。
最初,如果不重新实现 UITableView 似乎是不可能的,但我认为通过简单地子类化 UITableView 来在 uitableview 外部的侧面绘制这些部分图像(每当它调用时)是半可行的 layoutSubviews
(IE。每当它滚动时)。这有一些小问题:因为它在 UITableView 之外绘制,所以任何自动调整大小都可能会破坏整个布局。我真的不确定这一切的可行性。
有什么想法吗?
编辑:我刚刚意识到我的第一个想法行不通,因为图像侧本身的任何触摸都不会被桌面视图跟踪,所以如果您触摸那里,您就无法滚动。我认为这里最大的问题是弄清楚如何传播触摸,以便在整个视图中跟踪触摸。
解决方案 2
半夜胡思乱想,终于想出了一个真正的解决办法。
将 UITableview 嵌入到 UIScrollView 中,当用户滚动视图时,触摸会通过父滚动视图,而不是表视图本身。几乎您需要做的所有事情都在layoutSubviews 方法中;由于每当用户滚动视图时都会调用滚动视图的layoutSubviews,因此只需更改表格视图的框架以保持固定在屏幕上,并更改表格视图的contentOffset以匹配滚动视图的内容偏移量。
示例代码:
- (void) layoutSubviews{
tableView.frame = CGRectMake(self.contentOffset.x, self.contentOffset.y, tableView.frame.size.width, tableView.frame.size.height);
tableView.contentOffset = self.contentOffset;
}
此时,您可以将桌面视图调整到一侧,并在另一侧执行您想要的操作。
其他提示
你可以以某种方式检查你在表视图(或最顶层等)中的哪个部分,然后只需有一个 UIView ,每当该部分发生变化时就会更新,我的想法有点难以解释,但它与完全重做 UITableView,只需在表视图旁边有另一个视图来处理图像,而不是尝试嵌入该功能。
另一种方法来做到这一点,可能有点棘手,但你可以尝试缩进你的单元格,这样它们就不会从表视图的最左边开始,使表视图非常宽,并在包含该内容的节标题中有一个自定义视图左边的图像,希望能正确完成?好问题,也是一个有趣的问题。
好吧,我做了一些类似于音乐应用程序和聚光灯搜索的事情。
我没有子类化 UITableView,我只是通过它的 rollViewDidScroll 方法跟踪了各个部分,并将标题视图添加到 tableView 的左侧(因此您必须将 tableview 放在 viewController 视图的右侧,这意味着您可以'不要使用 UITableViewController)。
这个方法应该在scrollViewDidScroll、ViewDidLoad和didRotateFromInterfaceOrientation中调用:(如果您支持轮换)
请记住,您必须在左侧留出等于您支持的任何界面方向的标题大小的空间。
-(void)updateHeadersLocation
{
for (int sectionNumber = 0; sectionNumber != [self numberOfSectionsInTableView:self.tableView]; sectionNumber++)
{
// get the rect of the section from the tableview, and convert it to it's superview's coordinates
CGRect rect = [self.tableView convertRect:[self.tableView rectForSection:sectionNumber] toView:[self.tableView superview]];
// get the intersection between the section's rect and the view's rect, this will help in knowing what portion of the section is showing
CGRect intersection = CGRectIntersection(rect, self.tableView.frame);
CGRect viewFrame = CGRectZero; // we will start off with zero
viewFrame.size = [self headerSize]; // let's set the size
viewFrame.origin.x = [self headerXOrigin];
/*
three cases:
1. the section's origin is still showing -> header view will follow the origin
2. the section's origin isn't showing but some part of the section still shows -> header view will stick to the top
3. the part of the section that's showing is not sufficient for the view's height -> will move the header view up
*/
if (rect.origin.y >= self.tableView.frame.origin.y)
{
// case 1
viewFrame.origin.y = rect.origin.y;
}
else
{
if (intersection.size.height >= viewFrame.size.height)
{
// case 2
viewFrame.origin.y = self.tableView.frame.origin.y;
}
else
{
// case 3
viewFrame.origin.y = self.tableView.frame.origin.y + intersection.size.height - viewFrame.size.height;
}
}
UIView* view = [self.headerViewsDictionary objectForKey:[NSString stringWithFormat:@"%i", sectionNumber]];
// check if the header view is needed
if (intersection.size.height == 0)
{
// not needed, remove it
if (view)
{
[view removeFromSuperview];
[self.headerViewsDictionary removeObjectForKey:[NSString stringWithFormat:@"%i", sectionNumber]];
view = nil;
}
}
else if(!view)
{
// needed, but not available, create it and add it as a subview
view = [self headerViewForSection:sectionNumber];
if (!self.headerViewsDictionary && view)
self.headerViewsDictionary = [NSMutableDictionary dictionary];
if (view)
{
[self.headerViewsDictionary setValue:view forKey:[NSString stringWithFormat:@"%i", sectionNumber]];
[self.view addSubview:view];
}
}
[view setFrame:viewFrame];
}
}
我们还需要声明一个属性来保持视图可见:
@property (nonatomic, strong) NSMutableDictionary* headerViewsDictionary;
这些方法返回标题视图的大小和 X 轴偏移量:
-(CGSize)headerSize
{
return CGSizeMake(44.0f, 44.0f);
}
-(CGFloat)headerXOrigin
{
return 10.0f;
}
我已经构建了代码,以便删除任何不需要的标题视图,因此我们需要一个在需要时返回视图的方法:
-(UIView*)headerViewForSection:(NSInteger)index
{
UIImageView* view = [[UIImageView alloc] init];
if (index % 2)
{
[view setImage:[UIImage imageNamed:@"call"]];
}
else
{
[view setImage:[UIImage imageNamed:@"mail"]];
}
return view;
}
其外观如下:
它在 lanscape 中的外观如何,我使用约束在 tableView 的左侧给出 44px
希望这可以帮助 :)。