UIImageView auto resize inside a custom UITableViewCell with varying height - ios

I have set up a custom cell prototype inside storyboard not using autolayout and i have run into a rather vexing problem where a UIImageView i have inside the cell seems to obey constraints all of it's own when i want it to reflect the size of the cell with a bit of padding.
Here is the setup in storyboard interface builder and view mode is set to "scale to fill"
And here is what i get back, with no editing of the placement or scaling of the image, it seems very much like it's using aspect fill.
I have tried various options and none seem to work for me so far, The only other way i can think is turn of auto resizing and set the rect myself manually when the cell is created any ideas?
and my code for setting the cell
- (void)setCell:(NSDictionary*)messageData
{
[_nameLabel setText:messageData[#"name"]];
[_messageLabel setText:messageData[#"message"]];
[_nameLabel sizeToFit];
[_messageLabel sizeToFit];
UIImage *image;
if([messageData[#"direction"] boolValue])
{
image= [[UIImage imageNamed:#"bubble_left"]resizableImageWithCapInsets:UIEdgeInsetsMake(18, 6, 6, 10) resizingMode:UIImageResizingModeStretch];
}
else
{
image= [[UIImage imageNamed:#"bubble_right"]resizableImageWithCapInsets:UIEdgeInsetsMake(18, 10, 6, 6) resizingMode:UIImageResizingModeStretch];
}
[_bubbleImage setImage:image];
}
and the protocol methods
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CUIChatCellTableViewCell *cell = [_chatTableView dequeueReusableCellWithIdentifier:#"CustomCell" forIndexPath:indexPath];
NSDictionary *messageData = _testDataArray[indexPath.row];
[cell setCell:messageData];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
_customCell = [_chatTableView dequeueReusableCellWithIdentifier:#"CustomCell"];
//configure cell
NSDictionary *messageData = _testDataArray[indexPath.row];
[_customCell setCell:messageData];
//Get height of the cell
CGFloat height = [_customCell.messageLabel frame].size.height+[_customCell.nameLabel frame].size.height+20;
return height;
}

Set autoresizing properties like this, may you get help from this.

I could not get AutoResizing to work and i tried another test project from scratch and it seemed to work, so it must have been certain settings, either way i ended up having to set the height manually for each cell based on it's content anyway here is the code to do so
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
_customCell = [tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
//configure cell
CMessageInfo *messageData = _testDataArray[indexPath.row];
[_customCell setCell:messageData];
//Get height of the cell
CGFloat height = [_customCell.messageLabel frame].size.height+[_customCell.nameLabel frame].size.height+20;
return height;
}

Related

UItableviewcells with background image not filling the whole width of screen?

Hi i am new for ios and in my app i have created one UITableView and i have set background image for UITableViewcell but image not filling the whole width of screen as like below screen. Why this problem is occuring?
I mean UITableViewCell left and right sides gap is coming images is not filling whole cell width.
please help me someone
my code:-
#import "TableViewController.h"
#interface TableViewController ()
{
UITableView * tableList;
TableCell * Cell;
}
#end
#implementation TableViewController
- (void)viewDidLoad {
[super viewDidLoad];
tableList = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen]bounds].size.width, [[UIScreen mainScreen]bounds].size.height) style:UITableViewStylePlain];
tableList.delegate = self;
tableList.dataSource = self;
tableList.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.view addSubview:tableList];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"MyCell";
Cell = (TableCell *)[tableList dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (Cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableCell" owner:self options:nil];
Cell = [nib objectAtIndex:0];
}
//UIImageView *imageBackground = [[UIImageView alloc] init];
if (indexPath.row == 0) {
Cell.backGroundImage.image = [UIImage imageNamed:#"cell_top.png"];
} else if (indexPath.row == 9) {
Cell.backGroundImage.image = [UIImage imageNamed:#"cell_bottom.png"];
} else {
Cell.backGroundImage.image = [UIImage imageNamed:#"cell_middle.png"];
}
//imageBackground.contentMode = UIViewContentModeScaleToFill;
//Cell.backgroundView = imageBackground;
return Cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 44.0;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if ([cell respondsToSelector:#selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:#selector(setPreservesSuperviewLayoutMargins:)]) {
[cell setPreservesSuperviewLayoutMargins:NO];
}
if ([cell respondsToSelector:#selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
#end
Try to set the layoutMargins property of the cells and the UITableView to UIEdgeInsetsZero.
- (void) viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
tableList.layoutMargins = UIEdgeInsetsZero;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
[...]
Cell.layoutMargins = UIEdgeInsetsZero;
return Cell;
}
Also check for the contentMode of the UIImageview.
Cell.backGroundImage.contentMode = UIViewContentModeScaleAspectFill;
try set contentInset on Left = 0
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
Use Debug View Hierarchy to figure out UITableView, UITableViewCell or UIImage is not filling the whole width of screen
http://www.raywenderlich.com/98356/view-debugging-in-xcode-6
Please check your "TableCell" in the storyboard. Did you select custom insets option for your custom cell?
Rather than setting up your table view with code, you want to do this in a storyboard. Then you'll want to use auto layout to connect constraints from the table view to the view controller's view. There are lots of tutorials available to teach you how to do this. Learning this will make things much easier in the long run.
Change the name of your tableList property to tableView. That will make more sense to other developers (including yourself in the future), since that's what it is (a UITableView instance).
Your cell is named Cell with a capital C, but you don't want to name properties with capital letters. Also, it doesn't need to be a class property the way it's being used. Remove it from the #interface section.
Coding Guidelines for Cocoa
Remove the -numberOfSectionsInTableView: method. The default is 1, so you don't need code to return the default value.
Instead of -dequeueReusableCellWithIdentifier:, use -dequeueReusableCellWithIdentifier:forIndexPath:. Then you won't need to follow it with a test to see if a cell was returned (it always will be). You'll need to register your nib with -registerNib:forCellReuseIdentifier:. Or better yet, just design it in the storyboard.
It appears that your custom table view cell has a UIImageView named backGroundImage. That should be added as a subview to the cell's backgroundView property (which you'll need to create - the view, not the property, which is already part of UITableViewCell). Set the image view's autoresizingMask so it will resize with the backgroundView:
- (void)awakeFromNib
{
[super awakeFromNib];
self.backgroundView = [[UIView alloc] initWithFrame:self.bounds];
self.backGroundImage.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.backGroundImage.frame = self.backgroundView.bounds;
[self.backgroundView addSubview:self.backGroundImage];
}
Remove the -tableView:heightForRowAtIndexPath: method. You only want to use this if you return different values. The default row height is 44.0, so you don't need to do anything else.

Reasons for UITableViewCell UI inconsistency

Most of the time, when my app is working the way it should, my Table View items look like this:
But every so often a cell (on initial load) looks likes this:
As you can see the image has resized, the 'published By' label has resized.
Why would this happen? The same code/storyboard should affect all the cells the same way? Why are some not doing what they are told?
If it helps, when a cell loads the wrong way, all I have to do is scroll up, and back down again, and the problem is fixed !!
This means that there clearly isn't a problem with the image or the amount of text, is it just the iPhone acting up?
Thanks for any help !
I think its cell dequeue issue. Your cell could not calculate proper height for cell. If you are using autolayout try the following code. hope it will works for you.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
static YOUR_TABLEVIEW_CELL *sizingCell = nil;
static NSString *CellIdentifier=#"YOUR_TABLEVIEW_CELL_IDENTIFIER";
sizingCell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (sizingCell==nil)
{
sizingCell=[[YOUR_TABLEVIEW_CELL alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[self configureFareIssueCell:sizingCell atIndexPath:indexPath];
return [self calculateHeightForConfiguredSizingCell:sizingCell];
}
//assign all the lables & images here
- (void)configureFareIssueCell:(YOUR_TABLEVIEW_CELL* )cell atIndexPath:(NSIndexPath *)indexPath
{
//e.g
cell.lbl.text=#"YOUR_TEXT";
cell.imageView.image=[UIImage imageNamed:#"NAME_OF_YOUR_IMAGE"];
}
- (CGFloat)calculateHeightForConfiguredSizingCell:(YOUR_TABLEVIEW_CELL *)sizingCell
{
CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height + 1.0f; // Add 1.0f for the cell separator height
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=#"YOUR_TABLEVIEW_CELL_IDENTIFIER";
YOUR_TABLEVIEW_CELL *cell =[tableView dequeueReusableCellWithIdentifier:#"YOUR_TABLEVIEW_CELL_IDENTIFIER"];
if (cell==nil)
{
cell=[[YOUR_TABLEVIEW_CELL alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[self configureFareIssueCell:cell atIndexPath:indexPath];
return cell;
}
Do you use layer mask for creating rounded image? If yes, you see this strange behavior because layer mask was created before UITableView assign proper frame for cell, so layer mask will have incorrect frame.

UIImage in TableViewCell pushes Cell Separator

I've added a UIImage to my table view cell. However, the UIImage is pushing the separator over to the right to make room for the UIImage. I'd like to find a way to have the separator include the UIImage and not be pushed over. Here is a picture of my table view cell.
Here is my cellForRowAtIndexPath method with code for the image:
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
Exercise *tempPlaceholder = [exercisesInTable objectAtIndex:indexPath.row];
NSString *exerciseDisplayName = tempPlaceholder.exerciseName;
exerciseDisplayName = [exerciseDisplayName capitalizedString];
exerciseDisplayName =
[exerciseDisplayName stringByReplacingOccurrencesOfString:#"_"
withString:#" "];
cell.textLabel.text = exerciseDisplayName;
cell.imageView.image = [UIImage imageNamed:#"quads.png"];
return cell;
}
If anyone could help me with this I'd really appreciate it. Thank you.
For anyone else who runs into this problem, using:
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
will fill the gap between the UIImage and the table cell separator.
Try change the size of imageView frame
cell.imageView.frame = CGRectMake(0, 0, 10.0, 10.0);
Or change the height of cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 40.0;
}
The behaviour you are experiencing will only occur on iOS 7 where the separators have insets that by default change with image view size.
To remove this behaviour simply set the separator insets to zero. However the separatorInset property is available on UITableView from iOS 7.0
So you only have to remove the inset in iOS 7.
You can check whether the table view responds to setSeparatorInset: doing
if ([self.tableview respondsToSelector:#selector(setSeparatorInset:)])
{
[self.tableview setSeparatorInset:UIEdgeInsetsZero];
}

Access previous cell from layoutSubviews

I've created a custom UITableViewCell class. In that class I adjust the height of the cell depending on the image inside it.
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
if (self.imageView.image) {
self.frame = CGRectMake(self.frame.origin.x,self.frame.origin.y,
self.frame.size.width, self.imageView.image.size.height);
}
}
But since they are all different heights some cells overlap each other.
The first image is the same height as the default cell height, therefore the second image is fine. The second image has a larger height which makes the third image to be positioned behind it.
Can I somehow access the previous cell from the layoutSubviews and adjust the y-position from that?
By doing this in layoutSubviews instead of tableView:heightForRowAtIndexPath:, your code depends on a side effect and is trying to defeat UITableView. You should fix this in tableView:heightForRowAtIndexPath: and let the UITableView do the work for you.
Instead of fixing a constant row height in the method
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 65; //For example
}
In the case, for example, that you have an array with the names of the images ordered (imageNamesArray), you can use something like this:
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat desiredImageWidth = 50.0f;
UIImage *image = [UIImage imageNamed:[imageNamesArray objectAtIndex:indexPath.row]];
CGFloat ratio = image.size.height/image.size.width;
return desiredImageWidth * ratio;
}

UITableViewCell: Begin/Endupdate causes cells to flip out

I have a tableview representing a feed, with three different custom UITableView cells. One (the top one) is solid and should always be there, but the cells underneith that one is either a product or an event cell (loaded from DB). The thing is that the Eventcells have a textview and an imageview that can varie in height, so to view these correctly I calculate the correct height for them and then set the height in heightForRowAtIndexPath. I need to update the cell with its new height somehow, so I do an tableview begin/end update. However when I do this for every cell each time its loaded into view, all the cells start bouncing around and change content when I scroll the tableview.
Here is my CellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return [self loadJobInfoCell:indexPath];
} else if (indexPath.section == 1) {
if ([[jobDetailsArray objectAtIndex:indexPath.row] isKindOfClass:[JobProduct class]]) {
return [self loadProductCell:indexPath];
} else if ([[jobDetailsArray objectAtIndex:indexPath.row] isKindOfClass:[JobEvent class]]) {
static NSString *CellIdentifier = #"EventCell";
EventCell *cell = [tableViewRef dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[EventCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
JobEvent *currentEvent = [jobDetailsArray objectAtIndex:indexPath.row];
// setting labels and stuff here
// Is there an image to this event?
if (![currentEvent.EventPicture isEqual:[NSNull null]]) {
[[cell largeImage] setImage:currentEvent.EventPicture];
[[cell largeImageHeightConstraint] setConstant:currentEvent.EventPicture.size.height];
NSNumber *height = [NSNumber numberWithFloat:currentEvent.EventPicture.size.height];
[largeImagesDictionary setObject:height forKey:[NSString stringWithFormat:#"%d", indexPath.row]];
} else {
[[cell largeImageHeightConstraint] setConstant:0.f];
}
// set correct height for the textview
NSDictionary *attributes = #{NSFontAttributeName: [UIFont systemFontOfSize:14]};
CGRect paragraphRect = [cell.tvText.text boundingRectWithSize:CGSizeMake(204.f, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:attributes context:nil];
[[cell tvTextHeightConstraint] setConstant:paragraphRect.size.height+16.f];
NSNumber *height = [NSNumber numberWithFloat:[[cell tvTextHeightConstraint] constant]];
[eventTextHeightDictionary setObject:height forKey:[NSString stringWithFormat:#"%d", indexPath.row]];
[tableViewRef beginUpdates];
[tableViewRef endUpdates];
return cell;
}
}
return nil;
Without the begin/endupdates it works fine, though the cells are not the correct height and get cut of. Can I somehow update the height without reloading the table, or is there a better solution to the whole situation? Ive tried keeping track of which cells have gotten their update but that doesn't work, it still messes up the order, height and content. I've tried every combination of solutions I could possibly think of, but being a novice iOS developer im not even sure im taking the correct approach to this problem.
Thanks very much in advance.
EDIT:
Man, Im stupid.. I've sat and calculated heights in cellforrowatindex insted of in heightforrowatindex and passed the data inbetween with nsdictionaries. I solved this with autolayout and pre-calculating the height of the data in heightforrowatindex.
I'm not exactly sure of your setup, but the way I've done this, is to set up the constraints in IB so that the image view and text view will expand automatically as the cell does. By doing it this way, I don't have to do any size changes for the image view or text view in code, just the cell size. My cell setup looks like this:
The image view is centered in the x direction and has a constraint to the top of the cell and one from the bottom to the top of the text view. The text view has constraints to the sides and to the bottom of the cell. I put a dummy image in the image view, and selected "Size To Fit Content" from the Editor menu -- this cause the height and width constraints for the image view to be deleted.
In code, I calculate the sizes for the image view and text view, then return the sum of their heights (plus a fudge factor) in heightForRowAtIndexPath. Here is the code for a sample app:
- (void)viewDidLoad {
[super viewDidLoad];
self.theData = #[#{#"text":#"jkkjhkj kh k jk h hkj hjkhkjh hjkh jk hhkjhjkh jkh hkj hkjh hkjhjkhhkk jk jkh jkhkhkjhjhkjhkjhkkjhjjhk kjhkjh jkh hk h kj h jkh jkh kjh kh hjkhk jhjk", #"Pic":#"pic1.jpg"},#{#"text":#"fjhg lfkgh gjk gjk glkjfhgjkhgjkgh sjkghsjkgsjgjgk jgk hg hdgjlhjhjgjg fgjklfg fghjgk gjlkg hjgh jg jlkgljsdkggjlglgjdlkg hgjlgjfkghjg ljhfg jlskfdg hjgjlkgjlkdf gjfghjlkfgljkgjlkdgjdfghjdgjglhjkg hljkg ljkgljkfgljkgljksdgljkfgjlfg ljfglldkfjgh ljkgjlkf dgfghslfjdgklfjgljfdfgl", #"Pic":#"pic2.tiff"},#{#"text":#"jdkh lj flfh ljs fajlh ljds f", #"Pic":#"pic3.tiff"}];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGSize textViewSize = [self.theData[indexPath.row][#"text"] sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(280.f, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
UIImage *pic = [UIImage imageNamed:self.theData[indexPath.row][#"Pic"]];
CGSize imageViewSize = pic.size;
return textViewSize.height + imageViewSize.height + 40;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RDCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.tv.text = self.theData[indexPath.row][#"text"];
cell.iv.image = [UIImage imageNamed:self.theData[indexPath.row][#"Pic"]];
return cell;
}

Resources