UITableView: Changing one cell's height constraint after table is constructed? - ios

I might be wanting a strange thing, but the task is to stretch last cell in UITableView to fill the rest space. So in case table will only have few cells, then the last one will match it's height to the rest until screen bottom.
To achieve this, I included height constraint in the last cell's xib.
I can calculate proper height and set the constant, but it does not matter what I do afterwards - setNeedsDisplay(), setNeedsLayout(), reloadData(), reloadRowsAtIndexPaths() etc. - the cell height is not changed.
Only when I call the update code second time, layout is adjusted.
Any hints how to force update the cell immediately?

You need to have the following implemented (viewDidLoad is fine).
var estimatedRowHeight = 80 (for example)
// Set automatic dimension on row height.
tableView.rowHeight = UITableViewAutomaticDimension
// Set estimated row height.
tableView.estimatedRowHeight = estimatedRowHeight
Remove the height constraint and then call your resize with either the reloadData, or reloadRowsAtIndexPaths().

Did you try the following method? Where you check for the last indexPath.row and put a different height that you calculate.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

Related

UI Tableview cell not expanding when text is added at the runtime

I am using table view for my chat application, in which the chat responses are added either one of two textviews as shown in the image. The thing is whenever I add a large text, the cell height does not expand to show the full text. It only shows the last line of that text. I am using objective-c. Is there a way to solve this ?. I do not want to completely create a new view like the questions asked before, I want changes to this specific view.
First, you need to use Label and set top and bottom constraint between label and contentView cell.
In order to allow the self-sizing cell mechanism to work, you must set the rowHeight property on the table view to the constant UITableViewAutomaticDimension. Then, you simply need to enable row height estimation by setting the table view's estimatedRowHeight property to a nonzero value, for example:
_tableView.estimatedRowHeight = 44.0; // set to whatever your "average" cell height is
_tableView.rowHeight = UITableViewAutomaticDimension;
You need to defined self-sizing cell like this.
tableCountries.estimatedRowHeight = 100.0;
tableCountries.rowHeight = UITableViewAutomaticDimension;
Make sure you have a proper constraint. You can have a constraint like this.
In the below label you need to set your textView top position. That's why when the below label expands it automatically expand label and text view will push to bottom.
I think your cell is not gettings its height because of textview scrolling maybe that will help:-
Use UITableViewAutomaticDimension and for that your tableview cell content should justify both top-bottom leading and trailing constraints to calculate cell height.
Set scrollEnabled to "false" for your textview.
With everything on the place your cell will get its height for sure.
you can do it in many ways :
1) You can set dynamic height of cell using UITableViewAutomaticDimension.
You need to set proper constraints in storyboard like setting top and bottom.
in ViewDidLoad add below :
tblView.rowHeight = UITableViewAutomaticDimension
tblView.estimatedRowHeight = 100
and in tableView cell's height method :
return UITableViewAutomaticDimension
2) Find text's height dynamically using below function :
let width = 100.0 \\your text label's width you gave
var height = chatMsg.text?.height(withConstrainedWidth: width, font: chatMsg.font!)
using above code you can find the height of your text. and you can use it dynamically
3) there are many code available to use for chat application in which you just need to pass text/image, and it will handle everything else.
Link : https://github.com/kerry/iMessageBubble
Add these two delegate methods:
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
Create Custom UITableViewCell with Three UILabel like lbl1,lbl2,lbl3.
Add the AutoLayout Constraints to lbl1 left, right, top and bottom. With fixed height (30).
Then set same constraints to remaining two Labels.
Here is main things:
1.select lbl1 heigh and double click on height constraint and set >=30
Do same things with lbl2 and lbl3.
Final step is:
Select lbl2 top constraints, change the constraints property like <=8.
Do same things with lbl3, that's it we are done all.
thanks..

Update constraint in UITableVeiwCell

I have a view in UITableViewCell , height of view can be 90 or 60 depending upon condition. I made a IBOutlet to height constraint and updating its value in cellForRow method , but getting layout waring in logs. Do I need to call any method like layoutIfNeeded in cellForRow after updating the constant ?
UITableViewDelegate has this method, that determines the height of cell.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
Implement this method and depending on you condition return the required height.
Apart from this you need to make sure that your constraints don't break, when supplied with this height.
So here are the steps,
Drag drop a UITableViewCell from 'Object Library'.
Select the cell and from 'Size Inspector', set the 'Row Height' to 60.
Set you subview and their contstraints. Don't put a height constraints on the 'Content View' of the table view cell.
Implement the above mentioned method and return height as 60.
If this same cell can have height 90, set 90 in step two, four and make sure constraints don't break when you set 90 in step two.

Changing UILabel text length in UITableViewCell with dynamic height does not resize it correctly

