How to set UITableViewCell height depending on screen size - ios

I download data from the web, it consists of text and image. I'm putting this data into UITableView, and I want image to be a background of UITableViewCell.
All the images has the same resolution 620x350.
All the iPhones have different screen sizes so I need to scale image's width and height depending on screen size,and also do this to UITableViewCell.
What are the best solutions?
Thank you.

The BEST and clean solution, it is just playing with the height of the cell, letting the image be resized automatically by Autolayout.
It is easy:
In your cell, add an UIImageView and set the size you want to have when the cell has the actual height;
Set as constraints of this UIImageView, at least top, bottom and one of the lateral border (right or left); set also the constraints to keep the proportion width/height;
At this point, when the cell grow, the image grow in height, and to keep the proportion (thanks constraint) it is resized the width as well, having ALWAYS the correct and proportioned size.
Now therefore, you have just to write the code for the cell's height:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
static CGFloat cellDefaultHeight = /*the default height of the cell*/;
static CGFloat screenDefaultHeight = /*the default height of the screen i.e. 480 in iPhone 4*/;
CGFloat factor = cellDefaultHeight/screenDefaultHeight
return factor * [UIScreen mainScreen].bounds.size.height;
}
Obviously, set the contentMode of the UIImageView to AspectFill.

Simply use - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat aspectRatio = 350.0f/620.0f;
return aspectRatio * [UIScreen mainScreen].bounds.size.width;// assuming that the image will stretch across the width of the screen
}

You can use the -tableView:heightForRowAtIndexPath: method in HTTableViewDelegate to return the height for each cell. In your case, you will want something like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [UIScreen mainScreen].bounds.size.height;
}

Related

Too much space between cells

I'm having trouble with reducing the spacing between my cells, I want it to be 1 px. Inside my cell I have a stackView which fills my entire cell, both set to 70.
I can accomplish almost what I want by adding negative constrains, but then my cells gets too big, I only want it to be 70. I set the cell to 70 in the custom cell class
self.frame.size.height = 70
And my stackView is set to the very same. I don't see why I get that amount of spacing between my cells?
Please use the below method to adjust the cell height;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}
1) Between 2 cells of table view always has no space
2) You set self.frame.size.height = 70 in your custom cell. But it will be useless ! Try this datasource method
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
3) Please check the height of the white view

table cell height issue iOS?

I have custom table view.I have added 4 views in that
1.ImageView
2.Three labels
Now I want that image should increase in size for multiple devices.For that i have given it below constraints.Proptional height is 176:339
Now in order to increase the height of the image i have increase height of table i used below code.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(!self.customCell)
{
self.customCell = [self.tableview dequeueReusableCellWithIdentifier:#"tableCell"];
}
CGFloat height;
height=self.customCell.img_main.frame.size.height;
height=height+self.customCell.label_one.frame.size.height;
height=height+self.customCell.label_two.frame.size.height;
height=height+self.customCell.label_three.frame.size.height;
height=height+self.customCell.dev_name.frame.size.height;
NSLog(#"height is %f",self.customCell.img_main.frame.size.height);
return height;
}
The heigh of image is always 176 which i set in interface builder for 4 inch screen.
Why the height of both images & table view cell is not increasing ?
This is for your second question, if you want to change the image view's height base on the image it display, i suggest to use Height Constraint instead of Proportional Height Constraint, the calculation will be easier. When you get the image, and know the image size, so you calculate and get the size of the image view, and then update the Height Constrains. Done.
drag the constraint to your cell
update the constraint when image setted
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CustomeCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellId" forIndexPath:indexPath];
cell.image = image;
cell.imageViewHeightConstraint.constant = [self calcuteSizeWithImage:image]; //you need to do the calculation yourself
return cell;
}

How to make the cell height fit the screen

