How to add subviews to a tableview cell dynamically - ios

I created a custom tableview cell in IB. I add a scroll view as a subview of the cell's contentView, and create the IBOutlet in the tableview cell subclass, and make the connection. My problem is, I want to add subviews to the cell dynamically, but when I did this in code, nothing happens. The cell is rendered successfully, but the scrollView has nothing to show (no subviews on it).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// deque the cell
// create some label depending on the MODEL object
// (this is done by code, not in IB. because the label is content-based)
// we don't know how many labels in advance
[cell.scrollView addSubview: label]; // not working !!
...
return cell;
}
But if I add the subviews in IB (which means the subviews are pre-defined), it works.
Is there any ways to add the subviews to a cell dynamically ? Or maybe I put the code in the wrong place ?

Thanks for all of the responses.
This is really embarrassing. The problem is I mis-config the label property, make the label text color white, but somehow the scrollView background is also white. So I can't see the labels, but actually they are already there.
All the responses are helpful, but #Shebin's answer gave me the hint to check the color, so I think I should mark his answer as the best.

Try this
UILabel *label1 = [[UILabel alloc]initWithFrame:CGRectMake(8, 8, 130, 30)];
label1.text = #"any text";
label1.textColor = [UIColor redColor];
label1.backgroundColor = [UIColor greenColor];
[cell addSubview:label1];// first try adding to cell
if you need to add as subview of cell.scrollView
NSLog(#"scrollView %#",cell.scrollView);//it should not be nil
check scrollView content size and frame
For dynamic string this will also help you
NSString *string = #"This is the text";
CGSize stringsize = [string sizeWithFont:[UIFont systemFontOfSize:[UIFont systemFontSize]]];
UILabel *label1 = [[UILabel alloc]initWithFrame:CGRectMake(8, 8, stringsize.width+30/*you have to adjust 30 as u required*/, 30)];
label1.text = string;
label1.textColor = [UIColor redColor];
label1.backgroundColor = [UIColor greenColor];
cell.scrollView.contentSize = CGSizeMake(label1.frame.size.width+30/*you have to adjust 30 as u required*/, label1.frame.size.height);
[cell.scrollView addSubview:label1];

You need to add proper constraints on your sub views. The scrollable size of a UIScrollView is computed based on the constraints of its subviews. Please ensure that constraints on the content view of your cell is properly added.
And if you are not setting constraints on your subview like label etc. then its intrinsicContentSize is used.

Related

Custom View with dynamic Height as UITableView Header ios xcode

In my project,i have a 1.MovieplayerView,2.a label with dynamic content,3.a tableView with variable number of rows.
I was doing this with all these views in scrollView.But i always have the issue with dynamic height of the label.it sometime overlaps the tableView.
I came to know that we can use customView as the tableView header.How this can be done with variable content Height and autolayout?I am new to iOS.Any suggestion ??
I know how to add a view as the header to a table.But when the contents in the view changes,it overlaps the contents of the tableView.
I went through
How to resize superview to fit all subviews with autolayout?,How do I set the height of tableHeaderView (UITableView) with autolayout?
Can some one give a simple example on how to do this?Or tell me if it is better to use a scrollview and add all these views as its subviews? any suggestion would be realy helpful.Thanks.
In viewDidAppear,
1. Get the height of the dynamic content, then set the height of your tableHeaderView accordingly.
2. Set the headerView again so the table view can refresh:
self.tableView.tableHeaderView = headerView
Try using following code is this what u want to achieve can u clearify me please
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 40)];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 200, 40)];
NSString *string = [NSString stringWithFormat:#"/ %#",selectedCategory];
label.font = [UIFont fontWithName:#"Helvetica" size:15.0];
label.textColor = ThemeColor;
[label setText:string];
[view addSubview:label];
[view setBackgroundColor:[UIColor colorWithRed:0.933f green:0.933f blue:0.933f alpha:1.00f]];
return view;
}
Don't forget to place this in nib of UITableView
It's hard to interpret your question regarding your use of the scroll view. If what you want is a custom view as the table view header, you could override this method in your table view class:
- (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section

iOS 7.1 UitableviewCell content overlaps with ones below

So I have code, which is sucessfully working on iOS 7.0 but not in 7.1. I have a simple tableview, with code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70.0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
for (UIView *view in cell.contentView.subviews) {
[view removeFromSuperview];
}
UILabel *label = [[UILabel alloc] init];
label.text = [NSString string];
for (NSInteger i = 0; i < 20; i++) {
label.text = [label.text stringByAppendingString:#"label String "];
}
label.translatesAutoresizingMaskIntoConstraints = NO;
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWorldWrapping;
//label.lineBreakMode = NSLineBreakByTruncatingTail; //I have tried this too
[cell.contentView addSubview:label];
NSDictionary *dict = NSDictionaryOfVariableBindings(label);
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-8-[label]-8-|" options:0 metrics:nil views:dict]];
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-8-[label]" options:0 metrics:nil views:dict]];
if (indexPath.row == 0) {
label.textColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:1.0];
}
else if (indexPath.row == 1) {
label.textColor = [UIColor colorWithRed:0 green:1.0 blue:0 alpha:1.0];
}
else if (indexPath.row == 2) {
label.textColor = [UIColor colorWithRed:0 green:0 blue:1.0 alpha:1.0];
}
else {
label.textColor = [UIColor colorWithWhite:0.3 alpha:1.0];
}
cell.backgroundColor = [UIColor colorWithWhite:1.0 alpha:1.0];
return cell;
}
I have 1section with 10rows. With each row reused I delete all subviews from contentView(I tried alloc-init UITableViewCell, but came with the same results).
On iOS 7.0, UILabel is displayed only in cell it belongs to. But in 7.1 UILabel continues displaying over another cells. What is interresting, that when I click on cell, it stop being overlaping by anothers, but only till I click on cell above.
My question is, how to make it work on 7.1devices like on 7.0ones.
I tried both simulator and device and I took a look at iOS 7.1 API Diffs, but found nothing related to this.
Maybe it is issue of Auto Layout, that i have variable height of UILabel, but I need to do so. I want to have all text in UILabel, but display only part of UILabel, that can be displayed in a cell, which is default behavior in 7.0, but 7.1 changes this and I don't why why and how to deal with it.
This is dropbox folder for images with detail explanation: Folder with images
Update: I tried things like tese, but nothing worked for me.
cell.frame = CGRectMake(0, 0, self.tableView.frame.size.width, 70);
cell.contentView.frame = CGRectMake(0, 0, self.tableView.frame.size.width, 70);
cell.opaque = NO;
cell.contentView.opaque = NO;
cell.clearsContextBeforeDrawing = NO;
cell.contentView.clearsContextBeforeDrawing = NO;
cell.clipsToBounds = NO;
cell.contentView.clipsToBounds = NO;
The issue has to do with the height of your cell. It isn't going to dynamically adjust that for you.
You'll probably notice that as you scroll and the view above goes out of view the overlapping text will disappear with it.
If you are wanting your text to clip at a certain height, then you need to set the number of lines, rather than setting it to 0 since that will let it continue forever.
The lineBreakMode won't take effect since it isn't stopped.
Optionally you could try to set clipping on the contentView to make sure all subviews stay inside.
Depending on the end result you want, you could do dynamic heights and change based on the content. There are a bunch of SO questions related to doing this.
Update - clipping the contentView
I'd have to try it out myself, but in lieu of that, here are a couple links related to clipping the contentView:
stop the clipping of contentView - you'd actually want to do the opposite.
adding subview - looks similar to what you are trying to do.
Looks like this works:
cell.clipsToBounds = YES;
Here is the Perfect solution of Overlapping content in Cells.
Just use below code in cellForRowAtIndexPath after allocating cell and before adding subviews.
for (id object in cell.contentView.subviews)
{
[object removeFromSuperview];
}
Actually the overlapping is occurring because whenever you scroll the tableview its allocating your added view again and again. So above code will solve your problem by removing the existing views from cell's contentView.
Now You can see the memory debug session after applying above code, your memory is stable this time.
Hope it'll help you.
Thanks !
This is problem with recreating cell contents. Try with following code segment.
for(UIView *view in cell.contentView.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
#Gaurav your answer should be the accepted answer. Thanks!
for object in cell.contentView.subviews
{
object.removeFromSuperview();
}
had similar behavior in iOS 8, using storyboard / IB.
fix was to add a Bottom Space to: Superview constraint from the bottom-most view to bottom of the prototype cell's Content View. The other views and constraints were all anchored from the top.
Are you using storyboards?
If so, select the table view controller in storyboards and uncheck the "Under bottom bars"
You can also do this programmatically.
If your TVC inherits from a nav view controller or a tab view controller, you may need to uncheck this layout option on the parent view instead
Re-checking all 4 constraints helps. While working with table view or collection view it's necessary to apply all four constraints (leading, trailing, top, bottom.)

How to keep the text of cell label at top when cell's height increases?

I am increasing cell's height in the method heightForRowAtIndexPath, as a result of it, the label is coming centered.
How do make sure that label is still at top with the text irrespective of the height of the row?
While allocating UITableViewCell, you need to do like this..
UITableViewCell * cell;
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:string];
At the time of initialization with style: UITableViewCellStyleSubtitle will come.
Hope this will work..
You can do it in two ways.
Create a custom label and set it's frame.
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, WIDTH, HEIGHT)];
[cell.contentView addSubView:lbl];
Use a UITableViewCell subclass and override -layoutSubviews. In this method, you'll want to call [super layoutSubviews].
- (void)layoutSubviews {
[super layoutSubviews];
CGSize size = self.bounds.size;
CGRect frame = CGRectMake(0.0f, 0.0f, size.width, size.height);
self.textLabel.frame = frame;
self.textLabel.contentMode = UIViewContentModeScaleAspectFit;
}
Write Following Code:
UILabel *myLable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, width, height)];
[cell.contentView addSubView: myLable];
If Also You want myLable fram is similare to myLable.text then write..
[myLable sizeToFit];
You cannot change the position of textlabel as it is auto-adjusted.
First option is you need to subclass UITableViewCell and customize textLabel frame.
Another is that you create your own custom label and make textlabel nil. So whenever cell's height will change, your label position will not change.
Set the autolayout Top property of UILabel.
try this:
set False to "Autoresize Subviews" property of your custom cell...