I have an UITableViewCell with UILabel which correctly resizes its height according to text length. To accomplish this I have correctly set AutoLayout constraints and specified
tableView.rowHeight = UITableViewAutomaticDimension
The problem I am having is when the test of the UILabel gets longer after pressing a UIButton - READ MORE, in the cell itself. I programmatically add text to the UILabel and I expect the cell height to grow. I have added:
self.layoutIfNeeded()
self.updateConstraints()
in the cell, but it is not working. Cell stays same height.
I have also forced a reload of the cell row in the delegate UIViewController
but it is not working either. Am I missing something basic here?
EDIT: The question differ from other similar questions, because I'd like the answer to avoid having to calculate the height manually. Since AutoLayout is perfectly able to calculate correct dynamic height at first load, I guess there should be a way to make it redraw the cell once the text in the label gets longer, without the need of performing manual calculation to estimate row height.
Get the Label height dynamically and set the tableviewcell height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Calculate the Label height and add it to default height of the cell
}
I have found a solution that works, after updating the UILabel content I am calling:
UIView.animateWithDuration(0.3) {
cell.contentView.layoutIfNeeded()
}
To update cell constraints. And then to resize the cell height:
tableView.beginUpdates()
tableView.endUpdates()
I will wait to accept this answer to see if someone else will answer a more elegant solution though.

Cell content not showing up if heightForRowAtIndexPath is implemented

I'm using iOS 9.2 and XCode 7.2.
I have a basic UITableView object in which i add different kind of UITableViewCell subclasses.
With one of them, when i set manually the height overriding the method heightForRowAtIndexPath, i don't get any content on the cell.
If i return -1 as height(the default value for the UITable row height), i get my cell showing up correctly. The thing is that i do need a different height for this row because the content is quite big.
here is the code for heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
MenuItem *menuItem = [menuManager menuItemAtIndex:indexPath.row];
if ([menuItem type] == MenuItemTypeEditorHeader) {
return 100;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
MenuItem is a class containing the specific menu object' informations, such as the type. The result is that the cell is showed up at the correct height, but it's empty.
Its not advisable to use heightForRowAtIndexPath anymore - thats old-school. Instead, do this :
Set up autolayout constraints in your cell (if you dont know how to - you need to, its not something you can avoid anymore!)
Create an estimatedRowHeight for autolayout to use, on the tableView. You can set it in the nib/storyboard or programmatically, in viewDidLoad for eg, like this :
self.tableview.estimatedRowHeight = 68.0;
Set your tableview to use 'automatic dimension', like this :
self.tableview.rowHeight = UITableViewAutomaticDimension;
And thats it. If you do these things, then your cells will vary in height according to their constraints. So if one of your subclasses has a height of 150px due to its constraints, that will work perfectly next to another subclass that has a height of 50px. You can also vary the height of a cell dynamically depending on the contents of the cell, for eg when you have labels that expand using 'greater than or equal to' constraints. Also - simply omit the 'heightForRowAtIndexPath' method, you dont need to implement it at all.
Are you calling tableView.reloadData() ?
print the length of menu objects before you call tableView.reloadData().
HeightForRowAtIndexPath just returns height of a row. So may be problem in cellForRowAtIndexPath.

Problems With Dynamically Resizing UITableViewCells

I'm attempting to dynamically resize a custom UITableViewCell to fit an attributed string's content. This is the result:
When I initialize my tableView I do the following:
self.chatsTableView.estimatedRowHeight = 72.0;
self.chatsTableView.rowHeight = UITableViewAutomaticDimension;
I also implemented the following method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
As you can see it is resizing my height (the smaller allowed is 72). However, for some reason it's creating a weird effect. I'm using storyboard, and auto layout.
Move it to the - (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath method.
You have to set estimatedRowHeight to UITableViewAutomaticDimension as well.
It should work only with the two properties you set , the row height and the estimated row height.
first try to remove the delegate method.
If the table "Jumps" a little when you scroll (because of a bug) then also implement the two delegate methods, heightForRow and estimatedHeightForRow and return the same values as you set in the properties , estimatedRowHeight = 72 and rowHeight = UITableViewAutomaticDimension.
If it's still doesn't work then I would double check the constraints.
For iOS 8+
Set up cell constraints. Make sure that ALL subviews that affects cell height are vertical connected. In this case: top edge of top label is pinned to superview's top AND top labels bottom edge is pinned to bottom's label top edge AND bottom's label bottom edge is pinned to superview's bottom. Vertical constraints chain have to be closed. In your case it looks like a bottom edge of bottom label is not pinned to contentViews bottom edge.
When dequeuing cell for reuse always use
dequeueReusableCellWithIdentifier:forIndexPath: not a shorter version without indexpath specified.
Set self.tableView.rowHeight = UITableViewAutomaticDimension;
Set self.tableView.estimatedRowHeight = 50.0;. This step is optional but helps table view proper manage things like scroll indicators etc.
Will work :)

Resources