UICollectionView header view create programmatically and add? - iphone

I have created UICollectionView in storyboard and added header footer view its working fine.But My question is how to create UICollectionViewReusable view to add as SupplementaryView programatically.I tried but delegates not called.Please note that i have set delegate also.below code i have tried
- (void)setUpCustomCollectionView
{
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 40, 320, 500) collectionViewLayout:layout];
[self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"brandingHeaderView"];
self.collectionView.bounces = NO;
self.collectionView.tag = 10;
self.collectionView.backgroundColor = [UIColor darkGrayColor];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
self.collectionView.dataSource=self;
self.collectionView.delegate=self;
[self.baseScrollView addSubview:self.collectionView];
}
And in delegate
-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath
{
if (kind == UICollectionElementKindSectionHeader) {
UICollectionReusableView *headerView = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"brandingHeaderView" forIndexPath:indexPath];
UIView * view =[[UIView alloc]initWithFrame:CGRectMake(0, 0, 0, 80)];
view.backgroundColor = [UIColor redColor];
[headerView addSubview:view];
return headerView;
}
}
guide me.

I have just been having a similar issue where the following delegate wasn't being called...
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
Then I remembered that when I was defining an instance of the UICollectionViewFlowLayout, I had assigned the itemSize value as per following code...
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(106.f, 106.f);
Try also adding the following line to it as well for the header...
layout.headerReferenceSize = CGSizeMake(320.f, 30.f);

