IOS - Styling Section Headers in a static UITableViewController - IOS7 - ios

Is it possible to style a section header background / font style in a static UITableViewController? I cant see any storyboard option to do this and as the table is static the table methods have been disabled in the.M file - so I'm not sure how to apply styling programatically either?

The UITableViewDelegate protocol defines a method viewForHeaderInSection which can be implemented in your delegate to return custom header views (works for static UITableViews as well). e.g:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
// you can get the title you statically defined in the storyboard
NSString *sectionTitle = [self tableView:tableView titleForHeaderInSection:section];
// create and return a custom view
UILabel *customLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 200.0f, 50.0f)];
customLabel.text = sectionTitle;
return customLabel;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
// return a custom height here if necessary
return 50.0f;
}

Related

UITableView section footer not hiding

I have created a UITableView using the Interface Builder I have a section footer space there, I have designed my custom view as the section footer. But I want the section footer to be hidden initially and only load it after a service call.
I have tried
self.tableview.tablefooterview.hidden = YES
self.tableview.sectionFooterHeight = 0.0f
I have also set the height in delegate methods, but the table footer view is not hiding at all. How do I hide the table footer view.
check this Link for how to Hide footer view in UITableView
- (UIView*)tableView:(UITableView*)tableView viewForFooterInSection:(NSInteger)section
{
return [[UIView alloc] initWithFrame:CGRectZero];
}
Use UITableView delegate method :-
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0;
}
Please try to set section footer value to more than 0(zero). I tried to set it as 0.000001 and it works.
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0.000001;
}
Please try this code
- (void)viewDidLoad
{
self.tableview.sectionHeaderHeight = 0.0;
self.tableview.sectionFooterHeight = 0.0;
self.tableview.tableHeaderView=[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.tableview.bounds.size.width, 0.01f)];
self.tableview.tableFooterView=[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.tableview.bounds.size.width, 0.01f)];
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0;
}

How to customize UIView of sections in UITableView?

I want to set the style my sections in a UITableView like viewForFooterInSection or viewForHeaderInSection.
I only can set the title using titleForHeaderInSection and height using heightForHeaderInSection but I want to set the baground color, font-size, font-color, etc...
It's posible do that?
you can do it with this delegate method whic provide by apple.
//for header
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *myview = [[UIView alloc] init];
//give size for veiw, background color, add label anything here
return myview;
}
//for footer
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UIView *myview = [[UIView alloc] init];
//give size for veiw, background color, add label anything here
return myview;
}

UITableView Background Image for Static Section/Cells

I know we can add background images/colors to section headers in dynamic table view/cells but can anyone help me do the same in a table view using Static Cells ?
What I want to do is use a background image for my 3rd section in a TableView which is using static cells (total of 4 sections it has)
I want to add a background image and change text color to say some RGB value for the 3rd section
You can use the delegate methods of UITableView to set the height and view for a section header. This should do what you want:
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return (section == 2)? 100:30;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 100)];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 100)];
label.text = #"Description";
label.textColor = [UIColor whiteColor];
[imageView addSubview:label];
imageView.image = [UIImage imageNamed:#"House.tiff"];
return (section == 2)? imageView:nil;
}
UITableViewCells have the backgroundView property which is a UIView. You can change that to be a UIImageView, for example, or build a more complex background for you table view cells. It shouldn't matter, whether the cell is static or dynamic.
The text color for the cell can then simply be changed by setting the UITableViewCells cell.textLabel.textColor.
Same applies for the UITableViewHeaderFooterView, which are (as the name says) used for the header and footer of your table view sections. In code, you can access the header for a section using
- (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section
This saves you from completely recreating the header from scratch, just to make small adjustments. Alternatively, override
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
and build a custom UIView that will become your header.
You should assign a tag(say 15) to the static cell in
tableview:didSelectRowForIndexPath
and then
- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(cell.tag==15)
cell.backgroundColor = [UIColor colorWithRed:255/255.0 green:250/255.0 blue:243/255.0 alpha:1.0];
}

Delete the extra separator of UITableView in iOS 7

