【问题标题】:UITableView headers on the left side of sections (like Spotlight)部分左侧的 UITableView 标题(如 Spotlight)
【发布时间】:2011-03-03 11:43:53
【问题描述】:

找了好久,还是没找到办法。 我想将 iPhone 的 Spotlight 的部分标题复制到 UITableView 中。

众所周知,当您滚动时,“常规”表格视图标题会在部分顶部保持可见。但是,除了 Springboard 的 Spotlight 页面之外,还有一种我从未在其他地方看到过的标题:在那里,标题跨越了部分的整个高度,并且没有卡在部分的顶部,而是在左侧。

这到底是怎么做到的?

【问题讨论】:

    标签: iphone ios cocoa-touch uitableview


    【解决方案1】:

    好问题。我做了一个小实验。它几乎看起来像聚光灯下的景色。但它缺少一项导入功能。如果它们发生碰撞,下方的“图像”不会将上方的图像推到顶部。

    我怀疑是否存在不使用私有框架的内置解决方案。


    我做到了:

    如您所见,顶部的两个标题图像重叠。他们不会像普通的标题那样互相推动。而且我不得不停用细胞分离器。如果我使用它们,它们会出现在整个牢房中。所以你必须自己画它们。没有大碍。

    但我不知道如何修复重叠。

    这是实现这一点的代码:

    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
        return 1;
    }
    
    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
        UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 44)];
        contentView.backgroundColor = [UIColor lightGrayColor];
    
        UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 34, 34)] autorelease];
        imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d", section]];;
    
        [contentView addSubview:imageView];
        return [contentView autorelease];
    }
    

    【讨论】:

    • 为了处理这种重叠的怪癖,也许我们可以试试UIScrollViewDelegate-scrollViewDidScroll:?我也会做我能做的,但至少你的小原型看起来很有希望。谢谢!
    • @Matthias 我设法得到了想要的结果。请参阅下面的答案
    【解决方案2】:

    好的,我已经做了类似于音乐应用和聚光灯搜索所做的事情。

    我没有继承 UITableView,我只是通过它的 scrollViewDidScroll 方法跟踪了各个部分,并将标题视图添加到 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

    希望这会有所帮助:)。

    【讨论】:

    • 甜蜜而简单的实现。恭喜!
    • 聪明的解决方案!
    【解决方案3】:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-08
    • 1970-01-01
    • 1970-01-01
    • 2010-11-16
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多