I have a uitableview with a tablefooterview. I would like use cell separators within the tableview but would like to get rid of the full screen width separator placed by default between the tableview and the tablefooterview. I have tried
if ([cell respondsToSelector:#selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
and
cell.separatorInset = UIEdgeInsetsMake(0, cell.bounds.size.width, 0, 0);
but neither works
Have a look at this sample implementation.
You can see here that UITableView with plain style does in fact loose the last separator if a footerView is set.
(Orange view is the footerView and there is no separator above him)
Of course in Grouped tableView this does not work as discussed in comments under your question.
https://gist.github.com/bartekchlebek/2b05b5ddcc3efec3f514
#import "ViewController.h"
#interface ViewController () <UITableViewDataSource>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds
style:UITableViewStylePlain];
tableView.dataSource = self;
tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
footerView.backgroundColor = [UIColor orangeColor];
tableView.tableFooterView = footerView;
[self.view addSubview:tableView];
}
#pragma mark - UITableViewDataSource
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"ID"];
cell.textLabel.text = [NSString stringWithFormat:#"Row: %#", #(indexPath.row)];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
#end
Edit:
I have found that a much simpler way to avoid the gap between the last section and the table footer is to implement heightForFooterInSection and return a very small value that is not 0. This will result in nothing being visible.
For some reason, returning 0 doesn't suppress the rendering of section footers in a grouped-style table view, and it will try to render a 1-point footer. There is other discussion on StackOverflow about this.
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return CGFLOAT_MIN;
}
I was able to accomplish this in what feels like a slightly hacky way, but it seems to work fine.
My hack is simply to place the actual footer view you want inside of a wrapper view, with a frame position of (0, -1).
Let's say you have a table footer view that you want to use, a class called MyTableFooterView.
In that case you can do something like this:
//This is the view we will actually add as the table footer
//We make it one point shorter since the content will be shifted up
//one point out of its frame
CGRect footerFrame = CGRectMake(0, 0, self.tableView.width, myFooterHeight-1);
UIView* tableFooterWrapper = [[UIView alloc] initWithFrame:footerFrame];
//This is the view that we are trying to use as a table footer.
//We place it 1 point up inside the wrapper so it overlaps that pesky 1-point separator.
CGRect contentFrame = CGRectMake(0, -1, self.tableView.width, myFooterHeight);
UIView* footerContent = [[MyTableFooterView alloc] initWithFrame:contentFrame];
//Make sure the footer expands width for to other screen sizes
footerContent.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[tableFooterWrapper addSubview:footerContent];
self.tableView.tableFooterView = tableFooterWrapper;
This works reliably for me. It's possible that there's a more idiomatic way, but I haven't come across one yet.
Use following code
tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
Related
I have a tableview with a header view on it and paging enabled:
[super viewDidLoad];
CGRect headerFrame = [UIScreen mainScreen].bounds;
UIView *header = [[UIView alloc] initWithFrame:headerFrame];
header.backgroundColor = [UIColor flatWhiteColor];
self.tableView.tableHeaderView = header;
self.tableView.pagingEnabled = YES;
The Cells are the height of the screen:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [UIScreen mainScreen].bounds.size.height;
}
however, when I run it on my iPhone 6, the first table cell is never highlighted properly:
when its not highlighted
when I select the cell
help anyone?
The problem is because the height of headerView it's not actually equal with the size of the tableView and on the next page(the first table cell) you are seeing a part from the headerView.
Try this code:
CGRect headerFrame = CGRectMake(0, 0, self.tableView.frame.size.width, self.tableView.frame.size.height);
and
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return self.tableView.frame.size.height;
}
I found out the answer. It turns out a UIView inside my header was a bit too long and overlapped into my table cell. Thanks for your answers!
We have a UITableView and it was working fine for iOS7 but when I tried in the iOS8 simulator, I saw the cell separator was placed incorrectly for most cells. Strangely, some cells display the separator correctly.
See the attached image:
I set the cell height this way:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70.0f;
}
Do you know what's happening? Thanks!
EDIT:
A workaround I'm using in the meantime is to disable the separator...
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
...and paint it myself in the cell view...
UIView* separator = [[UIView alloc] initWithFrame:CGRectMake(20, cellHeight-1, frame.size.width - 40, 1)];
separator.layer.borderWidth = 1;
separator.layer.borderColor = [[UIColor grayColor] CGColor];
[self addSubview:separator];
...but I'd like not to do it.
I had the same problem and here is how I solved it:
If you are using a custom cell for your table view and you have overridden layoutSubviews, you need to call it's superview's method at the beginning of the method:
- (void)layoutSubviews
{
[super layoutSubviews];
// Your implementation
}
I got a table view with two sections, no crazy code, just my delegate methods.
It works pretty fine, like i want it to work. It should just look like on this screenshot:
Now the problem is: Sometimes while scrolling or flicking the scoll view to the bounds, this happens (if you can't see it: There is 1 or 1/2 pixel in gray on the top of the second section header, what is not intended to be so):
So, is this a iOS 7.1 or 7.x bug? I'm not using a custom view for the header. Does anyone know how to fix this?
Feedback really is appreciated.
I had this same problem that I battled for a few weeks, and the way I solved it was to set the tableView's separatorStyle to UITableViewCellSeparatorStyleNone, and add a custom subview that is a line to the cell's contentView.
Then in your cellForRowAtIndexPath method, hide the line subview of the last cell in the section:
- (UIView *)lineView
{
// Your frame will vary.
UIView *colorLineView = [[UIView alloc]initWithFrame:CGRectMake(82, 67.5, 238, 0.5)];
colorLineView.backgroundColor = [UIColor blackColor];
return colorLineView;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
static NSString *identifier = #"cellIdentifier";
UIView *lineView = [self lineView];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
[cell.contentView addSubview:lineView];
}
if (indexPath.section == 0)
{
if (indexPath.row == keys.count -1)
{
lineView.hidden = YES;
}
}
return cell;
}
It may be recycling one of the cell views with the separator from the scroll. This is a long shot, but what if you were to try tweaking the footer view for the section by returning an empty view?
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return [[UIView alloc] init];
}
It's also a good trick for removing empty cells from the table when you have only a couple rows.
I tried it with multiple different things and the cleanest approach i found is this.
I created a custom view for the header, but wanted it to look the same as the original not modified header:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 34)];
[headerView setBackgroundColor:[UIColor groupTableViewBackgroundColor]];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, tableView.frame.size.width, 34)];
[label setFont:[UIFont boldSystemFontOfSize:14]];
if (section == 0) {
NSMutableArray *difficultyArray = [dictionary objectForKey:#"Difficulty"];
NSString *difficulty = [difficultyArray objectAtIndex:0];
[label setText:[NSString stringWithFormat:#"Time Challenge (%#)", difficulty]];
} else {
[label setText:#"Freeplay (5x5 board)"];
}
[headerView addSubview:label];
return headerView;
}
Now we got the sections as they would appear without custom header views, but the bug still exists. I made it simple and clean:
UIView *lineFix = [[UIView alloc] initWithFrame:CGRectMake(0, 77.5, self.tableView.frame.size.width, 0.5)];
lineFix.backgroundColor = [UIColor groupTableViewBackgroundColor];
[self.tableView addSubview:lineFix];
Now we set a view over the buggy seperator with a height of 0.5 pixel, the seperator isn't visible anymore. Between the two section headers now is a 0.5 height view what shouldn't be there, but since i set it the same color as the section background color it isn't noticeable. The view moves, because it is a subview of the tableview, the same direction like the tableview.
If you have questions, just add a comment.
I want to make a Table View Controller that hold a table view and an image view in table view header view. When I scroll down the table view I want to zoom in the image (like in CNN app for iOS). I tried a lot of things but none of them to this as I want. Maybe someone can help me. Thanks!
All screen will look like this image like in this image:
(source: mzstatic.com)
I tried to do this by making the image at the top the header view of the table, but couldn't get that to work.
The way that did work, was to add a scroll view to the top of a UIViewController's view with a image view inside it. I then added a table view, and made it the same size as the controller's view so that it is over top the small scroll view that holds the image (this was done in a storyboard with auto layout turned off). In code, I add a table header view that's transparent and has a label that acts as the caption for the picture. It has the same height as the small scroll view. When you scroll the content of the table view up, I also scroll the small scroll view but at half the rate. If you pull the content down, I change the frame of the small scroll view so that it expands and stays centered. Here's the code:
#interface ViewController ()
#property (strong,nonatomic) NSArray *theData;
#property (weak,nonatomic) IBOutlet UITableView *tableView;
#property (weak,nonatomic) IBOutlet UIScrollView *imageScrollView;
#property (nonatomic) CGRect svFrame;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.imageScrollView.delegate = self;
self.imageScrollView.contentSize = CGSizeMake(500, 500);
self.svFrame = self.imageScrollView.frame;
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine"];
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 135)];
headerView.backgroundColor = [UIColor clearColor];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, headerView.frame.size.width, 24)];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.text = #"This is a Picture Caption";
[headerView addSubview:label];
self.tableView.tableHeaderView = headerView;
[self.tableView reloadData];
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
UIView *bgView = [[UIView alloc] init];
bgView.backgroundColor = [UIColor whiteColor];
cell.backgroundView = bgView;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.theData[indexPath.row];
return cell;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (! [scrollView isEqual:self.imageScrollView]) {
if (scrollView.contentOffset.y > 0) {
self.imageScrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y/2);
}else{
self.imageScrollView.frame = CGRectMake(scrollView.contentOffset.y, scrollView.contentOffset.y, self.svFrame.size.width - (scrollView.contentOffset.y * 2), self.svFrame.size.height - (scrollView.contentOffset.y * 2));
}
}
}
My cells all have varying heights, determined by text entered by the user.
Whatever height the last cell takes on seems to determine (change) the height for all remaining blank cells.
It doesn't appear that heightForRowAtIndexPath is getting called for these remaining, empty cells, nor is CFRAIP.
Does anyone know how to fix this or why it is happening?
Put this code in viewDidLoad of the the viewController where Tableview is placed.
self.tableView.tableFooterView = [[UIView alloc] init];
I meet the problem too. And it frustrated me much. After some consideration, I think it may be a feature of tableview that it show blank cell. It's reasonable to use the last cell height for the blank cell. Otherwise, what height to choose to use?
I think it's not acceptable to show black cell. If you dislike the style like me, you can try this to get rid of blank cells:
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
or
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
//then add view for separator line by yourself
or
UITableView *tableView = [[UITableView alloc] initWithFrame:self.tableView.frame style:UITableViewStyleGrouped];
tableView.backgroundColor = self.tableView.backgroundColor;
self.tableView = tableView;
If you must show blank cell and control the height, maybe it's the simplest way/workaround to add additional cell. For example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataArray == nil || self.dataArray.count == 0 ? 1 : self.dataArray + 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.count == self.dataArray.count){ //the last cell
cell = [[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
} else {
cell = .... //as uausal
}
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.count == self.dataArray.count){
return 50;
} else {
return xxx; //as usual
}
}
Now we can control any height !.
Hope it can help you.
You can refer to the link as well: How can I modify the appearance of 'empty' cells in plain UITableView?