how to set UITextView height dynamically inside a custom UITableViewCell with autolayout - ios

I have UITableView, every tableViewCell is custom. Inside my customTableViewCell is a UITextView, TextViews frame is pin or same as its superView which is tableViewCell.
How Am I gonna set the UITableViewCell height dynamically that is proportional to the TextViews size which will also depends to content text that I get from internet.
(sample prototype)
// this is how I manipulate every cell height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
// How do I set the height here, whats the best approach for this. with autolayout BTW
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// I initialize every cell here with my ArrayContainer, nothing much to refer here.
}

Follow this answer: Link reference
Add a height constraint to your UITextView and create an outlet to your custom cell class.
Use sizeThatFits: on UITextView to get the size that fits the content and set this value as a constant of the constraint described in 2. Do this in tableView:heightForRowAtIndexPath:.
One caveat is that if there're many cells (hundreds or thousands) then you may hit performance issues.

Primarily get the texts as NSArray and Assign it into the UITextView's as temporary, So that you will get the Height of Cell :
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGRect frame;
// set the height here, According to the NSArray of text
if(textView || section )
UITextView *tempTxtView = [[UITextView alloc] init];
tempTxtView.text = // Add the Text of index according to the Section
// Fit the UITextView to the Content
frame = tempTxtView.frame;
frame.size.height = tempTxtView.contentSize.height;
tempTxtView.frame = frame;
}
return frame.size.height;
}
Once got the UITableViewCell height : Then No need to worry about this, right ?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// I initialize every cell here with my ArrayContainer, nothing much to refer here.
self.textView = [[UItextView alloc] initWithFrame:CGRectMake(cell.frame.origin.x +20, cell.frame.origin.y +10, cell.frame.size.width - 20, cell.frame.size.height - 20)];
// ....... Do further with the NSArray of Text
}
Note : I Haven't Tested, Its just a thought. Hope this will help you

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGSize titlesize = [TxtValue.text sizeWithFont:[UIFont fontWithName:appdel.strFont size:25.0f] constrainedToSize:CGSizeMake(300, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping]; /// ----- -set width as per your requirement inplace of 300
return titlesize.height+10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
}

Related

How to make the height of custom UITableViewCell dynamic for each cell made in the UITableView?

I have to make the height of UITableViewCell dynamic with respect to number of images in the cell.
Add following lines of code in your viewDidLoad():
tableView.estimatedRowHeight = 200.0
tableView.rowHeight = UITableViewAutomaticDimension
where estimatedRowHeight is the maximum height you want to set for UITableViewCell.
Also, add this delegate method and return UITableViewAutomaticDimension:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
set the UITableView's rowHight property to UITableViewAutomaticDimension and set the estimated row height to what the most common height is. Then in your layout of the cell make sure there are constraints between all of the visual elements vertically and the cell will be laid out properly. The vertical constraints should be something like:
V:|-(5)-[imageOne]-[imageTwo]-|
Where "|" is the cell's content view.
Implement the delegate method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath (NSIndexPath *)indexPath
#interface yourController : UIViewController<UITableViewDelegate,UITableViewDataSource>
set delegate in view did load
- (void)viewDidLoad {
[super viewDidLoad];
tableview.delegate=self;
tableview.dataSource=self;
}
now method of height of table view cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 40;//your value
}
in cell
- (CGFloat)cellHeight {
[self layoutIfNeeded];
return CGRectGetMaxY(_imageview.frame) + 10;
}
the imageView is the last view in cell. It only needs maxY of the lastView
in controller
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
OJTopicRootCell *cell = (OJTopicRootCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath];
return cell.cellHeight;
}
Use the estimatedHeight methods to quickly calcuate guessed values which will allow for fast load times of the table.
If these methods are implemented, the above -tableView:heightForXXX calls will be deferred until views are ready to be displayed, so more expensive logic can be placed there.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0);
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);

How to create a UITextField with n number of lines inside a UITableview

How to create a UITextField with n number of lines inside a UITableview.Each cell may contain 1 or more number of heights, So that UITableView will have different cell heights each cell, is it possible to make it?
You can use this functions to calculate dynamic height.
It return the hight of your textfiled's dynamic height based on your width.
-(CGFloat)getDynamicHeightOfLabelWithFont:(UIFont *)font withText:(NSString *)text withFrame:(CGRect)initialFrame
{
UITextField *txtDummy = [[UITextField alloc] initWithFrame:initialFrame];
txtDummy.font = font;
txtDummy.text = text;
txtDummy.borderStyle = UITextBorderStyleNone;
CGRect dummyFrame = initialFrame;
dummyFrame.size = [txtDummy sizeThatFits:initialFrame.size];
return dummyFrame.size.height;
}
You need to call that in 2 places
On -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
on - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