UILabel in UITableView

My question is how to add a gray edge to each label on (UITableViewCell that contains many 3 labels)?
So that my labels for each cell will be sepraeted by the edge.
You can have a UIView as content of UITableViewCell by adding subviews to contentView property of UITableViewCell.
Add your labels as subviews to the cell and to have separators in between labels you can use this kind of code
UIView* vertLineView = [[UIView alloc] initWithFrame:CGRectMake(80, 0, 1, 44)];
vertLineView.backgroundColor = [UIColor redColor];
[self.contentView addSubview:vertLineView];
Reference:Draw vertical separator on UITableViewCell
Hope this solves your problem.
If you only want to separate the labels from each other, you could add a UIImageView between them with a small width (like 1 or 2 points) with a dark picture. If you want them to have border, set:
myLabel.layer.borderColor = [UIColor blackColor];
myLabel.layer.borderWidth = 1.0;
Don't forget to include QuarzCore.

iOS UITableView unexpectedly adding margins

I have a UITableView, and currently it has a single cell in it. I have written a custom TableViewCell class which inherits from UITableViewCell in order to do some custom drawing. I have set the width of the table to the desired size, and am trying to set the width of the cell to the same size, so it will fill up the entire width of the table. The problem seems to be that I'm getting some margins on the left and right sides of the cell, and I don't know why.
Here's an example of the problem.
I made the TableView background black to be more clear. The TableView is the correct size. The background image is added to the cell, not the table, and it should be taking up the full width of the table.
I have tried making the TableView wider (as wide as the screen) to try to accommodate the size of the background image, but that doesn't quite do it. I would rather just figure out where these margins are coming from, and how I can get rid of them.
The TableView itself is initialized in Interface Builder. The style is set to Grouped, scrolling is disabled, and the view mode is set to Scale To Fill.
Here's the cell class' initWithStyle method
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// Initialization code
_primaryLabel = [[UILabel alloc] init];
_primaryLabel.textAlignment = UITextAlignmentLeft;
_primaryLabel.font = [UIFont systemFontOfSize:18];
_primaryLabel.backgroundColor = [UIColor clearColor];
_detailLabel = [[UILabel alloc] init];
_detailLabel.textAlignment = UITextAlignmentLeft;
_detailLabel.font = [UIFont systemFontOfSize:12];
_detailLabel.backgroundColor = [UIColor clearColor];
_icon = [[UIImageView alloc] init];
[self.contentView addSubview:_primaryLabel];
[self.contentView addSubview:_detailLabel];
[self.contentView addSubview:_icon];
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
UIImageView* whiteDisclosureView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 15, 13)];
[whiteDisclosureView setImage:[UIImage imageNamed:#"white_disclosure.png"]];
self.accessoryView = whiteDisclosureView;
UIImageView * background = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 305, 61)];
[background setImage:[UIImage imageNamed:#"button_silver.png"]];
[self setBackgroundView:background];
self.backgroundColor = [UIColor clearColor];
self.frame = self.contentView.frame = CGRectMake(0, 0, 305, 61);
}
return self;
}
Is your tableView using "grouped" style? With grouped style, iOS normally adds left and right margin for the table cells.
It may be possible to remedy this by adjusting the frame of the tableView to slightly outside its superview. See here for example in previous question
You shouldn't explicitly set your cell's frame (size), but declare its style. (If you don't do that already) The cells are designed to automatically take up the whole space. (Horizontally)
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
If not when allocating your cell, how do you set the cell's frame?
EDIT: Instead of using hardcoded frame sizes, use self.frame. Additionally, remove the last statement where you set the frame.
Another alternative solution I used.
#jonkroll's solution does work but it does not fulfil my need. I have a header section in the table view which I want to keep the margin left and right as is, but want to remove them on the normal cell.
The solution I did is to implement a layoutSubViews method in a custom table view cell. Within this method, set the contentView's width equal to table cell's width.
-(void)layoutSubviews {
self.contentView.frame.size.width = self.frame.size.width;
}
This may be very late, but I think some people will run into the same problem as well. Hope this solution works for you guys : )

Resources