Is it possible to disable floating headers in UITableView with UITableViewStylePlain?

前端 未结 29 988
走了就别回头了
走了就别回头了 2020-11-29 15:02

I\'m using a UITableView to layout content \'pages\'. I\'m using the headers of the table view to layout certain images etc. and I\'d prefer it if they didn\'t

相关标签:
29条回答
  • 2020-11-29 15:33

    Ignore XAK. Do not explore any private methods if you want your app to have the chance of being accepted by apple.

    This is easiest if you are using Interface Builder. You would add a UIView at the top of the view (where the images will go), then add your tableview below that. IB should size it accordingly; that is, the top of the tableview touches the bottom of the UIView you've just added and it's height covers the rest of the screen.

    The thinking here is that if that UIView is not actually part of the table view, it will not scroll with the tableview. i.e. ignore the tableview header.

    If you're not using interface builder, it's a little more complicated because you've got to get the positioning and height correct for the tableview.

    0 讨论(0)
  • 2020-11-29 15:33

    The snippet display a sticky header only for the first section. Others section headers will float with a cells.

    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    
        if section == 1 {
            tableView.contentInset = .zero
        }
    
    }
    
    func tableView(_ tableView: UITableView, didEndDisplayingHeaderView view: UIView, forSection section: Int) {
        if section == 0 {
            tableView.contentInset = .init(top: -tableView.sectionHeaderHeight, left: 0, bottom: 0, right: 0)
        }
    }
    
    0 讨论(0)
  • 2020-11-29 15:33

    you can easily achieve this by implementing the viewForHeaderInSection method in the tableview delegate class. this method expects a UIView as return object (which is your header view). i have done this same thing in my code

    0 讨论(0)
  • 2020-11-29 15:34

    (For who ever got here due to wrong table style) Change Table style from plain to grouped, via the attributes inspector, or via code:

    let tableView = UITableView(frame: .zero, style: .grouped)
    
    0 讨论(0)
  • 2020-11-29 15:35

    Ok, i know it is late but i had to do it. I have spent 10 hours by now searching for a working solution but did not find a complete answer. Did found some hints but difficult for starters to understand. So i had to put in my 2 cents and complete the answer.

    As it has been suggested in the few of the answers the only working solution that i was able to implement is by inserting normal cells in the table view and handle them as Section Headers, but the better way to achieve it is by inserting these cells at row 0 of every section. This way we can handle these custom non-floating headers very easily.

    So, the steps are.

    1. Implement UITableView with style UITableViewStylePlain.

      -(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. Implement titleForHeaderInSection as usual ( you can get this value by using your own logic, but I prefer to use standard delegates ).

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

      - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
      {
          int sectionCount = [sectionArray count];
          return sectionCount;
      }
      
    4. Implement numberOfRowsInSection as usual.

      - (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. Return 0.0f in heightForHeaderInSection.

      - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
      {
          return 0.0f;
      }
      
    6. DO NOT implement viewForHeaderInSection. Remove the method completely instead of returning nil.

    7. In heightForRowAtIndexPath. Check if(indexpath.row == 0) and return the desired cell height for the section header, else return the height of the cell.

      - (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. Now in cellForRowAtIndexPath, check if(indexpath.row == 0) and implement the cell as you want the section header to be and set the selection style to none. ELSE implement the cell as you want the normal cell to be.

      - (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. Now implement willSelectRowAtIndexPath and return nil if indexpath.row == 0. This will care that didSelectRowAtIndexPath never gets fired for the Section header row.

      - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
      {
          if (indexPath.row == 0)
          {
              return nil;
          }
      
          return indexPath;
      }
      
    10. And finally in didSelectRowAtIndexPath, check if(indexpath.row != 0) and proceed.

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

    With this you are done. You now have a perfectly scrolling, non-floating section header.

    0 讨论(0)
  • 2020-11-29 15:37

    You should be able to fake this by using a custom cell to do your header rows. These will then scroll like any other cell in the table view.

    You just need to add some logic in your cellForRowAtIndexPath to return the right cell type when it is a header row.

    You'll probably have to manage your sections yourself though, i.e. have everything in one section and fake the headers. (You could also try returning a hidden view for the header view, but I don't know if that will work)

    0 讨论(0)
提交回复
热议问题