For my UITableView I have such code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 4;
}
But when I launch me app, it shows an extra separator. It's not additional cell - it cannot be selected. How can it be fixed?
Eliminate extra separators below UITableView
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
return [UIView new];
// If you are not using ARC:
// return [[UIView new] autorelease];
}
With iOS7
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
}
It is by default in UITableView. You can use templates to create the kind of view you need, in an empty view controller (or) change the frame size of your UITableView in code by creating and allocating your own view.
You can also try to set footer view height to zero, by using next code in UITableViewDelegate class:
- (CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0;
}

How to use UITableViewHeaderFooterView?

Hi I want to use UITableHeaderFooterView in my app and i am doing this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[_tableView registerClass:[M3CTableViewCell class] forCellReuseIdentifier:#"cell"];
[_tableView registerClass:[M3CHeaderFooter class] forHeaderFooterViewReuseIdentifier:#"footer"];
}
- (UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section {
M3CHeaderFooter * footer = [[M3CHeaderFooter alloc]initWithReuseIdentifier:#"footer"];
footer.textLabel.text = #"Test";
return footer;
}
By doing this I am not getting anything at Footer's place.
And this method is not even getting called but I think this method is part of UITableViewDelegate protocol.
Using the new iOS 6 feature of reusable header/footer views involves two steps. You seem to be doing only the first step.
First step: you're telling the table view what class to use for the section header view, by registering your custom subclass of UITableViewHeaderFooterView (I assume your M3CHeaderFooter is a subclass of UITableViewHeaderFooterView).
Second step: Tell the table view what view to use (AND reuse) for a header section by implementing the tableView delegate method
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
So in your viewDidLoad you'd implement something like this:
// ****** Do Step One ******
[_tableView registerClass:[M3CHeaderFooter class] forHeaderFooterViewReuseIdentifier:#"TableViewSectionHeaderViewIdentifier"];
Then you'd implement the table View delegate method in the class where you're creating and displaying your table view:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 40.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *headerReuseIdentifier = #"TableViewSectionHeaderViewIdentifier";
// ****** Do Step Two *********
M3CHeaderFooter *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerReuseIdentifier];
// Display specific header title
sectionHeaderView.textLabel.text = #"specific title";
return sectionHeaderView;
}
Now mind you that you do not need to subclass UITableViewHeaderFooterView in order to use it.
Before iOS 6, if you wanted to have a header view for a section, you'd implement the above tableView delegate method and tell the table view what view to use for each section. So each section had a different instance of a UIView which you provided. This means that if your tableView had 100 sections, and inside the delegate method you created a new instance of a UIView, then you would have given the tableView 100 UIViews for the 100 section headers that were displayed.
Using the new feature of reusable header/footer views, you create an instance of a UITableViewHeaderFooterView and the system reuses it for each displayed section header.
If you wanted to have a reusable UITableViewHeaderFooterView without subclassing then you simply change your viewDidLoad to this:
// Register the class for a header view reuse.
[_buttomTableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:#"TableViewSectionHeaderViewIdentifier"];
and then your delegate method to this:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 40.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *headerReuseIdentifier = #"TableViewSectionHeaderViewIdentifier";
// Reuse the instance that was created in viewDidLoad, or make a new one if not enough.
UITableViewHeaderFooterView *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerReuseIdentifier];
sectionHeaderView.textLabel.text = #"Non subclassed header";
return sectionHeaderView;
}
I hope that was clear enough.
EDIT: When subclassing the header view, you can implement code similar to the following if you wish to add a custom view to the headerView:
// Add any optional custom views of your own
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 30.0)];
[customView setBackgroundColor:[UIColor blueColor]];
[sectionHeaderView.contentView addSubview:customView];
Doing this in the subclass, as opposed to viewForHeaderInSection: delegate method (as noted below by Matthias), will ensure that only one instance of any subviews are created. You can then add any properties within the subclass that will allow you to access your custom subview.
UITableViewHeaderFooterView is one of the few places I would programmatically handle the view rather than use Storyboard or a XIB. Since you cannot officially use appearance proxy and there is no IB way to do it without abusing UITableViewCells. I do it the old-fashioned way and just use the tag on the label to fetch the custom elements.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kSectionHeaderReuseIdentifier];
if (headerView == nil) {
[tableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:kSectionHeaderReuseIdentifier];
headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kSectionHeaderReuseIdentifier];
}
UILabel *titleLabel = (UILabel *)[headerView.contentView viewWithTag:1];
if (titleLabel == nil) {
UIColor *backgroundColor = [UIColor blackColor];
headerView.contentView.backgroundColor = backgroundColor;
titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 0.0f, 300.0f, 44.0f)];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.backgroundColor = backgroundColor;
titleLabel.shadowOffset = CGSizeMake(0.0f, 0.0f);
titleLabel.tag = 1;
titleLabel.font = [UIFont systemFontOfSize:24.0f];
[headerView.contentView addSubview:titleLabel];
}
NSString *sectionTitle = [self.sections objectAtIndex:section];
if (sectionTitle == nil) {
sectionTitle = #"Missing Title";
}
titleLabel.text = sectionTitle;
return headerView;
}
This is an old post and has good answers, but I wanted to share another work-around for a very similar issue I experienced.
At first, I used:
-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
With a custom prototype cell for my header view. Subclassing UITableViewCell as such
static NSString *cellIdentifier = #"CustomHeaderCell";
CustomHeaderCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
However, when animating TableView cells above section headers (making them twice as tall) the header view would disappear. This, as pointed out, is because the implementation only supplied a view, not a re-usable view.
Instead of forgoing everything with the customized prototype cell, I implemented the UITableViewHeaderFooterWithIdentifier and set it as the prototyped cell's contentView, without subclassing UITableViewHeaderFooterWithIdentifier.
static NSString *customHeaderViewIdentifier = #"CustomHeaderView";
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:customHeaderViewIdentifier];
headerView = (UITableViewHeaderFooterView *)cell.contentView;
I realize this creates two instances of the header view (at least I think it would..) however it does allow you to keep the benefits of a customized prototype cell without doing everything programatically.
Full code:
// viewDidLoad
[myTableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:#"CustomHeaderView"];
// Implement your custom header
-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *cellIdentifier = #"CustomHeaderCell";
CustomHeaderCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
static NSString *customHeaderViewIdentifier = #"CustomHeaderView";
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:customHeaderViewIdentifier];
// do your cell-specific code here
// eg. cell.myCustomLabel.text = #"my custom text"
headerView = (UITableViewHeaderFooterView *)cell.contentView;
return headerView;
}
There are a few ways of approaching this, but here is one a solution in Swift: the idea here is that we have a subclass of UITableViewHeaderFooterView called SNStockPickerTableHeaderView; it exposes a method called, configureTextLabel() that when called, sets the font and the color of the text label. We call this method only after the title has been set, that is from, willDisplayHeaderView, and the font gets correctly set.
The header view also supports a custom line separator to set it apart from the rest of the cells.
// MARK: UITableViewDelegate
func tableView(tableView:UITableView, willDisplayHeaderView view:UIView, forSection section:Int) {
if let headerView:SNStockPickerTableHeaderView = view as? SNStockPickerTableHeaderView {
headerView.configureTextLabel()
}
}
func tableView(tableView:UITableView, viewForHeaderInSection section:Int) -> UIView? {
var headerView:SNStockPickerTableHeaderView? = tableView.dequeueReusableHeaderFooterViewWithIdentifier(kSNStockPickerTableHeaderViewReuseIdentifier) as? SNStockPickerTableHeaderView
if (headerView == nil) {
// Here we get to customize the section, pass in background color, text
// color, line separator color, etc.
headerView = SNStockPickerTableHeaderView(backgroundColor:backgroundColor,
textColor:primaryTextColor,
lineSeparatorColor:primaryTextColor)
}
return headerView!
}
And here is the custom UITableViewHeaderFooterView:
import Foundation
import UIKit
private let kSNStockPickerTableHeaderViewLineSeparatorHeight:CGFloat = 0.5
private let kSNStockPickerTableHeaderViewTitleFont = UIFont(name:"HelveticaNeue-Light", size:12)
let kSNStockPickerTableHeaderViewReuseIdentifier:String = "stock_picker_table_view_header_reuse_identifier"
class SNStockPickerTableHeaderView: UITableViewHeaderFooterView {
private var lineSeparatorView:UIView?
private var textColor:UIColor?
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// We must implement this, since the designated init of the parent class
// calls this by default!
override init(frame:CGRect) {
super.init(frame:frame)
}
init(backgroundColor:UIColor, textColor:UIColor, lineSeparatorColor:UIColor) {
super.init(reuseIdentifier:kSNStockPickerTableHeaderViewReuseIdentifier)
contentView.backgroundColor = backgroundColor
self.textColor = textColor
addLineSeparator(textColor)
}
// MARK: Layout
override func layoutSubviews() {
super.layoutSubviews()
let lineSeparatorViewY = CGRectGetHeight(self.bounds) - kSNStockPickerTableHeaderViewLineSeparatorHeight
lineSeparatorView!.frame = CGRectMake(0,
lineSeparatorViewY,
CGRectGetWidth(self.bounds),
kSNStockPickerTableHeaderViewLineSeparatorHeight)
}
// MARK: Public API
func configureTextLabel() {
textLabel.textColor = textColor
textLabel.font = kSNStockPickerTableHeaderViewTitleFont
}
// MARK: Private
func addLineSeparator(lineSeparatorColor:UIColor) {
lineSeparatorView = UIView(frame:CGRectZero)
lineSeparatorView!.backgroundColor = lineSeparatorColor
contentView.addSubview(lineSeparatorView!)
}
}
Here is the result, see section header for, "Popular Stocks":
I can't comment under Cameron Lowell Palmer post but to answer Christopher King, there is a simple way to ensure the re-use without sub-classing UITableViewHeaderFooterView and yet still using custom subviews.
First, do NOT register the class for a header view reuse.
Then in tableView:viewForHeaderInSection: you simply have to create UITableViewHeaderFooterView when needed:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *kYourTableViewReusableHeaderIdentifier = #"ID";
UILabel *titleLabel = nil;
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kYourTableViewReusableHeaderIdentifier];
if (headerView == nil) {
headerView = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:kYourTableViewReusableHeaderIdentifier];
titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(...)];
titleLabel.tag = 1;
// ... setup titleLabel
[headerView.contentView addSubview:titleLabel];
} else {
// headerView is REUSED
titleLabel = (UILabel *)[headerView.contentView viewWithTag:1];
}
NSString *sectionTitle = (...); // Fetch value for current section
if (sectionTitle == nil) {
sectionTitle = #"Missing Title";
}
titleLabel.text = sectionTitle;
return headerView;
}
Here is a "quick-and-dirty" way to get this going. It will make a small blue label in the header. I've confirmed that this renders OK in iOS 6 and iOS 7.
in your UITableViewDelegate:
-(void)viewDidLoad
{
...
[self.table registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:#"Header"];
...
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 34.;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UITableViewHeaderFooterView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:#"Header"];
UILabel *leftlabel = [[UILabel alloc] initWithFrame:CGRectMake(0., 0., 400., 34.)];
[leftlabel setBackgroundColor:[UIColor blueColor]];
[header.contentView addSubview:leftlabel];
return header;
}
In case it gets lost in the thorough answers above, the thing that people are likely missing (compared to the standard cellForRowAtIndexPath: method) is that you must register the class used for the section header.
[tableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:#"SectionHeader"];
Try adding registerClass:forHeaderFooterViewReuseIdentifier: and see if it starts working.
One of the reasons that method may not be being called is the style of the table. Standard vs Grouped handles headers/footers differently. That may explain why it's not getting called.
Set delegate property of UITableView instance to reference to the controller that implements next methods:
Method that returns view of section footer:
Asks the delegate for a view object to display in the footer of the specified section of the table view.
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
Height of view in section footer:
Asks the delegate for the height to use for the footer of a particular section.
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section

Resources