I guess mistake here:
[UICollectionViewFlowLayout class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
UICollectionViewFlowLayout can`t be header view
Edit:
To make it work you need subclass of UICollectionReusableView, don't forget override reuseIdentifier property. Also check docs:
UICollectionReusableView Class Reference

override init(collectionViewLayout layout: UICollectionViewLayout) {
super.init(collectionViewLayout: layout)
let nib = UINib(nibName: "Empty", bundle: nil)
collectionView!.registerNib(nib, forCellWithReuseIdentifier: "cell")
/* register the header nib's */
let headerNib = UINib(nibName: "Header", bundle: nil)
collectionView?.registerNib(headerNib, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header")
/* register footers nib */
let footerNib = UINib(nibName: "Footer", bundle: nil)
collectionView?.registerNib(footerNib, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "footer")
collectionView!.backgroundColor = UIColor.whiteColor()
}
convenience required init(coder aDecoder: NSCoder){
let flowLayout = UICollectionViewFlowLayout()
flowLayout.minimumLineSpacing = 20
flowLayout.minimumInteritemSpacing = 10
flowLayout.itemSize = CGSize(width: 80, height: 120);
flowLayout.scrollDirection = .Vertical
flowLayout.sectionInset =
UIEdgeInsets(top: 10, left: 20, bottom: 10, right: 20)
// set the header and footer views size properties
flowLayout.headerReferenceSize = CGSize(width: 300, height: 50)
flowLayout.footerReferenceSize = CGSize(width: 300, height: 50)
self.init(collectionViewLayout: flowLayout)
}
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> HeaderCollectionReusableView{
let view = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "header", forIndexPath: indexPath) as! HeaderCollectionReusableView
view.headerLabel.text = "header section title"
return view
}

to add it, a custom nib file should be created called Header(Header.xib) and UILabel is dragged from the object library and added to the Header.xib. A custom file a subclass of UICollectionReusableView is created next. e.g. HeaderCollectionReusableView.swift and the header.xib is made to see it and an IBOutlet of the label is done inside this custom class.

In order to add header view programmatically to UICollectionView, you need to do following things.
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout alloc] init];
layout.headerReferenceSize = CGSizeMake(100.0f, 40.0f);
UICollectionView* _collectionView=[[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
[_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:UICollectionElementKindSectionHeader];
-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath
if ([kind isEqualToString:UICollectionElementKindSectionHeader]){
UICollectionReusableView *reusableView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:UICollectionElementKindSectionHeader forIndexPath:indexPath];
if (reusableView==nil) {
reusableView= [[UICollectionReusableView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
label.text= #"Top stories";
label.textColor = [UIColor blueColor];
[reusableView addSubview:label];
}
return reusableView;
}
return nil;
}

Related

iOS - UICollectionView spacing still there when set to 0 - How to set with no spacing between cells

I have a simple UICollectionView which I have set with 0 spacing in InterfaceBuilder but when I populate the collection view with cells there is still some spacing. Is there something special and not immediately obvious that I need to do in order to actually see a collectionview cell with 0 spacing beyond setting it to have 0 spacing? Thanks.
EDIT* some code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor clearColor];
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(2, 2, cell.frame.size.width -4, cell.frame.size.height -4)];
lbl.backgroundColor = [UIColor clearColor];
lbl.font = [UIFont boldSystemFontOfSize:20];
lbl.text = [NSString stringWithFormat:#"$%0.0f", [[amountsArray objectAtIndex:indexPath.row] floatValue]];
lbl.textAlignment = NSTextAlignmentCenter;
lbl.layer.borderWidth = 1;
[cell addSubview:lbl];
[lbl release];
return cell;
}
Simple solution for your Query. Add this in your viewController's .m file:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
ProductDetailViewController *HomeVC = [self.storyboard instantiateViewControllerWithIdentifier:#"ProductDetailView"];
HomeVC.title = #"DemoProject";
[self.navigationController pushViewController:HomeVC animated:YES];
}
- (UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 0, 0, 0); // top, left, bottom, right
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 0.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 0.0;
}
Swift 3 version of #MihirOza 's solution
Worked for both Horizontal and Vertical collection views
Code
// removing spacing
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
You have to create custom UICollectionViewLayout.
Space between the cells will be equal to cellSpacing.
final class CustomFlowLayout: UICollectionViewFlowLayout {
let cellSpacing: CGFloat = 0
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
if let attributes = super.layoutAttributesForElements(in: rect) {
for (index, attribute) in attributes.enumerated() {
if index == 0 { continue }
let prevLayoutAttributes = attributes[index - 1]
let origin = prevLayoutAttributes.frame.maxX
if (origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize.width) {
attribute.frame.origin.x = origin + cellSpacing
}
}
return attributes
}
return nil
}
}
I solved this issue and got the layout I desired with the following:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor clearColor];
//clear any contents on the cell
for (UIView *subView in [cell subviews]) {
[subView removeFromSuperview];
}
//Label to put on the cell
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(2, 2, cell.frame.size.width -4, cell.frame.size.height -4)];
lbl.backgroundColor = [UIColor clearColor];
lbl.textColor = [UIColor colorWithRed:[CPExtras RGBtoPercent:70] green:[CPExtras RGBtoPercent:92] blue:[CPExtras RGBtoPercent:105] alpha:1];
lbl.font = [UIFont boldSystemFontOfSize:20];
lbl.text = #"100";
lbl.textAlignment = NSTextAlignmentCenter;
//Give the cell a border
cell.layer.borderColor = [[UIColor colorWithRed:[CPExtras RGBtoPercent:70] green:[CPExtras RGBtoPercent:92] blue:[CPExtras RGBtoPercent:105] alpha:0.5] CGColor];
cell.layer.borderWidth = 0.5;
[cell addSubview:lbl];
[lbl release];
return cell;
}
In IB I had these measurement settings for the collectionview:
In order to actually have zero space, the number of cells and their width should be divisible by the collection view's own width, for example
if you have 5 cells at a time with a width of 100px, then your collection view should have 500px in width, if it's larger then it will force a space between cells.
The documentation for [UICollectionViewFlowLayout minimumInteritemSpacing] mentions:
This spacing is used to compute how many items can fit in a single line, but after the number of items is determined, the actual spacing may possibly be adjusted upward.
You may need to implement a custom layout to do this. The documentation can be found here, and an example here.

Monotouch.Dialog StyledStringElement full image [duplicate]

I have created a custom UITableViewCell. The table view is showing data fine. What I am stuck in is when user touches cell of tableview, then I want to show the background color of the cell other than the default [blue color] values for highlighting the selection of cell.
I use this code but nothing happens:
cell.selectedBackgroundView.backgroundColor=[UIColor blackColor];
No need for custom cells. If you only want to change the selected color of the cell, you can do this:
Objective-C:
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor redColor];
[cell setSelectedBackgroundView:bgColorView];
Swift:
let bgColorView = UIView()
bgColorView.backgroundColor = UIColor.red
cell.selectedBackgroundView = bgColorView
I think you were on the right track, but according to the class definition for selectedBackgroundView:
The default is nil for cells in plain-style tables (UITableViewStylePlain) and non-nil for section-group tables UITableViewStyleGrouped).
Therefore, if you're using a plain-style table, then you'll need to alloc-init a new UIView having your desired background colour and then assign it to selectedBackgroundView.
Alternatively, if all you wanted was a gray background when the cell is selected, you could use this:
cell.selectionStyle = UITableViewCellSelectionStyleGray;
Table View Cell selection background color can be set via the Storyboard in Interface Builder:
If you have a grouped table with just one cell per section, just add this extra line to the code:
bgColorView.layer.cornerRadius = 10;
UIView *bgColorView = [[UIView alloc] init];
[bgColorView setBackgroundColor:[UIColor redColor]];
bgColorView.layer.cornerRadius = 10;
[cell setSelectedBackgroundView:bgColorView];
[bgColorView release];
Don't forget to import QuartzCore.
Swift 3: for me it worked when you put it in the cellForRowAtIndexPath: method
let view = UIView()
view.backgroundColor = UIColor.red
cell.selectedBackgroundView = view
The following works for me in iOS 8.
I have to set the selection style to UITableViewCellSelectionStyleDefault for custom background color to work. If any other style, the custom background color will be ignored. There seems to be a change in behaviours as previous answers needs to set style to none instead.
The full code for the cell as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// This is how you change the background color
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor redColor];
[cell setSelectedBackgroundView:bgColorView];
return cell;
}
Create a custom cell for your table cell and in the custom cell class.m put the code below, it will work fine. You need to place the desired color image in selectionBackground UIImage.
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
UIImage *selectionBackground = [UIImage imageNamed:#"yellow_bar.png"];
UIImageView *iview=[[UIImageView alloc] initWithImage:selectionBackground];
self.selectedBackgroundView=iview;
}
Swift 3.0 extension
extension UITableViewCell {
var selectionColor: UIColor {
set {
let view = UIView()
view.backgroundColor = newValue
self.selectedBackgroundView = view
}
get {
return self.selectedBackgroundView?.backgroundColor ?? UIColor.clear
}
}
}
cell.selectionColor = UIColor.FormaCar.blue
In Swift 4, you can also set the background color of your table cell globally (taken from here):
let backgroundColorView = UIView()
backgroundColorView.backgroundColor = UIColor.red
UITableViewCell.appearance().selectedBackgroundView = backgroundColorView
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIView *view = [[UIView alloc] init];
[view setBackgroundColor:[UIColor redColor]];
[cell setSelectedBackgroundView:view];
}
We need to set the selected background view in this method.
Swift 4+:
Add following lines in your table cell
let bgColorView = UIView()
bgColorView.backgroundColor = .red
self.selectedBackgroundView = bgColorView
Finally it should be as below
override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
let bgColorView = UIView()
bgColorView.backgroundColor = .red
self.selectedBackgroundView = bgColorView
}
If you want to add a custom highlighted color to your cell (and your cell contains buttons,labels, images,etc..) I followed the next steps:
For example if you want a selected yellow color:
1) Create a view that fits all the cell with 20% opacity (with yellow color) called for example backgroundselectedView
2) In the cell controller write this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.backgroundselectedView.alpha=1;
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
self.backgroundselectedView.alpha=0;
[super touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
self.backgroundSelectedImage.alpha=0;
[super touchesCancelled:touches withEvent:event];
}
If you are using a custom TableViewCell, you can also override awakeFromNib:
override func awakeFromNib() {
super.awakeFromNib()
// Set background color
let view = UIView()
view.backgroundColor = UIColor.redColor()
selectedBackgroundView = view
}
I want to note that the XIB editor offers you the following standard options:
Section: blue/gray/none
(the right-hand column with options, 4th tab, first group "Table View Cell", 4th subgroup, the 1st of 3 items reads "Selection")
Probably what you want to do may be achieved by selecting the right standard option.
One more tip to Christian's way to show rounded corner background for grouped table.
If I use cornerRadius = 10 for cell, it shows four corner's rounded selection background. It's not the same with table view's default UI.
So, I think about easy way to resolve it with cornerRadius.
As you can see from the below codes, check about cell's location (top, bottom, middle or topbottom) and add one more sub layers to hide top corner or bottom corner. This just shows exactly same look with default table view's selection background.
I tested this code with iPad splitterview. You can change patchLayer's frame position as you needed.
Please let me know if there is more easier way to achieve same result.
if (tableView.style == UITableViewStyleGrouped)
{
if (indexPath.row == 0)
{
cellPosition = CellGroupPositionAtTop;
}
else
{
cellPosition = CellGroupPositionAtMiddle;
}
NSInteger numberOfRows = [tableView numberOfRowsInSection:indexPath.section];
if (indexPath.row == numberOfRows - 1)
{
if (cellPosition == CellGroupPositionAtTop)
{
cellPosition = CellGroupPositionAtTopAndBottom;
}
else
{
cellPosition = CellGroupPositionAtBottom;
}
}
if (cellPosition != CellGroupPositionAtMiddle)
{
bgColorView.layer.cornerRadius = 10;
CALayer *patchLayer;
if (cellPosition == CellGroupPositionAtTop)
{
patchLayer = [CALayer layer];
patchLayer.frame = CGRectMake(0, 10, 302, 35);
patchLayer.backgroundColor = YOUR_BACKGROUND_COLOR;
[bgColorView.layer addSublayer:patchLayer];
}
else if (cellPosition == CellGroupPositionAtBottom)
{
patchLayer = [CALayer layer];
patchLayer.frame = CGRectMake(0, 0, 302, 35);
patchLayer.backgroundColor = YOUR_BACKGROUND_COLOR;
[bgColorView.layer addSublayer:patchLayer];
}
}
}
As per custom color for a selected cell in UITableView, great solution as per Maciej Swic's answer
Just to add to that, you declare Swic's answer in the Cell configuration usually under:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
And for an added effect, instead of the system colors, you may use RGB values for a custom color look. In my code this is how I achieved it:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
}
static NSString *CellIdentifier = #"YourCustomCellName";
MakanTableCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (cell == nil) {
cell = [[[NSBundle mainBundle]loadNibNamed:#"YourCustomCellClassName" owner:self options:nil]objectAtIndex:0];
}
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor colorWithRed:255.0/256.0 green:239.0/256.0 blue:49.0/256.0 alpha:1];
bgColorView.layer.cornerRadius = 7;
bgColorView.layer.masksToBounds = YES;
[cell setSelectedBackgroundView:bgColorView];
return cell;
}
Let me know if that works for you as well. You can mess with the cornerRadius number for the effects on the corners of the selected cell.
To add the background for all cells (using Maciej's answer):
for (int section = 0; section < [self.tableView numberOfSections]; section++) {
for (int row = 0; row < [self.tableView numberOfRowsInSection:section]; row++) {
NSIndexPath* cellPath = [NSIndexPath indexPathForRow:row inSection:section];
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:cellPath];
//stuff to do with each cell
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor redColor];
[cell setSelectedBackgroundView:bgColorView];
}
}
I've got a slightly different approach than everyone else that reflects the selection on touch rather than after being selected. I have a subclassed UITableViewCell. All you have to do is set the background color in the touch events, which simulates selection on touch, and then set the background color in the setSelected function. Setting the background color in the selSelected function allows for deselecting the cell. Make sure to pass the touch event to the super, otherwise the cell won't actually act as if its selected.
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.backgroundColor = UIColor(white: 0.0, alpha: 0.1)
super.touchesBegan(touches, withEvent: event)
}
override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
self.backgroundColor = UIColor.clearColor()
super.touchesCancelled(touches, withEvent: event)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
self.backgroundColor = selected ? UIColor(white: 0.0, alpha: 0.1) : UIColor.clearColor()
}
To override UITableViewCell's setSelected also works.
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Set background color
let view = UIView()
view.backgroundColor = UIColor.redColor()
selectedBackgroundView = view
}
for those that just want to get rid of the default selected grey background put this line of code in your cellForRowAtIndexPath func:
yourCell.selectionStyle = .None
for Swift 3.0:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
cell.contentView.backgroundColor = UIColor.red
}
I use below approach and works fine for me,
class MyTableViewCell : UITableViewCell {
var defaultStateColor:UIColor?
var hitStateColor:UIColor?
override func awakeFromNib(){
super.awakeFromNib()
self.selectionStyle = .None
}
// if you are overriding init you should set selectionStyle = .None
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let hitColor = hitStateColor {
self.contentView.backgroundColor = hitColor
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let defaultColor = defaultStateColor {
self.contentView.backgroundColor = defaultColor
}
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
if let defaultColor = defaultStateColor {
self.contentView.backgroundColor = defaultColor
}
}
}
1- Add a view to the content view of your cell.
2- Right click your cell.
3- Make the added view as "selectedBackgroundView".
Here is the important parts of the code needed for a grouped table. When any of the cells in a section are selected the first row changes color. Without initially setting the cellselectionstyle to none there is an annonying double reload when the user clicks row0 where the cell changes to bgColorView then fades and reloads bgColorView again. Good Luck and let me know if there is a simpler way to do this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([indexPath row] == 0)
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIView *bgColorView = [[UIView alloc] init];
bgColorView.layer.cornerRadius = 7;
bgColorView.layer.masksToBounds = YES;
[bgColorView setBackgroundColor:[UIColor colorWithRed:.85 green:0 blue:0 alpha:1]];
[cell setSelectedBackgroundView:bgColorView];
UIColor *backColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:1];
cell.backgroundColor = backColor;
UIColor *foreColor = [UIColor colorWithWhite:1 alpha:1];
cell.textLabel.textColor = foreColor;
cell.textLabel.text = #"row0";
}
else if ([indexPath row] == 1)
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIColor *backColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
cell.backgroundColor = backColor;
UIColor *foreColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
cell.textLabel.textColor = foreColor;
cell.textLabel.text = #"row1";
}
else if ([indexPath row] == 2)
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIColor *backColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
cell.backgroundColor = backColor;
UIColor *foreColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
cell.textLabel.textColor = foreColor;
cell.textLabel.text = #"row2";
}
return cell;
}
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:[indexPath section]];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:path];
[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
[tableView selectRowAtIndexPath:path animated:YES scrollPosition:UITableViewScrollPositionNone];
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tvStat cellForRowAtIndexPath:indexPath];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
#pragma mark Table view Gestures
-(IBAction)singleTapFrom:(UIGestureRecognizer *)tapRecog
{
CGPoint tapLoc = [tapRecog locationInView:tvStat];
NSIndexPath *tapPath = [tvStat indexPathForRowAtPoint:tapLoc];
NSIndexPath *seleRow = [tvStat indexPathForSelectedRow];
if([seleRow section] != [tapPath section])
[self tableView:tvStat didDeselectRowAtIndexPath:seleRow];
else if (seleRow == nil )
{}
else if([seleRow section] == [tapPath section] || [seleRow length] != 0)
return;
if(!tapPath)
[self.view endEditing:YES];
[self tableView:tvStat didSelectRowAtIndexPath:tapPath];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
Make sure you have used the above line to use the selection effect
override func setSelected(selected: Bool, animated: Bool) {
// Configure the view for the selected state
super.setSelected(selected, animated: animated)
let selView = UIView()
selView.backgroundColor = UIColor( red: 5/255, green: 159/255, blue:223/255, alpha: 1.0 )
self.selectedBackgroundView = selView
}
In case of custom cell class. Just override:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
if (selected) {
[self setBackgroundColor: CELL_SELECTED_BG_COLOR];
[self.contentView setBackgroundColor: CELL_SELECTED_BG_COLOR];
}else{
[self setBackgroundColor: [UIColor clearColor]];
[self.contentView setBackgroundColor: [UIColor clearColor]];
}
}
It's easy when the table view style is plain, but in group style, it's a little trouble, I solve it by:
CGFloat cellHeight = [self tableView:tableView heightForRowAtIndexPath:indexPath];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kGroupTableViewCellWidth+2, cellHeight)];
view.backgroundColor = kCommonHighlightedColor;
cell.selectedBackgroundView = view;
[view release];
UIRectCorner cornerFlag = 0;
CGSize radii = CGSizeMake(0, 0);
NSInteger theLastRow = --> (yourDataSourceArray.count - 1);
if (indexPath.row == 0) {
cornerFlag = UIRectCornerTopLeft | UIRectCornerTopRight;
radii = CGSizeMake(10, 10);
} else if (indexPath.row == theLastRow) {
cornerFlag = UIRectCornerBottomLeft | UIRectCornerBottomRight;
radii = CGSizeMake(10, 10);
}
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:cornerFlag cornerRadii:radii];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = maskPath.CGPath;
view.layer.mask = shapeLayer;
noted the kGroupTableViewCellWidth, I define it as 300, it's the width of group table view cell width in iPhone
I'm using iOS 9.3 and setting the color through the Storyboard or setting cell.selectionStyle didn't work for me, but the code below worked:
UIView *customColorView = [[UIView alloc] init];
customColorView.backgroundColor = [UIColor colorWithRed:55 / 255.0
green:141 / 255.0
blue:211 / 255.0
alpha:1.0];
cell.selectedBackgroundView = customColorView;
return cell;
I found this solution here.
Try Following code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[cellIdArray objectAtIndex:indexPath.row] forIndexPath:indexPath];
// Configure the cell...
cell.backgroundView =
[[UIImageView alloc] init] ;
cell.selectedBackgroundView =[[UIImageView alloc] init];
UIImage *rowBackground;
UIImage *selectionBackground;
rowBackground = [UIImage imageNamed:#"cellBackgroundDarkGrey.png"];
selectionBackground = [UIImage imageNamed:#"selectedMenu.png"];
((UIImageView *)cell.backgroundView).image = rowBackground;
((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;
return cell;
}
//Swift Version:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")! as UITableViewCell
cell.selectedBackgroundView = UIImageView()
cell.backgroundView=UIImageView()
let selectedBackground : UIImageView = cell.selectedBackgroundView as! UIImageView
selectedBackground.image = UIImage.init(named:"selected.png");
let backGround : UIImageView = cell.backgroundView as! UIImageView
backGround.image = UIImage.init(named:"defaultimage.png");
return cell
}

Specify width of the cell imageView

Is it possible to constraint the width of [[cell imageView] a standard UITableViewCell?
I've tried [[cell imageView] setFrame:CGRectMake(0, 0, 50, 50)] but it has no effect.
[EDIT]
Otherwise, is it possible to change a UIImage size before adding it in the UIImageView?
You can use .transform method in UIView example
cell.imageView.transform = CGAffineTransformMakeScale(0.65, 0.65);
//if you are subclassing UITableViewCell you can do this too
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.bounds = CGRectMake(10,5,65,65);
self.imageView.frame = CGRectMake(10,5,65,65);
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
if (self.imageView.image) {
//TODO: adjust the textLabel and detailTextLabel
}
}
If you can't simply set the image view's frame on a regular UITableViewCell, you could make a UITableViewCell subclass, and reposition the image view in -layoutSubviews.
This is the in-built functionality to provide imageView for every cell. Its frame cannot be changed unless it is sub-classed.
However, you can add any of your own imageViews by simply adding the following code in the method,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString* cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil)
{
cell = (UITableViewCell*) [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
UIImageView* *myView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[myView setImage:image];
myView.tag = 123;
[cell.contentView addSubview:myView];
[myView release];
}
else
{
myView = (UIImageView*) [cell.contentView viewWithTag:123];
}
}
Image Fix Size:
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[imgview setImage:image];
[cell addSubview:imgView];
[imgView release];
No it is not possible.
its width should not be changed, for that you have to create UITableViewCell subclass and you can change imageview in UITableViewCell and change width according to it.
or u can use
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIImageView *imgView;
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
imgView = [[UIImageView alloc] initWithFrame:(100,0,100,62)];
[imgView setImage:[UIImage imageNamed:#"img.png"]];
imgView.tag = 55;
[cell.contentView addSubview:imgView];
[imgView release];
}
else
{
imgView = (id)[cell.contentView viewWithTag:55];
}
here is my swift solution of this problem
//
// UITableVIewCellBasicWithFixedSizeImage.swift
//
// Created by Andrew Ashurow on 4/28/16.
// Copyright © 2016. All rights reserved.
//
class UITableVIewCellBasicWithFixedSizeImage: UITableViewCell {
private let
IMAGE_VIEW_WIDTH:CGFloat = 27,
TEXT_VIEW_LEFT_INSET:CGFloat = 15
override func layoutSubviews() {
super.layoutSubviews()
if let
imageView = imageView,
textLabel = textLabel{
//set fixed image width
imageView.frame = CGRect(
origin: imageView.frame.origin,
size: CGSize(
width: IMAGE_VIEW_WIDTH,
height: imageView.frame.size.height
)
)
imageView.contentMode = .Center
imageView.autoresizingMask = .None
//calculate textLabel inset
textLabel.frame = CGRect(
origin: CGPoint(
x: imageView.frame.origin.x + imageView.frame.size.width + TEXT_VIEW_LEFT_INSET,
y: textLabel.frame.origin.y
),
size: textLabel.frame.size
)
}
}
}

How to add a footer to the UITableView?

I'me using this code to add a footer to the TableView. It has 20 sections, and each section a few rows. There's a titleForHeaderInSection, and sectionForSectionIndexTitle methods.
CGRect footerRect = CGRectMake(0, 0, 320, 40);
UILabel *tableFooter = [[UILabel alloc] initWithFrame:footerRect];
tableFooter.textColor = [UIColor blueColor];
tableFooter.backgroundColor = [self.theTable backgroundColor];
tableFooter.opaque = YES;
tableFooter.font = [UIFont boldSystemFontOfSize:15];
tableFooter.text = #"test";
self.theTable.tableFooterView = tableFooter;
[tableFooter release];
What am I doing wrong?
thanks,
RL
I'm specifically seeing in my code that
self.theTable.tableFooterView = tableFooter;
works and
[self.theTable.tableFooterView addSubview:tableFooter];
does not work. So stick to the former and look elsewhere for the possible bug.
HTH
You need to implement the UITableViewDelegate method
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
and return the desired view (e.g. a UILabel with the text you'd like in the footer) for the appropriate section of the table.
I used that and it worked Perfectly :)
UIView* footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
[footerView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"ProductCellBackground.png"]]];
self.tableView.tableFooterView = footerView;
[self.tableView setSeparatorStyle:(UITableViewCellSeparatorStyleNone)];
[self.tableView setContentInset:(UIEdgeInsetsMake(0, 0, -500, 0))];
I know that this is a pretty old question but I've just met same issue. I don't know exactly why but it seems that tableFooterView can be only an instance of UIView (not "kind of" but "is member")... So in my case I've created new UIView object (for example wrapperView) and add my custom subview to it... In your case, chamge your code from:
CGRect footerRect = CGRectMake(0, 0, 320, 40);
UILabel *tableFooter = [[UILabel alloc] initWithFrame:footerRect];
tableFooter.textColor = [UIColor blueColor];
tableFooter.backgroundColor = [self.theTable backgroundColor];
tableFooter.opaque = YES;
tableFooter.font = [UIFont boldSystemFontOfSize:15];
tableFooter.text = #"test";
self.theTable.tableFooterView = tableFooter;
[tableFooter release];
to:
CGRect footerRect = CGRectMake(0, 0, 320, 40);
UIView *wrapperView = [[UIView alloc] initWithFrame:footerRect];
UILabel *tableFooter = [[UILabel alloc] initWithFrame:footerRect];
tableFooter.textColor = [UIColor blueColor];
tableFooter.backgroundColor = [self.theTable backgroundColor];
tableFooter.opaque = YES;
tableFooter.font = [UIFont boldSystemFontOfSize:15];
tableFooter.text = #"test";
[wrapperView addSubview:tableFooter];
self.theTable.tableFooterView = wrapperView;
[wrapperView release];
[tableFooter release];
Hope it helps. It works for me.
Initially I was just trying the method:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
but after using this along with:
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
problem was solved. Sample Program-
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 30.0f;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UIView *sampleView = [[UIView alloc] init];
sampleView.frame = CGRectMake(SCREEN_WIDTH/2, 5, 60, 4);
sampleView.backgroundColor = [UIColor blackColor];
return sampleView;
}
and include UITableViewDelegate protocol.
#interface TestViewController : UIViewController <UITableViewDelegate>
These samples work well. You can check section and then return a height to show or hide section. Don't forget to extend your viewcontroller from UITableViewDelegate.
Objective-C
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if (section == 0)
{
// to hide footer for section 0
return 0.0;
}
else
{
// show footer for every section except section 0
return HEIGHT_YOU_WANT;
}
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UIView *footerView = [[UIView alloc] init];
footerView.backgroundColor = [UIColor blackColor];
return footerView;
}
Swift
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.backgroundColor = UIColor.black
return footerView
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if section == 0 {
// to hide footer for section 0
return 0.0
} else {
// show footer for every section except section 0
return HEIGHT_YOU_WANT
}
}
Swift 2.1.1 below works:
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let v = UIView()
v.backgroundColor = UIColor.RGB(53, 60, 62)
return v
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 80
}
If use self.theTable.tableFooterView = tableFooter there is a space between last row and tableFooterView.
[self.tableView setTableFooterView:footerView];
instead of
self.theTable.tableFooterView = tableFooter;
try
[self.theTable.tableFooterView addSubview:tableFooter];
I had the same problem but I replaced the following line in my header:
#interface MyController : UIViewTableViewController <UITableViewDelegate, UITableViewDataSource>
with this line and it works as expected:
#interface RequestViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
Notice the UIViewController.
Good luck :)
If you don't prefer the sticky bottom effect i would put it in viewDidLoad()
https://stackoverflow.com/a/38176479/4127670

How to reliably subclass UITableViewCell for grouped UITableView?

When writing a customized subclass of UITableViewCell, I find that the results work well for the rectangular cells of a plain-styled UITableView, but do not work at all for the rounded cells in a grouped-styled table.
Is there a way to reliably subclass UITableViewCell to draw cells which work for grouped-style tables? (Without using Interface Builder.)
Could the answer be as simple as first calling [super layoutSubviews] inside your UITableViewCell subclass’s layoutSubviews method?
Here is my code.
First I create the UITextField and add it to the contentView in the initWithStyle: method:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
inputField = [[UITextField alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:inputField];
inputField.borderStyle = UITextBorderStyleLine;
[inputField release];
}
return self;
}
Then in layoutSubviews, I’ve got this:
-(void)layoutSubviews
{
inputField.frame = CGRectMake(5, 5, 100, 20);
}
With that code, the text field is 5px from the left of the screen, which is, of course, 5px to the left of the table cell when it’s in grouped mode. In other words, OUTSIDE of the table view cell. No good.
Use this code and the inputField is placed 5px to the right of the cell, like I want it to be:
-(void)layoutSubviews
{
[super layoutSubviews]; // the magic line
inputField.frame = CGRectMake(5, 5, 100, 20);
}
I could have totally misunderstood the problem you were having, though!
Erik
I used to have lots of problems with UITableViewCell subclasses, but then I just stopped subclassing.
Adding subviews to the contentView property of a UITableViewCell seems to accomplish the same thing in any instance that I've run across, so I just do that inside my UITableViewController.
Here's an example that has a title and value:
- (UITableViewCell *)tableView:(UITableView*)tableView
cellForRowAtIndexPath: (NSIndexPath*)indexPath
{
static NSString* CellIdentifier = #"AccountDetailsCell";
UILabel* mainLabel = nil;
UILabel* valueLabel = nil;
const CGFloat kAccountDetailFontSize = 14.0;
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if ( cell == nil )
{
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
reuseIdentifier: CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake( 10.0, 0.0, 150.0, 44.0 )] autorelease];
mainLabel.tag = MAINLABEL_TAG;
mainLabel.font = [UIFont boldSystemFontOfSize: kAccountDetailFontSize];
mainLabel.textAlignment = UITextAlignmentLeft;
mainLabel.textColor = [UIColor darkGrayColor];
mainLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight;
mainLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview: mainLabel];
valueLabel = [[[UILabel alloc] initWithFrame: CGRectMake( 150.0, 0.0, 150.0, 44.0 )] autorelease];
valueLabel.tag = VALUELABEL_TAG;
valueLabel.font = [UIFont boldSystemFontOfSize: kAccountDetailFontSize];
valueLabel.textAlignment = UITextAlignmentRight;
valueLabel.textColor = [UIColor darkTextColor];
valueLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
valueLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview: valueLabel];
}
else
{
mainLabel = (UILabel*)[cell.contentView viewWithTag: MAINLABEL_TAG];
valueLabel = (UILabel*)[cell.contentView viewWithTag: VALUELABEL_TAG];
}
mainLabel.text = (NSString*)kCellTitles[indexPath.section][indexPath.row];
valueLabel.text = [self tableView: tableView valueLabelTextForRowAtIndexPath: indexPath];
return cell;
}
I've noticed this problem as well. My workaround has been to just make my table cells smaller (300 width instead of 320). It's not a great solution, but it works well.
I don't believe you can get rid of the table view insets on an individual basis when in "grouped" mode. I could be wrong though!
What problem are you having? In drawRect you are given a rect, and know your total size - just conform to that space. If you are using layoutSubviews, same thing.