2009-07-02 50 views
120

我正在使用UITableView来布置内容'网页'。我使用表视图的标题来布局某些图像等,如果它们没有浮动但是保持静态,就像样式设置为时那样,我更喜欢它。是否可以通过UITableViewStylePlain在UITableView中禁用浮动标题?

其他然后使用,有没有办法做到这一点?我想避免使用分组,因为它会在我的所有单元格中添加边距,并且需要禁用每个单元格的背景视图。我想完全控制我的布局。理想情况下,他们会是一个“UITableViewStyleBareBones”,但我没有看到文档该选项...

非常感谢,

回答

23

您应该可以通过使用自定义单元格来完成您的标题行。这些将像表格视图中的其他单元格一样滚动。

您只需在cellForRowAtIndexPath中添加一些逻辑即可在标题行中返回正确的单元格类型。

虽然您可能必须自己管理自己的部分,即将所有内容都放在一个部分中并假冒标题。 (您也可以尝试为标题视图返回隐藏视图,但我不知道这是否可行)

+9

是啊...它似乎有点黑客。这看起来像是一个苹果公司的一部分,显然代码是在那里做的,我们只需要能够设置一个标志。 – Tricky 2009-07-02 13:54:26

-4

您可以轻松地在实现代码如下委托类实现viewForHeaderInSection方法实现这一目标。这个方法需要一个UIView作为返回对象(这是你的标题视图)。我在我的代码中做了同样的事情

+0

我也做到了这一点,当您滚动时,返回的视图仍然浮动... – Tricky 2009-07-02 12:31:20

+0

原始海报不需要自定义标题。他们想要一个不会“浮动”在表格顶部的标题。你的建议仍然浮动。 – jemmons 2010-07-19 00:05:03

60

警告:此解决方案实现了预留的API方法。这可能会阻止该应用程序被苹果批准在AppStore上发布。

我所描述的私有方法节头浮在my blog

基本的,轮流,你只需要继承UITableView和它的两个方法返回NO

- (BOOL)allowsHeaderViewsToFloat; 
- (BOOL)allowsFooterViewsToFloat; 
+27

仅仅因为它引用了私有API(不是每个人都在编写要提交给AppStore的代码),答案都不值得赞赏。当答案正确时,这是双重的。为这些方法返回NO的子类化(或者更简单地说,创建一个UITableView类别)会阻止标头浮动。 如果您希望将此功能添加为公共API,请提交错误报告:http://bugreport.apple.com – jemmons 2010-07-19 00:18:17

+4

如果我们在应用程序中实现该功能,苹果如何意识到您正在使用私人API?从他们所知道的,我只是在UITableView的子类中实现了一个方法,他们甚至不需要拆卸代码就看不到它,并且它不会那么容易。它不是在私人API中调用方法,它只是实现一个... – 2012-01-25 19:46:53

0

忽略XAK。如果您希望自己的应用有机会被苹果接受,请不要探索任何私人方法。

如果您使用Interface Builder,这是最容易的。你可以在视图的顶部添加一个UIView(图像将放在那里),然后在下面添加你的tableview。 IB应相应地调整它的大小;也就是说,tableview的顶部会触及刚刚添加的UIView的底部,并且它的高度覆盖了屏幕的其余部分。

这里的想法是,如果该UIView实际上不是表视图的一部分,它将不会与tableview一起滚动。即忽略tableview标题。

如果您不使用接口构建器,它会更复杂一点,因为您必须为tableview获取正确的位置和高度。

+0

这不回答问题。 Tricky指的是titleHeaderViews,它是位于单元格之间的视图,而不是表格标题视图,这是您似乎暗示的。 – 2010-06-15 13:52:22

258

一个可能更容易的方式来实现这一目标:

的Objective-C:

CGFloat dummyViewHeight = 40; 
UIView *dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, dummyViewHeight)]; 
self.tableView.tableHeaderView = dummyView; 
self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0); 

斯威夫特:

let dummyViewHeight = CGFloat(40) 
self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight)) 
self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0) 

节头现在将滚动就像任何普通的细胞。

+4

