how to add a subview to a tableView cell.contentView swift - swift

I'm a little confused where should I declare and how to add a subView to a cell to make the cell shorter in width.
I tried to use func viewWillLayoutSubviews(){} in my tableViewCell class but I can't access the tableView from there...weird..
What do I need to subclass for this to work and where do I need to insert this code?
Currently this code just adds a subview to the cell and kind of floats on top of the cell instead of containing the cell. I'm using it in cellForRowAtIndexPath.
let testFrame : CGRect = cell.contentView.frame
var testView : UIView = UIView(frame: testFrame)
testView.backgroundColor = UIColor.redColor()
testView.alpha=0.5
testView.bounds = CGRectMake(cell.bounds.origin.x,
cell.bounds.origin.y,
cell.bounds.size.width - 50,
cell.bounds.size.height);
//TableViewCell.addSubview(testView)
cell.contentView.addSubview(testView)
return cell

A subview is added inside of the cell, you are adding testView as a subview of the cell's content view. The frame of testView will be relative to the cell's content view (testView's superview).
It is not a good idea to change the width of UITableViewCell because there may be unintended side effects. You can override setFrame in a subclass of UITableViewCell which you return from cellForRowAtIndexPath:. More info here: How to set the width of a cell in a UITableView in grouped style
You should look at UICollectionView if you need cells that are not full width or make your table view the width you need.

Related

Subview of dynamic height in UITableViewCell

This question is w.r.t xib and old style of showing custom CellView's in UITableView. I do have autolayouts in my views.
I have a DynamicSubView (dynamic height) of type UIView which I want to reuse in UITableViewCell. For this I have tried 2 things,
Adding DynamicSubview as [cell.contentView addSubview:myDynamicView]
Added a UIView inside cell.xib's contentView with constraint 0-0-0-0 on all Left-Top-Right-Bottom. And a height as NSLayoutConstraint which I am calulating & changing at runtime. And setted identity inspector of that view to DynamicSubview.
In MyCell.m class, I have added created a object of DynamicSubView class in awakeFromNib & in layoutSubView method, I am calculating dynamic height of DynamicSubView.
I tried adding height related code in heightForRowAtIndexPath, but it goes in infinite-loop for the very first time when table loads.
The problem is the cells are getting overlaped. Should I create an array of height values and reload again. Any better solution to reload the cell again with proper height.
Code In MyCell class:
- (void)awakeFromNib
{
[super awakeFromNib];
self.myDynamicView = (DynamicSubView *)self.myContainerView;
[self.myDynamicView setUpView:YES];
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self.myDynamicView doSomething];
self.c_height.constant = [self.myDynamicView getHeightOfDynamicSubview];
//CGRect cellFrame = self.contentView.frame;
//self.contentView.frame = CGRectMake(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, self.c_height.constant);
self.cellHeight = self.c_height.constant;
}
Rather than using the LayoutSubiew() inside the tableViewCell, you can you the following methods in your view controller
SWIFT
self.tableView.estimatedRowHeight = 100 (Let's say minimum height of your tableViewCell is 100)
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}

disable tableHeaderView (Not to be confused with section header) scrolling