I have a UITableView and there are 10 rows (This is a dynamic table, so more rows will be loaded).
Each cell/row should have the height of the full screen. There are different screen sizes in iOS now.
Therefore i am not able to give a fixed height for cell row as iOS devices have varying heights.
So how can I make a cell height to fit the screen height ?
If your tableView is in a ViewController then you can use this code below:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return CGRectGetHeight(self.view.bounds);
}
Else if your screen covers full screen, then use this
return CGRectGetHeight([[UIScreen mainScreen] bounds]);
Else if your screen contains a Navigation Bar as well, then use
return CGRectGetHeight([[UIScreen mainScreen] bounds] - 64.0f);
Or the Best Solution would be perhaps
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return CGRectGetHeight(tableView.bounds);
}
Edited
Its better to use rowHeight property instead of the delegate. Reason discussed below:
There are performance implications to using
tableView:heightForRowAtIndexPath: instead of rowHeight. Every
time a table view is displayed, it calls
tableView:heightForRowAtIndexPath: on the delegate for each of its
rows, which can result in a significant performance problem with table
views having a large number of rows (approximately 1000 or more).
Thanks to rdelmar
Source
How about this?
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return self.view.frame.size.height-yourTableViewStartingYPosition;
}
If it's full screen it will be return self.view.frame.size.height

how set image set full width and set UIViewContentModeScaleAspectFit?

I want to set a image for UITableviewcell but imageview contentmode is UIViewContentModeScaleAspectFit and also set full width depends on width height of UIIMageView is change,how to do that.
Change your UIIMageView content mode to UIViewContentModeScaleToFill or UIViewContentModeScaleAspectFill
Edited
Use following UITableView's Method
Add you UIImageView Height in NSMutableArray (heightsArray)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [heightsArray objectAtIndex:indexpath.row];
}

The best way to calculate UITableViewCell height without contentView frame

