UITableView don't float section headers - objective-c

Is it possible to not float the section headers for a UITableView with style UITableViewStylePlain?
I'm building AcaniChat, an open-source version of iPhone's native Messages app, and I want to make the timestamps section headers, but they shouldn't float.
I know that section headers don't float for table views of style UITableViewStyleGrouped, but that style looks less like what I'm going for. Should I just use that style and restyle the table view to make it look how I want?
I might do that if I can figure out how to make https://stackoverflow.com/questions/6564712/nsfetchedresultscontroller-nsdate-section-headers.

The interesting thing about UITableViewStyleGrouped is that the tableView adds the style to the cells and not to the TableView.
The style is added as backgroundView to the cells as a class called UIGroupTableViewCellBackground which handles drawing different background according to the position of the cell in the section.
So a very simple solution will be to use UITableViewStyleGrouped, set the backgroundColor of the table to clearColor, and simply replace the backgroundView of the cell in cellForRow:
cell.backgroundView = [[[UIView alloc] initWithFrame:cell.bounds] autorelease];

I guess either you will have to use two kinds of custom tableCells or skip the tableview entirely and work on a plain scrollview to achieve this kind of style.

This can now be done in two quick and easy steps (iOS 6 only):
Change your UITableView style to UITableViewStyleGrouped. (You can do this from Storyboard/NIB, or via code.)
Next, set your tableview's background view to a empty view like so [in either a method such as viewDidAppear or even in the cellForRow method (though I would prefer the former)].
yourTableView.backgroundView = [[UIView alloc] initWithFrame:listTableView.bounds];
Voila, now you have your table view - but without the floating section headers. Your section headers now scroll along with the cells and your messy UI problems are solved!
This works because UITableViewStyleGrouped seems to now work by adding a background view to a plain UITableView, but without the floating section headers.
[N.B. Earlier to iOS 6, individual background images were added to UITableViewCell's.]
Do try this out and let me know how it goes.
Happy coding :)
EDIT: for iOS 7, simply change the table view style to 'UITableViewStyleGrouped' and change the view's tint color to 'clear color'.

You can achieve this by putting the headers into their own sections. First double your number of sections. Then for the even-numbered sections, return your header as the header and zero as the number of rows. For the odd-numbered sections, return nil for the header.
Assuming you're using an NSFetchedResultsController, it would look something like this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.fetchedResultsController.sections.count * 2;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if ((section % 2) == 0)
{
section /= 2;
id<NSFetchedResultsSectionInfo> sectionInfo = self.fetchedResults.sections[section];
return sectionInfo.name;
}
else
{
return nil;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ((section % 2) == 0)
{
return 0;
}
else
{
section /= 2;
id<NSFetchedResultsSectionInfo> sectionInfo = self.fetchedResults.sections[section];
return sectionInfo.numberOfObjects;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ((indexPath.section % 2) == 0)
{
return nil;
}
else
{
indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section/2];
id object = [self.fetchedResultsController objectAtIndexPath:indexPath];
// configure your cell here.
}
}

Related

Can't remove lines behind SearchResultsTableView cells

I'm creating an iphone application using Objective-C/Xcode. I have a setup where when I click the search box, the search display view shows up and as I type into the searchbox, the searchDisplayController loads the searchResultsTableView cells with rows consisting of autocomplete terms.
because the results cells are a lot bigger than the autocomplete cells, I have the following to manage row height:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return 30;
} else {
return 90;
}
}
However I get some weird behavior where the separator lines behind the cells are showing and making an ugly appearance.
(To clarify which separator lines are coming from where, I used
self.searchDisplayController.searchResultsTableView.separatorColor = [UIColor redColor];
)
Do you know how I could remove/hide these background separator lines from being shown in this view? I've tried various color/transparency and cell size manipulations and searched google/SO but could not figure it out.
Try changing your tableView to style to Grouped