Is it possible to disable the scrolling of tableHeaderView (Not to be confused with section header).Right now whenever I scroll the table, view in the tableHeaderView also gets scrolled.
What i am doing:
I have a class subclassed from UITableViewController.
In storyboard, I am using the static table view.
Table style is Grouped and I have added 8 sections having a row each.
On the top of 1st section, added a view which is the tableHeaderView.
I want to disable the scrolling of view with title "Profile" when I scroll the table.
PS:
I know this is achievable if I subclassed my class from UIViewController instead of UITableViewController.
But I don't want to UIViewController because I am using storyboard for designing static cell and If I use UIViewController instead of UITableViewController then compiler throws a warning "Static table views are only valid when embedded in UITableViewController instances"
Please let me know which is the best approach to achieve this.Is it possible to disable the scrolling of tableHeader using my current approach or do I need to use UIViewController instead.
Just use an embed segue with a parent UIViewController consisting of a header view and a container view. Embed your UITableViewController in the container view. More specific steps in this answer.
If you want everything in UITableViewController, you can insert your own subview doing something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.header = [[UIView alloc] init];
self.header.frame = CGRectMake(0, 0, self.tableView.bounds.size.width, 44);
self.header.backgroundColor = [UIColor greenColor];
[self.tableView addSubview:self.header];
self.tableView.contentInset = UIEdgeInsetsMake(44, 0, 0, 0);
}
and then manipulate the position of the view in scrollViewDidScroll and friends:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
self.header.transform = CGAffineTransformMakeTranslation(0, self.tableView.contentOffset.y);
}
I say "and friends" because you'd need to take care of the corner cases like scrollViewDidScrollToTop:. scrollViewDidScroll gets called in every display cycle during scrolling, so doing it this way looks flawless.
Timothy Moose was spot on. Here are the necessary changes for iOS8.
MonoTouch (C#)
// create the fixed header view
headerView = new UIView() {
Frame = new RectangleF(0,0,this.View.Frame.Width,44),
AutoresizingMask = UIViewAutoresizing.FlexibleWidth,
BackgroundColor = UIColor.DarkGray
};
// make it the top most layer
headerView.Layer.ZPosition = 1.0f;
// add directly to tableview, do not use TableViewHeader
TableView.AddSubview(headerView);
// TableView will start at the bottom of the nav bar
this.EdgesForExtendedLayout = UIRectEdge.None;
// move the content down the size of the header view
TableView.ContentInset = new UIEdgeInsets(headerView.Bounds.Height,0,0,0);
.....
[Export("scrollViewDidScroll:")]
public virtual void Scrolled(UIScrollView scrollView)
{
// Keeps header fixed, this is called in the displayLink layer so it wont skip.
if(headerView!=null) headerView.Transform = CGAffineTransform.MakeTranslation(0, TableView.ContentOffset.Y);
}
[Export ("scrollViewDidScrollToTop:")]
public virtual void ScrolledToTop (UIScrollView scrollView)
{
// Keeps header fixed, this is called in the displayLink layer so it wont skip.
if(headerView!=null) headerView.Transform = CGAffineTransform.MakeTranslation(0, TableView.ContentOffset.Y);
}

Get width/frame of entire UITableViewCell

I have a method where I have a (rendered) UITableViewCell*. I would like to know the width/frame of the entire cell.
cell.frame doesn't seem to work - it gives me the frame of a random cell. The closest I got is cell.contentView.frame but it doesn't include the area covered by the accessoryView (see http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7). cell.contentView.superview.frame doesn't work either - it gives me a frame at some arbitrary location just like cell.frame does.
cell.contentView.width + cell.accessoryView.width works except in cases where the accessory view is UITableViewCellAccessoryNone
Any ideas how I can get the entire frame/width of the UITableViewCell in all cases?
Try this,
NSLog(#"Cell Width = %f",cell.frame.size.width);
NSLog(#"Cell Height = %f",cell.frame.size.height);
It will show the current cell Width and Height.
This code gives you the frame of the particular cell selected by indexPath:
// Get the cell rect and adjust it to consider scroll offset
CGRect cellRect = [tableView rectForRowAtIndexPath:indexPath];
cellRect = CGRectMake(cellRect.origin.x - tableView.contentOffset.x, cellRect.origin.y - tableView.contentOffset.y, cellRect.size.width, cellRect.size.height);
cell.frame will always give you the frame of the cell you're messaging.
And even if it did return a random cell, you should still be able to use the width of the frame, because all the cells have the same width.
I think by default, a cell will use 100% of the width of the UITableView so a UITableView's width is equivalent to a cell's width and because you would likely have set your table cell height using:
[UITableView setRowHeight:tableCellHeight];
Where tableCellHeight is a number of your choice and UITableView is the name of your UITableView not the UITableView class itself.
Then you would have both the width and height of a table cell, or did I misinterpret your question?

Change image or style of specific UITableViewCell

Is there any way that I can get a specific cell to change its style or background image while scrolling the table view?
I want to change the image of a cell which is on top of the visible cells. But only its image is going to be changed the others will stay same, until after scrolling the others come to top of the cells which are shown on the screen. Then the top one's image is going to change this time.
You need to implement scrollViewDidScroll: method of UIScrollViewDelegate in your controller then use visibleCells property of UITableView to get the visible cells of the table.
Something like the following code should work
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
UITableView* tableView;
NSArray* visibleCells;
BOOL first;
tableView = (UITableView*)scrollView;
visibleCells = tableView.visibleCells;
first = YES;
for (UITableViewCell* cell in visibleCells) {
if (first) {
//customize the top cell
first = NO;
}else {
//customize the other visible cells
}
}
}

Automatically determining the size of a UITableViewCell

I am trying to determine the size of a UITableCellView. The reason being that I am using one class for different orientations and devices.
The cell contains one subview that is supposed to fill the entire cell. Right know I'm doing this in the UITableViewCell's init method:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
//iPad
subv = [[OrbitView alloc] initWithFrame:CGRectMake(52, 5, 660, 420) ];
}else{
//iPhone
subv = [[OrbitView alloc] initWithFrame:CGRectMake(15, 5, 290, 200) ];
}
Clearly, there must be a better way of doing this, without the magic numbers. How/Where should I set the frame of the subview in the UITableViewCell so that it fills the entire UITableViewCell?
Use the dimensions of the table view that the cell will go in. Set the autoresizingMask to flexible width to handle rotation and accessory views. This code assumes you have set the rowHeight of the table, but you could use a fraction of the screen height instead of testing the device type.
-(CGRect) cellFrameForTableView:(UITableView *)inTable {
CGRect result = [inTable frame];
result.origin = CGPointZero;
result.size.height = [inTable rowHeight];
return result;
}
Add your custom view to the cell content, not the cell, if you want auto sizing to adjust your view to leave room for cell extras like accessory views. In that case things like edit controls will adjust your custom view along with the content view.
In the past I have had trouble with flexible height views in cells, so I would go with flexible bottom margin instead.