Dynamically size cell based on content iOS - ios

I have a custom cell shown in attachment:
I am using a UIWebView to display tweet text. Some of the tweets are short and I want to resize the web view, move up the Time Since, and then finally resize the cell. I know how to resize the web view, but don't know how to figure out how to move the time since and resize the cell.
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSFetchedResultsController *fetchedResultsController = nil;
if (self.tweetsSegmentedControl.selectedSegmentIndex == REPORTERS_SELECTED_INDEX)
{
fetchedResultsController = self.reportersFetchedResultsController;
}
else if (self.tweetsSegmentedControl.selectedSegmentIndex == PLAYERS_SELECTED_INDEX)
{
fetchedResultsController = self.playersFetchedResultsController;
}
Tweet *tweet = [fetchedResultsController objectAtIndexPath:indexPath];
//Calcaulate height of box, instead of return a fixed number
return 170;
}

I know how to resize the web view
Don't. Use autosizing to stretch the UIWebView with height of the cell.
how to move the time since
Don't. Use autosizing to pin Time Since to the bottom of the cell.
resize the cell
Use -tableView:heightForRowAtIndexPath:
Update
The way I did this before is to set a known size for the flexible view (for you the web view) in the prototype cell and set a known size for the prototype cell. In this case we'll say the web view is kPrototypeViewHeight and the prototype is kPrototypeCellHeight.
In the table view controller:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIWebView *webView = … // Whatever you need to do to get the web view
CGFloat webViewHeight = webView.frame.size.height;
return kPrototypeCellHeight - kPrototypeViewHeight + webViewHeight;
}
Note: This will be done before -tableView:cellForRowAtIndexPath: is called. So you need to know your size before you have to draw yourself.
Note 2: Because you are changing the size of webView yourself, you will not want it autosized.
Note 3: You will be redering each web view in your table to calculate your height. My guess is scrolling will be very slow.
Hope that helps.

Related

Explicitly set row height for some rows but use estimatedRowHeight for others

I have a UITableViewCell which contains a UIWebView as a subview. The web view fills the entire cell. I am using estimatedRowHeight to calculate the row height. However, at the time the table view is built, the cell has no height because the web view has not loaded it's content, therefore the cell has no content. Because of this, estimatedRowHeight returns 44 instead of the correct height of the web view content.
Does anyone know how I can correctly calculate the height of a row when the content is not immediately set? Is there a way to estimate the height of some cells and explicitly set the heigh of other cells, in the same table view?
This is how I am using estimatedRowHeight:
self.tableView.estimatedRowHeight = 200;
self.tableView.rowHeight = UITableViewAutomaticDimension;
I am not using the delegate method. I have tried it, but it does not change the result. The cell I am using has a xib which also uses Auto Layout constraints. To be clear, the cell does appear and the web view does get added to the cell. The problem is that the height of the cell is not big enough to show the entire web view. The web view loads an HTML embed code for an audio player.
I did some fiddling around and found out that you can use UITableViewAutomaticDimension in the following way:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
TableSection *tableSection = (self.tableModel.sections)[indexPath.section];
if (tableSection.sectionType == TableSectionTypeWebView)
{
return 120;
}
else
{
return UITableViewAutomaticDimension;
}
}
This basically says, use a height of 120 for any WebView sections but for everything else I want you to figure out the height. I am using a my own custom table model here (i.e. TableSection, sectionType, etc...)
I had to add self.tableView.estimatedRowHeight = 200; to my init method for that to work.
Now I can provide an estimated row height but also explicitly set a row height for some sections, or even some rows if I wanted.
I haven't seen any documentation for this, but I tested it with variable length strings and it held up just fine.
You make your class a UIWebViewDelegate and then in and set your class as a delegate to every single UIWebView in your UITableViewCell
-(void)webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
frame.size.height = 1;
aWebView.frame = frame;
//Asks the view to calculate and return the size that best fits //its subviews.
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
Now you can get the height of the UIWebView and set it to the rows height, because the following method will be called again once a 'beginUpdates' is invoked
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath {
return _webView.frame.size.height;
}
Hope This helps