Header views height for grouped UITableView on iOS7

I'm building my settings screen and using a grouped table view.
When trying to set the headers I see spacing above my header view.
I double checked and I do pass the correct view height in -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section.
Here is a screenshot of this behavior:
You can see my view with the title (VIBRATE, SILENT MODE) in it and it's darker bg color and the brighter space above it.
After much searching, I have finally found a fix for this. The tableview's delegate needs to implement heightForFooterInSection and return a very small number. Returning 0 defaults to the same spacing that was causing the extra spaces.
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return CGFLOAT_MIN;
}
Try this:
- (void)viewWillAppear:(BOOL)animated{
CGRect frame = self.tableView.tableHeaderView.frame;
frame.size.height = 1;
UIView *headerView = [[UIView alloc] initWithFrame:frame];
[self.tableView setTableHeaderView:headerView];
}
This is pretty much the same as Casey's response, however, it is a bit cleaner as it doesn't require implementing a delegate method. When you are setting up your table view, simply set the property sectionFooterHeight to 0. It accomplishes the same thing with less code (and no DBL_MIN oddness).
tableView.sectionFooterHeight = 0.0;
Pretty sure it is just a simple hack. But an easy way to do it is to write this function:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 48.0f; // header height
}
to customize its height.
Pretty sure there are other ways to do it, that I don't know of.
It seems that Apple made a conscious design decision to make grouped table views have extra space on top. Try adjusting the contentInset of the UITableView. See my answer here
Swift 2.2 version:
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.min
}

UITableView: load all cells

