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;
}

其外观如下:

the section's header is moving out of the screen as it's section does

the section's header is moving with the section's origin

它在 lanscape 中的外观如何,我使用约束在 tableView 的左侧给出 44px

in landscape orientation希望这可以帮助 :)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top