这个friggin就像一个魅力!表格标题视图标题的存在会停止浮动的章节标题。并且为表格提供适当内容的无形标题可以做到这一点。非常感谢!想知道为什么这个答案没有得到太多的关注 – 2012-06-11 11:45:57

+2

还是不信!没有私人API,没有深入课堂,没有什么!我一直在面对这个问题很长时间,并且一直在滚动视图的顶部添加tableviews(禁用tableview滚动),这将使表格标题正常滚动。但刚开始搜索苹果是否提供了新的方法来解决这个问题..很高兴我偶然发现了你的答案。再次感谢 – 2012-06-11 11:53:57

+0

你用这件小事拯救了我的一天。按预期工作,不需要单行代码。我很惊讶。谢谢你,先生! – 2012-09-12 20:48:49

16

关于UITableViewStyleGrouped有趣的是,tableView将样式添加到单元格而不是TableView。

样式作为backgroundView添加到单元格中,作为名为UIGroupTableViewCellBackground的类,该类根据该部分中单元格的位置处理绘制不同背景。

所以有一个非常简单的解决方案将是cellForRow使用UITableViewStyleGrouped,该表的backgroundColor设置为clearColor,并且只需更换backgroundView细胞:

cell.backgroundView = [[[UIView alloc] initWithFrame:cell.bounds] autorelease]; 
+1

这应该是最好的答案。这里有一篇关于它的博客文章:http://corecocoa.wordpress.com/2011/09/17/how-to-disable-floating-header-in-uitableview/ – Sam 2012-03-28 14:05:27

+0

该解决方案实际上并不奏效。我一直在周围的单元周围获得额外的空间。任何想法 ? – gsempe 2012-09-12 14:34:30

4

虽然这也许不能解决你的问题,当我想做类似的事情时,它为我做了。而不是设置标题我使用了上面部分的页脚。保存我的是,这部分本质上是小而静的,所以它从来没有滚动到视图的底部。

+0

好主意。我喜欢这个黑客。 – 2012-01-31 21:21:20

+0

有点可笑。欣赏这个想法,但是黑客就是黑客。标题将在底部开始浮动,因此不能真正解决问题 – 2012-06-11 11:56:57

0

这可以通过在UITableViewController的viewDidLoad方法中手动分配标题视图而不是使用委托的viewForHeaderInSection和heightForHeaderInSection来实现。例如,在您的UITableViewController的子类,你可以做这样的事情:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    UILabel *headerView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 40)]; 
    [headerView setBackgroundColor:[UIColor magentaColor]]; 
    [headerView setTextAlignment:NSTextAlignmentCenter]; 
    [headerView setText:@"Hello World"]; 
    [[self tableView] setTableHeaderView:headerView]; 
} 

头视图将消失,然后当用户滚动。我不知道为什么这样工作,但它似乎达到了你想要做的。

28

好吧,我知道这是晚了,但我不得不这样做。 我花了10个小时,现在正在寻找一个工作解决方案,但没有找到完整的答案。发现了一些提示,但难以让初学者理解。所以我必须投入2美分并完成答案。

正如我在少数答案中提出的那样,我能够实现的唯一工作解决方案是在表视图中插入普通单元格并将它们作为Section Headers来处理,但实现它的更好方法是通过将这些单元格插入每个部分的第0行。这样我们就可以很容易地处理这些自定义的非浮动头文件。