SUMMARY
Given that we don't always know what the frame of a cell or its content view is going to be (due to editing, rotation, accessory views etc.), what is the best way to calculate the height in tableView:heightForRowAtIndexPath: when the cell contains a variable height text field or label?
One of my UITableViewController's contains the following presentation:
UITableViewCell with UITextView.
UITextView should be the same width and height as UITableViewCell.
I created the UITableViewCell subclass, and then and initialized it with UITextView (UITextView is a private field of my UITableViewController)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"TextViewCell";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[BTExpandableTextViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier textView:_notesTextView] autorelease];
}
return cell;
}
I implemented the following method in my UITableViewCell subclass:
- (void)layoutSubviews{
[super layoutSubviews];
CGFloat height = [textView.text sizeWithFont:textView.font constrainedToSize:CGSizeMake(textView.frame.size.width, MAXFLOAT)].height + textView.font.lineHeight;
textView.frame = CGRectMake(0, 0, self.contentView.frame.size.width, (height < textView.font.lineHeight * 4) ? textView.font.lineHeight * 4 : height);
[self.contentView addSubview:textView];
}
and of course i implemented the following UITableViewDataSource method (look! I am using self.view.frame.size.width (but really i need UITableViewCell contentView frame width):
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
CGFloat height = [_notesTextView.text sizeWithFont:_notesTextView.font
constrainedToSize:CGSizeMake(self.view.frame.size.width, MAXFLOAT)].height;
CGFloat groupedCellCap = 20.0;
height += groupedCellCap;
if(height < [BTExpandableTextViewCell minimumTextViewHeightWithFont:_notesTextView.font]){
height = [BTExpandableTextViewCell minimumTextViewHeightWithFont:_notesTextView.font];
}
return height;
}
also I implemented the following method (thats not so important but ill post it anyway, just to explain that cell's height is dynamical, it will shrink or expand after changing text in UITextView)
- (void)textViewDidChange:(UITextView *)textView{
CGFloat height = [_notesTextView.text sizeWithFont:_notesTextView.font
constrainedToSize:CGSizeMake(_notesTextView.frame.size.width, MAXFLOAT)].height;
if(height > _notesTextView.frame.size.height){
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
}
And now, my question is:
After loading view, UITableViewController is calling methods in the following order: (ill remove some, like titleForHeaderInSection and etc for simplification)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
and only then
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Look! I should return the correct UITableViewCell height before cellForRowAtIndexPath!
That means: I don't know UITableViewCell contentView frame. And i can't get it programmatically.
This width can be one of:
iPhone plain table, portrait orientation
iPhone plain table, landscape orientation
iPhone grouped table, portrait orientation
iPhone grouped table, landscape orientation
and the same for the iPad ( another 4 values )
And don't forget that contentView frame can be smaller because of UITableViewCell accessoryType, or because of UITableView editing state. (for example if we have UITableViewCell with multiline UILabel of any height in any editing state and with any accessoryView)
So this problem is fundamental: I just can't get cell contentView frame width for constraining, because I should return this height before cell layouts contentView. (And this is pretty logical, by the way) But this contentView frame really matters.
Of course sometimes I can know this width exactly and "hardcode" it
(for example: UITableViewCellAccessoryDisclosureIndicator has 20 px width, and tableView cannot be in editing state, then I can write self.view.frame.size.width - 20 and the task is done)!
Or sometimes contentView is equal to UITableViewController's view frame!
Sometimes I'm using self.view.frame.width in -tableView:heightForRowAtIndexPath: method.. (like now, and it works pretty well, but not perfectly because of grouped UITableView, should subtract some constant values, and they are different for 2 devices * 2 orientations)
Sometimes I have some #defined constants in UITableViewCell (if I know width exactly)...
Sometimes I'm using some dummy pre-allocated UITableViewCell (what is just stupid, but sometimes is pretty elegant and easy for use)...
But I don't like anything of that.
What's the best decision?
Maybe i should create some helper class, that will be initialized with such parameters:
accessory views, device orientation, device type, table view editing state, table view style (plain, grouped), controller view frame, and some other, that will include some constants (like grouped tableView offset, etc) and use it to find the expected UITableViewCell contentView width? ;)
Thanks
Table view uses the tableView:heightForRowAtIndexPath: method to determine its contentSize before creating any UITableViewCellcells. If you stop and think about it, this makes sense, as the very first thing you would do with a UIScrollView is set its contentSize. I have run into a similar problem before, and what I've found is that it is best to have a helper function that can take the content going into the UITableViewCell and predict the height of that UITableViewCell. So I think you will want to create some sort of data structure that stores the text in each UITableViewCell, an NSDictionary with NSIndexPaths as keys and the text as values would do nicely. That way, you can find the height of the text needed without referencing the UITableViewCell.
Although you can calculate heights for labels contained in table view cells, truly dynamically, in '- layoutSubviews' of a UITableViewCell subclass, there's no similar way of doing this (that I know of) for cell heights in '- tableView:heightForRowAtIndexPath:' of a table view delegate.
Consider this:
- (void)layoutSubviews
{
[super layoutSubviews];
CGSize size = [self.textLabel.text sizeWithFont:self.textLabel.font
constrainedToSize:CGSizeMake(self.textLabel.$width, CGFLOAT_MAX)
lineBreakMode:self.textLabel.lineBreakMode];
self.textLabel.$height = size.height;
}
Unfortunately though, by the time '- tableView:heightForRowAtIndexPath:' is called, that is too early, because cell.textLabel.frame is yet set to CGRectZero = {{0, 0}, {0, 0}}.
AFAIK you won't be able to do this neither with content view's frame, nor summing up individual labels' frames...
The only way I can think of is to come up with a convenience class, methods, constants, or such that will try to cover up all possible width in any device orientation, on any device:
#interface UITableView (Additions)
#property (nonatomic, readonly) CGFloat padding;
#end
#implementation UITableView (Additions)
- (CGFloat)padding
{
if (self.formStyle == PTFormViewStylePlain) {
return 0;
}
if (self.$width < 20.0) {
return self.$width - 10.0;
}
if (self.$width < 400.0 || [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return 10.0;
}
return MAX(31.0, MIN(45.0, self.$width * 0.06));
}
#end
Also note that, recently we also have new iPhone 5's 4-inch width (568 instead of 480) in landscape orientation.
This whole thing is pretty disturbing, I know... Cheers.

Resources