2010-08-04 64 views
1

iPad上的音乐应用程序有很多有趣的自定义UI功能,其中之一是查看albums of a particular artist时显示的桌面视图。UITableView带有侧面标题图片

它在每个部分的边上都有图像,几乎与部分标题视图的行为非常类似。如果向下滚动,顶部图像将保留在那里,直到下一张图像出现时才会将其关闭,反之亦然。

最初,它似乎没有再次全部重新实现的UITableView完全不可能的,但我认为这是半可行通过简单地继承一个UITableView到一边绘制这些部分的图像,UITableView的外面,每当它调用layoutSubviews(即每当它滚动)。这有一些小问题:因为它在UITableView的外部绘制,任何自动调整都可能会抛出整个布局。我真的不确定这一切的可行性。

有什么想法?


编辑:我只是意识到,我的第一个想法不会在任何接触图像方面自己不会跟踪的tableview,所以你不能滚动,如果你碰到那里。我认为这里最大的问题是弄清楚如何传播触觉,以便触及整个视图。

回答

0

在半夜随机思考它之后,我终于想出了一个真正的解决方案。

将UITableview嵌入到UIScrollView中,当用户滚动视图时,触摸通过父滚动视图,而不是通过tableview本身。几乎所有你需要做的事都在于layoutSubviews方法;因为每当用户滚动视图时都会调用scrollview的layoutSubviews,只需更改tableview的框架以保持固定在屏幕上,然后将tableview的contentOffset更改为与scrollview的内容匹配。

示例代码:

- (void) layoutSubviews{ 
    tableView.frame = CGRectMake(self.contentOffset.x, self.contentOffset.y, tableView.frame.size.width, tableView.frame.size.height); 
    tableView.contentOffset = self.contentOffset; 
} 

在这一点上,你可以调整的tableview到一边,做你想做的另一方。

1

你可以通过某种方式检查你在tableview(或者最上面的那个)中的哪个部分,然后只要有一个UIView在部分改变时得到更新,我的想法有点难以解释,但它不会与重做UITableView完全相关,只是在表视图旁边有另一个视图来执行映像,而不是试图嵌入该功能。

另一种方法来做到这一点,也许有点棘手,但你可以尝试缩进你的单元格,以便他们不开始在表视图的左边,使tableview非常广泛,并在该部分有一个自定义视图在左侧包含该图片的标题,希望能够正确地做到这一点?很好的问题和一个有趣的玩法。

+0

实际上,两者的结合听起来很可行。在位于单元格旁边的tableview中添加子视图,以及“缩进”单元格,以便表格和侧视图不重叠。 – 2010-08-04 22:38:58

+1

是的。无论如何,我相信它是一个有趣的用户界面实验,并且我希望看到你是否能够获得理想的效果:) – 2010-08-04 23:07:01

+0

好吧,显然这是可能的,就像我用我的原型做的那样。但是它需要来自数据源/委托方的大量帮助,以便“缩进”单元格和节标题。无法弄清楚如何在桌面视图本身中完成所有这些独立功能,但我想我不能太挑剔。 – 2010-08-05 21:41:23

0

好吧我已经做了类似于音乐应用和聚光灯搜索的功能。我已经通过它的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; 
} 

下面是它的外观:

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,我用约束上给予44px中的的tableView

in landscape orientation 希望这有助于:)。