所以,步骤是。

  1. 使用样式UITableViewStylePlain实现UITableView。

    -(void) loadView 
    { 
        [super loadView]; 
    
        UITableView *tblView =[[UITableView alloc] initWithFrame:CGRectMake(0, frame.origin.y, frame.size.width, frame.size.height-44-61-frame.origin.y) style:UITableViewStylePlain]; 
        tblView.delegate=self; 
        tblView.dataSource=self; 
        tblView.tag=2; 
        tblView.backgroundColor=[UIColor clearColor]; 
        tblView.separatorStyle = UITableViewCellSeparatorStyleNone; 
    } 
    
  2. 实现titleForHeaderInSection像往常一样(你可以用自己的逻辑此值,但我更喜欢使用标准的代表)。

    - (NSString *)tableView: (UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
    { 
        NSString *headerTitle = [sectionArray objectAtIndex:section]; 
        return headerTitle; 
    } 
    
  3. Immplement numberOfSectionsInTableView照常

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    { 
        int sectionCount = [sectionArray count]; 
        return sectionCount; 
    } 
    
  4. 实施numberOfRowsInSection如常。

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    { 
        int rowCount = [[cellArray objectAtIndex:section] count]; 
        return rowCount +1; //+1 for the extra row which we will fake for the Section Header 
    } 
    
  5. 返回0.0f in heightForHeaderInSection。

    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
    { 
        return 0.0f; 
    } 
    
  6. 请勿实施viewForHeaderInSection。完全移除该方法而不是返回nil。

  7. In heightForRowAtIndexPath。检查是否(indexpath.row == 0)并返回节标题所需的单元格高度,否则返回单元格的高度。

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
        if(indexPath.row == 0) 
        { 
         return 80; //Height for the section header 
        } 
        else 
        { 
         return 70; //Height for the normal cell 
        } 
    } 
    
  8. 现在的cellForRowAtIndexPath,检查(indexpath.row == 0),当你想要节头是和选择样式设置为none执行单元。 ELSE实现这个单元格就像你想要的正常单元格一样。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
        if (indexPath.row == 0) 
        { 
         UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SectionCell"]; 
         if (cell == nil) 
         { 
          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SectionCell"] autorelease]; 
          cell.selectionStyle = UITableViewCellSelectionStyleNone; //So that the section header does not appear selected 
    
          cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SectionHeaderBackground"]]; 
         } 
    
         cell.textLabel.text = [tableView.dataSource tableView:tableView titleForHeaderInSection:indexPath.section]; 
    
         return cell; 
        } 
        else 
        { 
         UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; 
    
         if (cell == nil) 
         { 
          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"] autorelease]; 
          cell.selectionStyle = UITableViewCellSelectionStyleGray; //So that the normal cell looks selected 
    
          cell.backgroundView =[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellBackground"]]autorelease]; 
          cell.selectedBackgroundView=[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SelectedCellBackground"]] autorelease]; 
         } 
    
         cell.textLabel.text = [[cellArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row -1]; //row -1 to compensate for the extra header row 
    
         return cell; 
        } 
    } 
    
  9. 现在实行willSelectRowAtIndexPath并返回零如果indexpath.row == 0,这将关心didSelectRowAtIndexPath方法永远不会被段标题行解雇。

    - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
        if (indexPath.row == 0) 
        { 
         return nil; 
        } 
    
        return indexPath; 
    } 
    
  10. 最后,在didSelectRowAtIndexPath方法,检查(indexpath.row!= 0),并继续进行。

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
        if (indexPath.row != 0) 
        { 
         int row = indexPath.row -1; //Now use 'row' in place of indexPath.row 
    
         //Do what ever you want the selection to perform 
        } 
    } 
    

有了这个,你就完成了。你现在有一个完美的滚动,非浮动部分标题。

0

检查答案如何实现与标题故事板:Table Header Views in StoryBoards

还要注意的是,如果你不执行

viewForHeaderInSection:(NSInteger)section 

它不会浮动而这正是你想要什么。

2

在思考如何解决这个问题时,我想起了关于UITableViewStyleGrouped的一个非常重要的细节。 UITableView实现分组样式(单元格周围的圆角边框)的方式是将自定义backgroundView添加到UITableViewCells,而不是UITableView。每个单元格根据其在部分中的位置添加一个backgroundView(上部的行获取部分边界的上部,中间的部分获取侧边界,底部获得 - 下部)。因此,如果我们只是想要一个简单的样式,并且我们没有为我们的单元格定制backgroundView(这是90%的时间),那么我们需要做的就是使用UITableViewStyleGrouped,并删除自定义背景。这可以通过以下这两个步骤来完成:

改变我们的tableView风格UITableViewStyleGrouped 添加以下行至cellForRow,就在我们返回的单元格:

cell.backgroundView = [[[UIView的页头] initWithFrame :cell.bounds] autorelease];

就是这样。 tableView风格将变成完全像UITableViewStylePlain,除了浮动标题。

希望这会有所帮助!

0

要完全去除浮节头节,你可以这样做:

- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 
{ 
    return [[UIView alloc] init]; 
} 

