I found a lot of similar questions, but there was no answer for me.
I'm trying to do the same cell, like note cell in iOS contacts application. There is label on left and uitextview on the right. There is only one problem when I can't set proper cell height. When delegate first asks about cell height, I call this method:
-(float)getHeight:(NSString *)descriptionFieldText
{
UITableViewCell * cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:#"Tmp"] autorelease];
cell.detailTextLabel.text = #"temp string";
[cell layoutSubviews];
float beg = cell.contentView.frame.size.width - cell.textLabel.frame.origin.x * 2 - cell.textLabel.frame.size.width;
return [m_balloon.descriptionField sizeWithFont:[cell.detailTextLabel.font fontWithSize:[cell.detailTextLabel.font pointSize]] constrainedToSize:CGSizeMake(beg, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap].height;
}
But I can't get proper height on all devices and all orientations. Please help.
Related
This question already has answers here:
Using Auto Layout in UITableView for dynamic cell layouts & variable row heights
(28 answers)
Closed 6 years ago.
Hi in my application i have a requirement to display prodcuts with description in tablview. For achieving this i added two satckviews on tablview cell content view. Both stackviews holds labels and one label have a prodcut name and another one have description. At app launch the app cell height is 100 by default, but when ever i select cell i want to show complete description in cell along with product name i mean need to change cell height.Can anyone please let help me how to achieve this.How to change cell height dynamically. Please help me.
I tried below approach it shows more description in stack view label but cell height is not getting change. So unable to see total description.
cell.productDescription.numberOfLines=50;
cell.productDescription.lineBreakMode=NSLineBreakByCharWrapping;
Best way to use Constraint for your application. So you don't have to manage heighforCell. If you are going to coding part then you have to find out height of text and then you need to set in heightForRowAtIndexPath method.
Here is the code to get height from string:
-(float )getHeightForText : (NSString *)strText
{
UILabel *lbl = [[UILabel alloc] init];
CGRect rect;
rect.origin = CGPointZero;
float width = YOUR_LABEL_WIDHT
rect.size = CGSizeMake(width, 3000);
lbl.font = MESSAGE_TEXT_FONT;
lbl.frame = rect;
lbl.text = strText;
lbl.numberOfLines = 1000;
[lbl sizeToFit];
float height = lbl.frame.size.height;
return height;
}
Write below code in your heightForRowAtIndexPath method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [self getHeightForText:YOUR_TEXT];
}
Use UITableViewDelegate Method
#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
basically I'm using autoresizing custom table view cells to display data on a table view and they resize perfectly, usually. The cells have a UILabel on them to display the data and the cells autoresize if the devices text size is changed. I'm sometimes having troubles with the cells autoresizing to show all of the UILabel's text. For example if the text size is medium sized, it sometimes doesn't fully display all the text of a longer label, it will show most of it then show "..." but if I increase or decrease the text size it will show it all but it might do the same thing for a different cell.
Any suggestions? Here's my code that calls the autoresize:
- (void)viewDidAppear:(BOOL)animated
{
[self.tableView reloadData];
[self retrieveFromParse];
self.tableView.estimatedRowHeight = 100;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
and to autoresize depending on text size:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
_cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (_cell == nil)
{
_cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
PFObject *object = [_postsArray objectAtIndex:indexPath.row];
NSString *nameString = [object objectForKey:#"Name"];
_cell.cellLabel.text = [NSString stringWithFormat:#"Posted by %#", nameString];
_cell.cellPostLabel.text = [NSString stringWithFormat:#" %#", [object objectForKey:#"Post"]];
//The following lines are to auto resize when the text size is changed
_cell.cellLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
_cell.cellPostLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline];
return _cell;
}
Try using autoresizingMask if that helps
_cell.cellLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
Auto Layout has trouble figuring out how to draw multi-line labels if you don't set preferredMaxLayoutWidth on each one. The trouble is finding out what value to use since tables can change widths across the various iPhone & iPad devices, orientations, etc. To fix this, I usually subclass UILabel to override layoutSubviews:
- (void)layoutSubviews {
[super layoutSubviews]; // 1
self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds); // 2
[super layoutSubviews]; // 3
}
The first call to super correctly determines how wide the label should be.
Using the correct width, set preferredMaxLayoutWidth to the correct value.
Do another layout pass to render the label with its final and correct properties.
If you use autolayout, I have solution for you. I'm not sure that this is the perfect one, but here it is (Swift):
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
// configure your cell
cell.layoutIfNeeded()
}
P.S. if I doesn't use layoutIfNeeded and if I rotate my device and turn it back, to portrait, label layouts as it must e.g. 2 or more strings in one cell.
Didn't find reason why this occur, because (I use more that one prototype cell in my project) other type cells is okay, but their labels have simular constraints and settings.
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 66
}
works just fine on 8.4.1 for UITableViewCellStyle.Default cells
I have a custom class created for custom cells for my table view. There's UILabel for messages. I'm using storyboard to set the constraints, pinning the label to the top and right side of the table cell, I found that doing this causes the label to resize to fit the content. Now I can't figure out how to add padding to the label because anything done in cellForRowAtIndexPath doesn't work since auto layout is selected. I've seen many examples that do CGRectMake with float values but they don't work and I think it's because of auto layout. Is there any solution for this?
I'm not even sure what code to show for this...so here goes something:
How I'm getting the height of the message...the cell is set for 220 width...cellForRowAtIndexPath:
static NSString *cellIdentifier = #"chatCell";
ChatCell *cell = (ChatCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[ChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
info = [receivedData objectAtIndex:indexPath.row];
message = [info objectForKey:#"message"];
CGSize constraint = CGSizeMake(220, 2000);
CGRect rect = [message boundingRectWithSize:constraint options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:[UIFont systemFontOfSize:12.0f]} context:nil];
CGSize size = rect.size;
With that information, I set the table row heights in heightForRowAtIndexPath. But adjusting the frame of the label cell.messageLabel gives me no result. Here's something else I tried in the cellForRowAtIndexPath:
UIView *messageFrame = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 220, size.height)];
[messageFrame addSubview:cell.messageLabel];
[cell addSubview:messageFrame];
But this is the result in the simulator:
Everything is moved up and the whole text doesn't show. Is there a simple solution for this or do I have to rethink my entire code?
ANSWER:
What I did was add a UIView in storyboard and put it's constraints to the bottom of the cell. Since I was adjusting the cell height based on content bounds function from ios7, setting the constraint to the bottom automatically stretched the UIView all the way to the bottom. Playing with the message label width, I got to have padding. Hope this helps someone.
I'm new in iOS programming that's why I'm looking for the most efficient solution to my problem.
What I want to achieve is to display in UITableViewCell with a name (some text) and under each name some filled little rectangles with a number inside, similar to badges.
My first idea is to create a UIView that will represent the badge and in a custom UITableViewCell I will add these rectangles as subviews.
The second idea is to create only one UIView that will draw all the little rectangles.
My question is, which is the better performing solution knowing that:
the number of cells will be max. 20 and the total number of rectangles no more than 50
The number of rectangles displayed in a cell is different
I want to reuse the cells, so I have to update/redraw the cell content for each row
I want to avoid the cell selection view problem that "hides" the subviews
Of course any other solution is appreciated.
Thanks in advance,
hxx
What i would suggest is to sub class the UITableViewCell and make the customization u need in it.The customized view can have a label and rectangles below it.
The rectangles can be small custom buttons with background images (if you have any or give it a background color) and title as your number.You would have to ,however calculate their width based on the width of your table to accomodate the maximum number of rectangles.
You can disable the selection of the table in the xib or you can do it programmatically like so cell.selectionStyle = UITableViewCellSelectionStyleNone; and do not implement didSelectRowAtIndexPath
I have followed the approach of subclassing the cell for my tables to customize their look and feel and it works good.I hope this helps.
A Good tutorial to begin with subclassing can be found here
http://howtomakeiphoneapps.com/how-to-design-a-custom-uitableviewcell-from-scratch/1292/
Why you are not creating cell in -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath Here you can defines your custom type cell which will also reuse and whenever you want you can add the different thing to cell like this.
static NSString *CellIdentifier = #"Cell";
UILabel *RequestSentTo;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
cell.selectionStyle=UITableViewCellSelectionStyleNone;
RequestSentTo = [[UILabel alloc] initWithFrame:CGRectMake(11, 2, 286, 40)];
RequestSentTo.backgroundColor = [UIColor clearColor];
RequestSentTo.tag = 200;
RequestSentTo.numberOfLines = 3;
RequestSentTo.font=[UIFont boldSystemFontOfSize:15.0];
RequestSentTo.textColor = [UIColor blackColor];
RequestSentTo.lineBreakMode=UILineBreakModeWordWrap;
[cell.contentView addSubview:RequestSentTo];
} else {
RequestSentTo=(UILabel*)[cell.contentView viewWithTag:200];
}
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:#"Shift Request for "];
[string appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:#"%# by ",dateStr] attributes:nil]];
[string appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:#"Dr. %#",notificationsObj.doctorName] attributes:purpleTextAttributes]];//purpl
RequestSentTo.attributedText=string;
RequestSentTo.lineBreakMode=UILineBreakModeWordWrap;
RequestSentTo.numberOfLines = 3;
Whenever you want you can add the things you want with reusing cell. Hope this helps
2 methods come into my mind.
You can put the components as subview inside UITableViewCell(Through XIB or programatically subclassing UITableViewCell) and use it in UITableView.
You can subclass UITableViewCell, and override the -(void)drawRect method and draw all the components that you wish to be displayed on cell.
See if can help.
You can create a new class extends to UITableViewCell, which means to rewrite UITableViewCell as your own cell named as MyTestCell.
And in this Cell you call create your properties, like labels and views, and add those to your new cell.
like add this to MyTestCell.h
#property (nonatomic, retain) UILable *myLable1;
#property (nonatomic, retain) UIView *mySubview1;
MyTestCell.m
_myLable1 = .....
_mySubview = .....
[self addSubview: _myLbale1];
[self addSubview: _mySubview1];
And when use, u can work like this
static NSString *CellIdentifier = #"MyCell";
MyTableViewCell *cell = [tableview dequeReuseID:CellIdentifier];
if (cell == nil) {
cell = [MyTableViewCell alloc] init.........
}
//And you can sign your property here in your cell
cell.myLable1 = ....
cell.myView1 = .....
return cell;
}
If your strings add to the lable is different,make the lable.height is different. you can use code like this
CGSize labelSize = [str sizeWithFont:[UIFont boldSystemFontOfSize:17.0f]
constrainedToSize:CGSizeMake(280, 100)
lineBreakMode:UILineBreakModeCharacterWrap]; //check your lableSize
UILabel *patternLabel = [[UILabel alloc] initWithFrame:CGRectMake(35, 157, labelSize.width, labelSize.height)];
patternLabel.text = str;
patternLabel.backgroundColor = [UIColor clearColor];
patternLabel.font = [UIFont boldSystemFontOfSize:17.0f];
patternLabel.numberOfLines = 0;// must have
patternLabel.lineBreakMode = UILineBreakModeCharacterWrap;// must have
add this to your cell, and make it dynamically resize your lable as well as your cell! And also you have to dynamically set high for your tableView Row height.(Do know what is dynamically resize?)
See this:
rewrite the method setMyLable1 in MyTableViewCell.m
-(void)setMyLable1:(UILable*)aLable
{
//in here when never your sign your alabel to your cell (like this : cell.myLable1) this method will be call and u can get the size of your string and set this label's height
//get string size StringSzie
[_myLable1 setFrame:CGRectMake(10,10,stringSize.width,stringSize.height)];
//And resize your cell as well
[self setFrame:CGRectMake(0,0,_myLable1.frame.size.width+20,_myLable1.frame.size.height+20)];
//done!!!
}
OK you get a automactically reszie cell for yourself and you have to dynamically reset height for your row in tableView too!!!!!
What do you need is called custom cell
Here is good tutorial for it
customize table view cells for uitableview
I've frustrated myself with this question for a couple of days. I'm trying to add a UILabel to a UITableViewCell. I want the UILabel to span the entire width of the cell, minus 5 or 10 on both the right and left sides for looks. My problem is in programmatically determining the size of the cell's frame in which to place the label. No matter which UITableViewStyle I use, the cell.contentVew.frame.size.width value is nowhere near the width of the cell frame itself.
For example, in the table I am constructing, I can achieve my desired result by subclassing UITableViewCell and creating a UILabel with a manually determined width (through just trial and error) by:
CGRectMake(10, 12, 397, self.contentView.frame.size.height);
But it's that 397 number that's vexing me. I want a way to programmatically determine what it should be for any width table or style. This should be a simple process by just determining the width of the entire frame of the cell and then subtracting 10 or 20 so the UILabel's edges don't actually touch the edge of the cell.
However, if I set the tableViewStyle to UITableViewStyleDefault and then try:
NSLog(#"Width: %f", self.contentView.frame.size.width);
I get 320. If I set the style to any of the other three styles, the returned number is 302. Even the 320 number isn't anywhere near the width of the cell frame (as with my manually determined number of 397).
What value do I need to access that will return the entire width of the cell's drawing frame? I'm sure, as with most vexing problems, the solution will make me want to slap myself on the forehead, but I'm to the point where I'm ready for it now.
EDIT for more info:
One clarification to anyone interested. This question of mine pertains primarily to a Grouped style table. For a plain style, the answer to my question above can be determined simply in the cellForRowAtIndexPath method by:
CGFloat cellWidth = [tableView rectForRowAtIndexPath:indexPath].size.width;
The problem I'm having is that the rectForRowAtIndexPath method returns the width of the frame in which the cell is drawn, which is fine for a plain style table since the cell width is the entire width of the frame. However, in a grouped table, the width of the cell is less than the width of the frame in which it is drawn, so this method will return a number that is quite a bit wider than the width of the cell. It's possible that the width of the cell in a grouped table style is a fixed number less than the width of the table frame, so this might be the way to solve the problem. I'll investigate that and answer my own question here if that's the case.
I have determined my own answer, and I hope it helps anyone faced with the same issue. The calculation of the margin of a grouped tableView I found on this StackOverflow answer.
This code will provide a label within a tableView cell that spans the cell with a margin between the two edges of the cell, and centered vertically within the cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *label;
CGFloat groupedStyleMarginWidth, tableViewWidth;
UIFont *labelFont = [UIFont boldSystemFontOfSize:17.0]; // Set to whatever you like
NSString *labelText = #"Test String";
// Calculate the margin between the cell frame and the tableView
// frame in a grouped table view style.
tableViewWidth = tableView.frame.size.width;
if (tableView.style == UITableViewStyleGrouped) {
if (tableViewWidth > 20)
groupedStyleMarginWidth = (tableViewWidth < 400) ? 10 : MAX(31, MIN(45, tableViewWidth*0.06));
else
groupedStyleMarginWidth = tableViewWidth - 10;
}
else
groupedStyleMarginWidth = 0.0;
if (cell == nil) {
CGRect tableViewRect;
CGRect labelRect;
CGFloat x, y, w, h, labelMargin;
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Retrieve the rect of the table view.
tableViewRect = [tableView rectForRowAtIndexPath:indexPath];
// Set whatever margin around the label you prefer.
labelMargin = 10;
// Determine rect values for the label.
x = tableRect.origin.x + labelMargin;
// Calculate width of label
w = tableRect.size.width - (groupedStyleMargin * 2) - (labelMargin * 2);
// Calculate height of table based on font set earlier.
h = [labelText sizeWithFont:font].height;
// Calculate y position for the label text baseline to center
// vertically within the cell.
y = (tableRect.origin.y / 2) - (h / 4);
labelRect = CGRectMake(x, y, w, h);
label = [[UILabel alloc] initWithFrame:labelRect];
label.text = labelText;
label.tag = 0;
[cell.contentView addSubview:stepLabel];
[label release];
}
else {
label = (UILabel *)[cell viewWithTag:0];
}
Sounds like this would best be handled by auto layout constraints nowadays.