How to Apple tableView cell height based on textview size for selected cells?

As you can see on the image below I have a Row that shows the Bio and another the Experience both are textviews inside a Tablecell. What i need is change the size of the cell based on the size of the textview. for this 2 fields based on a String lengh.
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 5) {
return bio_text.contentSize.height +10; //Not dynamic
}
if (indexPath.row == 6) {
return bio_text.contentSize.height +10; //Not dynamic
}
}
You know how tall a UITextView is because every UITextview has a ".contentSize" property, which means you have that text view's height.
If you're going to display all of the text in a text view in a particular table cell, then it's just a matter of returning the text view height. If you're need to scroll the text view (because there's simply too much content to comfortably display in a table cell), then you need to get the frame height of the text view and use that.

How do I change the height of a table cell that has already loaded?

Currently I have webviews loading in customized uitableview cells. The problem is the web views have variable sizes. In webViewDidFinishLoad I am able to set the size of the web view based on the actual size of the html document just fine. My problem is the table cells which have already had their height set in heightForRowAtIndexPath before the web views having finished loading. How can I change the height of a table cell after it has already been loaded?
Ideally I feel like I should be able to use some line of code like this.
cellW.frame = cellW.cellWebView.frame;
However I don't seem to have access to cell information in heightForRowAtIndexPath. I've felt like I've explained the situation fairly well, but any code you think I should post I can put up here. I've tried a lot things (so there comments and failed attempts at this everywhere), but the main issue is I can't seem to access cell information in the right places such as heightForRowAtIndexPath. If I could even set cell information somehow in webViewDidFinishLoad, I could simply set the frame of the cell where I am also setting the frame size of the web view.
Below is the setup for my table cell subclass.
#import <UIKit/UIKit.h>
#import "DefinitionsAndConstants.h"
#interface UITableViewCellWebView : UITableViewCell
{
UIWebView *cellWebView;
}
#property (nonatomic,retain) UIWebView *cellWebView;
#end
Here is what I have tried last trying to use part Gavin's code. But of course there is no way to set the table cell now that I've gotten out because cellForRowAtIndexPath is not assignable.
-(void)webViewDidFinishLoad:(UIWebView *)webViews {
[webViews stringByEvaluatingJavaScriptFromString:#"twitterfy()"];
[webViews stringByEvaluatingJavaScriptFromString:#"document.getElementById('tweettext').innerHTML=tweet"];
NSString* h = [webViews stringByEvaluatingJavaScriptFromString:#"getDocHeightMax()"];
int height = [h intValue];
webViews.frame = CGRectMake(0.0f, 0.0f, 320.0f, height);
NSString* i = [webViews stringByEvaluatingJavaScriptFromString:#"return indexPath"];
int ii = [i intValue];
NSIndexPath* ip = [NSIndexPath indexPathForRow:ii inSection:0];
UITableViewCellWebView *tableCell = (UITableViewCellWebView *)[self.tableView cellForRowAtIndexPath:ip];
if (tableCell) {
tableCell.frame = webViews.frame;
}
NSLog(#"Got height from webview %d", height);
}
I would set up a mutable array to read heights from. In viewDidLoad, you'll have to assign some starting values (probably just a bunch of #"44.0", it doesn't really matter, it won't be used for much yet). In your heightForRowAtIndexPath:, just return the number from that array. Then in webViewDidFinishLoad, replace the heights in the array with the height you actually need for that cell (the NSString *h in the code you posted, I believe), and call reloadData on your table view. reloadData will hit heightForRowAtIndexPath:, which will look at the heights array, which now has the actual height needed for that cell, so everything should be shiny.
You should be able to do something like this for your heightForRowAtIndexPath method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyTableViewCell *tableCell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
if (tableCell) {
return tableCell.cellWebView.frame.size.height;
}
return 44;
}
This way, if the table cell is visible, it'll set the height according to the height of the embedded web view, otherwise it'll use a default height. In order to make the table view refresh the height of the cell, you'll have to call the following once the web view is sized properly:
[self.tableView beginUpdates];
[self.tableView endUpdates];
That won't make it reload the cells, which could screw things up for you, it'll just make it check the heights again, and the cell height will animate to the new height.

How to increase the height of custom cell in UITableView

I have a tableview that fill with custom cells,, Now I want to increase the width of the cell,I increased the cell height of UITableview. But the problem is still same. Any one know how to increase the height of custom cell in UITableView.
Thanks,
If your cell heights vary, implement the following delegate:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44.0; // edit this return value to your liking
}
If they don't, merely set the rowHeight property of your table view instance to whatever height you want all of your cells to be. This answer does a good job of explaining why.

resizing a UITableViewCell frame issue

I am trying to resize my UITableViewCell's frame via:
[cell setFrame:CGRectMake(cell.frame.origin.x,
cell.frame.origin.y,
cell.frame.size.width,
cell.frame.size.height+25)];
however, it's not resizing after I do this... why is this?
This is weird as if I add a UIToolBar into the cell, it resizes but when I am adding a UIView, it doesn't:
[cell.contentView addSubview:sideSwipeView];
Here's the long and short of it:
Your cell width is determined by the width of the tableview it's in.
[EDIT: If it's a grouped table view, the cell is 20 - 60 pixels narrower than the tableview width, depending if you're using an iPhone, or an iPad.]
Your cell height is determined by the heightForRowAtIndexPath method.
If you're manually setting the cell's frame, it's going to be useless except when you're using a subclassed cell where you want to add subviews based on the cell's dimensions.
Even in this case, it's recommended to get the cell's frame from the tableview by using rectForRowAtIndexPath:(NSIndexPath*)indexPath method and then setting that frame as the cell's frame (after setting the frame's origin Y as 0).
I'm not quite sure about the UIToolBar, but your subview's frame won't change on changing the cell frame.
Maybe if you could tell us what you're trying to achieve, we can suggest a solution for you?
--------------------EDIT--------------------
So you need to dynamically add a subview to a cell on tapping it and resize it's height according to the new subview. This is gonna get hairy so here goes:
In your .h file declare:
BOOL subviewAdded;
In your .m file, in the init, do:
subviewAdded = NO;
Let's assume that you want the cell's height to be 50 without the subview and 100 with the subview. Accordingly, your heightForRow method should be:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return (subviewAdded?100.0f:50.0f);
}
This means that initially since subviewAdded is NO, all your cells will have the smaller height.
Now, to add a subview to a cell on tapping it, and to change it's height dynamically, do this in your didSelectRow method:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Get the cell at this indexPath
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if(subviewAdded)
{
subviewAdded = NO;
for(int i = 0; i < [thisCell.contentView.subviews count]; i++)
{
UIView *thisSubview = [thisCell.contentView.subviews objectAtIndex:i];
[thisSubview removeFromSuperview];
}
}
else
{
UIView *someView = [[UIView alloc] initWithFrame:someFrame];
[thisCell.contentView addSubview:someView];
[someView release];
subviewAdded = YES;
}
NSMutableArray *array = [NSMutableArray array];
[array addObject:indexPath];
[tableView reloadRowsAtIndexPaths:array
withRowAnimation:UITableViewRowAnimationFade];
}
So what's going to happen here is you're adding a subview to this cell you've tapped. Reloading this cell will call heightForRowAtIndexPath and do a nice little fade animation and change your tableview heights.
IMPORTANT: Ideally, you should maintain an array of NSNumbers with boolean values. The array size should be the same size as the number of tableview cells you have.
In heightForRow, you would then check against this array instead of using a single boolean for the whole tableView. This would ensure that you could have different heights for different cells.
That would look something like:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL thisBool = (BOOL)[[booleanArray objectAtIndex:indexPath.row] boolValue];
return (thisBool?100.0f:50.0f);
}
I didn't post all that code here since it's implied and what I've posted should put you well on your way to doing the boolean array thing.
Anyway, there you are. I just tested this code myself so it works :)
If you want to increase the height of your cell based on some parameter eg. text, image,
you must implement the heightForRowAtIndexPath method of UITableViewDelegate in your code.
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath

Resources