return nil不起作用。

要禁用浮动但仍显示节标题,您可以使用自己的行为提供自定义视图。

1

另一种方法是在你想要标题的那一个之前创建一个空白部分,并将标题放在该部分。由于该部分是空的,标题将立即滚动。

-2

我还有一个更简单的解决方案,而不会自动布局和一切通过XIB进行使用:

1 /放入tableview中的头球攻门被拖动和直接在tableview中删除它。

2在新制作的标题的Size Inspector中,只需更改自动调整大小:您应该只留下顶部,左侧和右侧锚点以及水平填充。

That's how it should be set for the header

这应该做的伎俩!从平原到

142

更改表格样式分组(谁曾来到这里,由于错误的表样式)

let tableView = UITableView(frame: .zero, style: .grouped) 
5

最简单的方式得到你想要设置你的表样式, 分离风格是什么UITableViewCellSeparatorStyleNone

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    return CGFLOAT_MIN; // return 0.01f; would work same 
} 

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { 
    return [[UIView alloc] initWithFrame:CGRectZero]; 
} 

不要试图返回页脚视图为nil,不要忘记设置标题高度和标题视图,之后你必须得到你想要的东西。

21

在你的Interface Builder中点击您的问题表视图

problem table view

然后导航到属性检查器和改变风格平原分组 ;)易

easy

1

您可以添加上面的一个Section(带有零行),然后将上面的SectionFooterView设置为当前节的headerView,footerView不会浮动。 希望它能提供帮助。

10

更改您的TableView风格:

self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped]; 

按照苹果文档的UITableView:

UITableViewStylePlain-一个普通的表视图。任何节标题或 页脚都显示为内联分隔符,并在滚动表 视图时显示为浮点。

UITableViewStyleGrouped-一个表格视图,其各节显示不同的 行组。部分页眉和页脚不会浮动。

希望这个小变化将帮助你..

5

还有一个取巧的办法。主要想法是将节号加倍,第一个仅显示headerView,而第二个显示实际单元。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return sectionCount * 2; 
} 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if (section%2 == 0) { 
     return 0; 
    } 
    return _rowCount; 
} 

什么需要做的是落实headerInSection代表:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 
    if (section%2 == 0) { 
     //return headerview; 
    } 
    return nil; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    if (section%2 == 0) { 
     //return headerheight; 
    } 
    return 0; 
} 

这种方法也有你的数据源的影响不大:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    int real_section = (int)indexPath.section/2; 
    //your code 
} 

与其他方法相比,这种方法是安全的,而不会改变tableview的frame或contentInsets。 希望这可能有所帮助。

-1

也许你可以简单地做头图背景透明:

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { 
    view.tintColor = [UIColor clearColor]; 
} 

或者全局应用:

[UITableViewHeaderFooterView appearance].tintColor = [UIColor clearColor]; 
1

也许你可以上的tableView 使用scrollViewDidScroll并根据电流来改变contentInset可见标题。

它似乎适用于我的用例!

extension ViewController : UIScrollViewDelegate{ 

    func scrollViewDidScroll(_ scrollView: UIScrollView) { 
     guard let tableView = scrollView as? UITableView, 
      let visible = tableView.indexPathsForVisibleRows, 
      let first = visible.first else { 
      return 
     } 

     let headerHeight = tableView.rectForHeader(inSection: first.section).size.height 
     let offset = max(min(0, -tableView.contentOffset.y), -headerHeight) 
     self.tableView.contentInset = UIEdgeInsetsMake(offset, 0, -offset, 0) 
    } 
} 
1

对于斯威夫特3+

只需使用和页脚的高度与以下设置为零:

override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 
    return .leastNormalMagnitude 
} 
0

据@ samvermette的回答,我已经实现了上述Swift中的代码使编码器可以轻松使用swift。

let dummyViewHeight = CGFloat(40) 
self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight)) 
self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0) 
0

REF:https://stackoverflow.com/a/26306212

let tableView = UITableView(frame: .zero, style: .grouped)

PLUSE

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 
    if section == 0 { 
     return 40 
    }else{ 
     tableView.sectionHeaderHeight = 0 
    } 

    return 0 
} 

这有助于使用头空间

相关问题