Is it possible to load all cells of an UITableView when the view is loaded so that they are not loaded when I'm scrolling?
(I would show a loading screen while doing this)
Please, it's the only way at my project (sorry too complicate to explain why ^^)
EDIT:
Okay let me explain you, what I'm definite doing:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [NSString stringWithFormat:#"Identifier %i/%i", indexPath.row, indexPath.section];
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSDictionary *currentReading;
if (cell == nil)
{
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
UILabel *label;
UIView *separator;
if(indexPath.row == 0)
{
// Here I'm creating the title bar of my "table" for each section
}
else
{
int iPr = 1;
do
{
currentReading = [listData objectAtIndex:iPr-1];
iPr++;
} while (![[currentReading valueForKey:#"DeviceNo"] isEqualToString:[devicesArr objectAtIndex:indexPath.section]] ||
[readingresultsArr containsObject:[currentReading valueForKey:#"ReadingResultId"]]);
[readingresultsArr addObject:[currentReading valueForKey:#"ReadingResultId"]];
//
// ...
//
}
}
return cell;
}
My error happens in the do-while-loop:
"listData" is an array with multiple dictionaries in it.
My problem ist that when I’m scrolling my table slowly down, all is fine, but when I’m scrolling quickly to the end of the view and then I’m scrolling to the middle, I get the error that iPr is out of the array’s range. So the problem is, that the last row of the first section has already been added to the "readingresultsArr", but has not been loaded or wants to be loaded again.
That’s the reason why I want to load all cells at once.
You can cause all of the cells to be pre-allocated simply by calling:
[self tableView: self.tableView cellForRowAtIndexPath: indexPath];
for every row in your table. Put the above line in an appropriate for-loop and execute this code in viewDidAppear.
The problem however is that the tableView will not retain all of these cells. It will discard them when they are not needed.
You can get around that problem by adding an NSMutableArray to your UIViewController and then cache all the cells as they are created in cellForRowAtIndexPath. If there are dynamic updates (insertions/deletions) to your table over its lifetime, you will have to update the cache array as well.
put a uitableview on a uiscrollview
for example , you expect the height of the full list uitableview is 1000
then set the uiscrollview contentsize is 320X1000
and set the uitableview height is 1000
then all cell load their content even not visible in screen
In my case it was that I used automaticDimension for cells height and put estimatedRowHeight to small that is why tableview loaded all cells.
Some of the answers here and here suggest using automaticDimension for cells height and put mytable.estimatedRowHeight to a very low value (such as 1).
Starting with iOS 15 this approach seems not to work anymore. Hence, another way to achieve the table to "load" all cells could be by automatically scrolling to the last cell. Depending on the tables height and how many rows it can show some cells are discarded but each cell would be loaded and shown at least once.
mytable.scrollEnabled = YES;
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:cellCount - 1 inSection:0];
[mytable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
mytable.scrollEnabled = NO;
If you want to scroll up again just scroll to the top as outlined here.
Following the comment that was made by juancazalla, I found that if you have a tableView that is using automaticDimension, loading all the cells at once can be best achieved by setting estimatedRowHeight to a low value (such as 1).

How does manually assigning tableView.rowheight affect subviews of the given Table View?

I have a custom view for displaying application status messages that I slide over my table view as needed. This worked fine until I started customizing my table view cells.
When I manually assign a row height to my table view cells in initWithSTyle...
self.TableView.rowHeight = 64.0;
...the custom view doesn't show up anymore.
I replaced the code above with a delegate method...
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 64.0;
}
...and now the custom view works as before.
Set rowHeight in the view controller.
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.rowHeight = 64.0f;
}
I think initWithStyle is too early to set the height. Eitherway, since your height is constant, it's still more efficient to set the height once (in viewDidLoad) than set it every time for each cell created (in initWithStyle or heightForRowAtIndexPath).
Did you create a custom cell class inheriting UITableVIewCell , if yes , then the height of customcell is different than the height of default cell.So you need to change the height of row to match your customcell;s in order for it to desplay correctly,Else cellswill overlap.
To Dynamically set height accoring to your customcell:-
YourCustomCell *cell = (YourCustomCell *)[tableView cellForRowAtIndexPath:indexPath];
return [cell.frame.size.height];
maintableView = [[UITableView alloc] init];
maintableView.frame = CGRectMake(0, 0, 320, 480);
maintableView.rowHeight = 100.0;
maintableView.delegate=self;
maintableView.dataSource=self;
It is working in my Xcode. Try like it. I think it will work.

UITableView Section Footer overlaps when scrolling

I have a UItableview for which i had the section header & footer programatically.
Initially i had problems with the sectio header overlapping on scroll which i solved using the scrollViewDidScroll delegate as
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
heightForHeader = 40.0;
if (scrollView.contentOffset.y<=heightForHeader&&scrollView.contentOffset.y>=0) {
scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
} else if (scrollView.contentOffset.y>=heightForHeader) {
scrollView.contentInset = UIEdgeInsetsMake(-heightForHeader, 0, 0, 0);
}
}
now the next issue is with the section footer that is overlapping while scrolling.
Can you help me with this?
Do you set your custom heights for header and footer?
Your table view delegate should implement this methods:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
which should return appropriate values.
If you return smaller values then your header and footer views have, then they may overlap.
You are looking for this: I have tested it and it works
CGFloat sectionFooterHeight = 40;
CGFloat tableViewHeight = self.tableView.frame.size.height;
if (scrollView.contentOffset.y=tableViewHeight) {
scrollView.contentInset = UIEdgeInsetsMake(0, 0,-scrollView.contentOffset.y, 0);
} else if (scrollView.contentOffset.y>=sectionFooterHeight+self.tableView.frame.size.height) {
scrollView.contentInset = UIEdgeInsetsMake(0, 0,-sectionFooterHeight, 0);
}
I ran into the same kind of issue today for small screen iphone. May be it will be helpful for someone who deals with tableview with less number of cells in section with big header/Footer views.
First of all, the Headers and footers wont scroll along the cell unless you don't have any more cell to view while scrolling. So, if you got just two or three cells and a big Footer view then it will definitely over lap. One way to tackle this is adding the footer view as last cell of the section. This is just my work around.