How to change each UITableViewCell height dynamically?

I'm working on application where i show user comment in UILable and UILable have sizetofit property. i want to change cell height according to UILable height.
My Question is how i change cell height for example first cell height may be 50, second Cell height may be 100 and so on.
For dynamic height of UITableViewCell you have to do below things
Fulfill all constraint requirement in UITableViewCell
Tell your TableView to dynamically layout Height of every Cell with below code
- (void)viewDidLoad {
[super viewDidLoad];
// two magic lines
tableView.estimatedRowHeight = 89
tableView.rowHeight = UITableView.automaticDimension
}
With just two lines of code, you instruct the table view to calculate the cell’s size matching its content and render it dynamically. This self sizing cell feature should save you tons of code and time. You’re gonna love it.
Hope this helps you by tableview methods:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
You can use this method for increase UITableViewCell height dynamically (No AutoLayout)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSMutableAttributedString *strName = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"%#",strItemName]];
[strName addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, strItemName.length)];
CGSize sizeItemName = CGRectIntegral([strName boundingRectWithSize:CGSizeMake(130, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil]).size;
int padding = 5;
//your default cell height for ex 55
if (sizeItemName.height < 55)
{
sizeItemName.height = 55;
}
return sizeItemName.height + padding;
}
In your heightForRowAtIndexPath, calculate the dynamic height based on the related cell data.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *data = [self.dataSource objectAtIndex:indexPath.row];
return [MyTableViewCell heightForData:data];
}
Then in your MyTabLeViewCell, write a function as below, let us say the data has the "content" which is the fact for dynamic height. And your tableViewCell defined a UILabel called contentLabel with CONTENT_LABEL_WIDTH
+(CGFloat) heightForData : (NSDictionary *)data{
self.contentLabel.text = [data objectForKey:#"content"];
CGSize contentLabelSize = [self.contentLabel sizeThatFits:CGSizeMake(CONTENT_LABEL_WIDTH, CGFLOAT_MAX)];
return contentLabelSize.height;
//If you want to have a minimum cell height no matter how small your content is, you can use below fmaxf with a pre-defined CELL_MIN_HEIGHT value.
// return fmaxf(CELL_MIN_HEIGHT, height);
}

Resize UILabell in iOS 7.1 in Custom Cell

I have a table view with custom cells. I'm using Xcode 5.1 and iOS 7.1. I would like to adjust a UILabel height based on the length of a string and also dynamically adjust the height of the cell to fit the label.
In
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
cell.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
cell.titleLabel.numberOfLines = 0;
[cell.titleLabel sizeToFit];
Some seem to resize correctly, others don't. As for the height of the cell, I can't get it to update based on the height of the label.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [self dynamicHeightAtIndexPath:indexPath]+20;
}
-(CGFloat)dynamicHeightAtIndexPath:(NSIndexPath *)indexPath
{
CGSize maximumSize = CGSizeMake(275, 9999);
UIFont *myFont = [UIFont fontWithName:#"MyriadPro" size:11];
CGSize stringsize = [[self.array objectAtIndex:indexPath.row] sizeWithFont:myFont
constrainedToSize:maximumSize
lineBreakMode:NSLineBreakByWordWrapping];
return stringsize.height;
}
The cell's height is determined solely by the value you return from tableView:heightForRowAtIndexPath:. This is a <UITableViewDelegate> method.
If you want to have the cell height be dynamic, you would need to perform a calculation in tableView:heightForRowAtIndexPath: based on the particular string that appears at that index path.
If you plan on doing a lot of scrolling, this calculation could get expensive and cause performance issues. If that is the case, I'd recommend caching the computed heights or computing them all at once and storing them in an array parallel with your data source.

How to resize UITableViewCell to fit its content?

I have a UITableview with multiple reusable TableViewCells.
In one cell I have a UITextView, that resizes itself to fit its content. Now I "just" have to resize the contentView of the TableViewCell, so I can read the while text. I already tried:
cell2.contentView.bounds.size.height = cell2.discriptionTextView.bounds.size.height;
Or:
cell2.contentView.frame = CGRectMake(0, cell2.discriptionTextView.bounds.origin.y,
cell2.discriptionTextView.bounds.size.width,
cell2.discriptionTextView.bounds.size.height);
In the method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath {}
But it won't work.
Does anyone know how to do this?
New code:
#implementation AppDetail
CGFloat height;
…
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{…
cell2.TextView.text = self.text;
[cell2.TextView sizeToFit];
height = CGRectGetHeight(cell2.TextView.bounds);
…
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
return 143;
}
if (indexPath.row == 1) {
return height;
}
return 0;
}
You can only resize a UITableViewCell in tableView:heightForRowAtIndexPath: delegate method.
You have to estimate what the size of the text will be when that method is called for every row when the tableView is loaded.
This is what I did to solve the problem.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * yourText = self.myArrayWithTextInIt[indexPath.row]; // or however you are getting the text
return additionalSpaceNeeded + [self heightForText:yourText];
}
-(CGFloat)heightForText:(NSString *)text
{
NSInteger MAX_HEIGHT = 2000;
UITextView * textView = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, WIDTH_OF_TEXTVIEW, MAX_HEIGHT)];
textView.text = text;
textView.font = // your font
[textView sizeToFit];
return textView.frame.size.height;
}
EDIT
While I used this solution for a while, I found a more optimal one that I would recommend using as it doesn't require allocating an entire textView in order to work, and can handle text greater than 2000.
-(CGFloat)heightForTextViewRectWithWidth:(CGFloat)width andText:(NSString *)text
{
UIFont * font = [UIFont systemFontOfSize:12.0f];
// this returns us the size of the text for a rect but assumes 0, 0 origin
CGSize size = [text sizeWithAttributes:#{NSFontAttributeName: font}];
// so we calculate the area
CGFloat area = size.height * size.width;
CGFloat buffer = whateverExtraBufferYouNeed.0f;
// and then return the new height which is the area divided by the width
// Basically area = h * w
// area / width = h
// for w we use the width of the actual text view
return floor(area/width) + buffer;
}
As #Rob Norback said, There is something called UITableViewAutomaticDimension.
For Swift, The easiest way to resize content from UITableViewCell on the fly is to just add this.
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Here's an updated version for iOS 7+ that is cleaner (no extra method)
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIFont * font = [UIFont systemFontOfSize:15.0f];
NSString *text = [getYourTextArray objectAtIndex:indexPath.row];
CGFloat height = [text boundingRectWithSize:CGSizeMake(self.tableView.frame.size.width, maxHeight) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:#{NSFontAttributeName: font} context:nil].size.height;
return height + additionalHeightBuffer;
}
You need you implement heightForRowAtIndexPath.
Say that the data that is to be displayed in the textView is stored in a NSArray.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat cellheight = 30; //assuming that your TextView's origin.y is 30 and TextView is the last UI element in your cell
NSString *text = (NSString *)[textArray objectAtIndex:indexpath.row];
UIFont *font = [UIFont systemFontOfSize:14];// The font should be the same as that of your textView
CGSize constraintSize = CGSizeMake(maxWidth, CGFLOAT_MAX);// maxWidth = max width for the textView
CGSize size = [text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
cellHeight += size.height; //you can also add a cell padding if you want some space below textView
}
I favor this solution of Jure
First, set constraints of textview to be pinned with its superview (cell's contentView in this case).
Disable textView.scrollEnabled
Set
table.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = 44;
If finally, your code not works, then use this instead
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 44;
}
Implement UITextViewDelegate like this:
- (void)textViewDidChange:(UITextView *)textView {
CGPoint currentOffset = self.tableView.contentOffset;
[UIView setAnimationsEnabled:NO];
[self.tableView beginUpdates];
[self.tableView endUpdates];
[UIView setAnimationsEnabled:YES];
[self.tableView setContentOffset:currentOffset animated:NO];
}
This thread has been quite a while, but in iOS 8 UITableViewAutomaticDimension was introduced. You have to set constraints from the top to the bottom of the cell like a scroll view to make this work. But after that, just add the following code to viewDidLoad():
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 122.0
Make sure your estimated height is as close as possible to the real thing otherwise you'll get some buggy scrolling.
Adding these two methods to the ViewController with UITableViewAutomaticDimension should do the trick. It has worked for me when embedding a UITextView inside of a UITableViewCell with variable length text.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
In case of UILabel subview in the UITableViewCell, I accomplished auto resize of the label just by setting the label's constraints (using storyboard, Xcode 8.3.2).
This is working since apparently the label's and the cell's default behavior is sizeToFit. Same should work for UITextView as well.

Resources