Auto layout for UITableViewCell with ratio imageView - ios

I have an imageView with height = 0.5 * width & pin 4 edges to cell.contentView.
How to cell auto fit height to imageView height.
For example:
iPhone5 : cell size = image size = 320 x 160
iPhone6+: cell size = image size = 414 x 207

You can set aspect ratio constraint to your UIImageView with properly multiplier in InterfaceBuilder. And use this code for calculating cell height:
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0; //your estimated height

Try to implement -
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
return screenWidth*0.5 ;
}

try this one
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [UIScreen mainScreen].bounds.size.width/2 ;
}

As you are using pins that is constraints for layout of the image view, changing the frame at the runtime won't change it's frame. You can follow below steps to change the frame at the runtime:
Set the height and width of the UIImageView required for iPhone 6+ (considering that iPhone 6+ is the highest resolution supported).
Take the IBOutlet of both the constraints.
In awakeFromNib method of your tableview cell's class, you can set the value of both the constraints using [constraintInstance setConstant:valueForTheConstraint].
Or you can try to set the aspect ratio for the height and width of the image view.

Related

How to get correct width of a UIView inside UITableViewCell?

I added a UICollectionView inside UITableViewCell. I am trying to set the collectionView.collectionViewLayout.itemSize.width equal to a UIView pageContainerView.bound.size.width inside table view cell. I am trying to set the item size in awakeFromNib. The pageContainerView is added using autolayout, it has both 8 leading and trailing to the super view.
- (void)awakeFromNib {
[super awakeFromNib];
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
CGFloat width = self.pageContainerView.bounds.size.width;
CGSize size = CGSizeMake(width, 321);
layout.itemSize = size;
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 0;
}
But the item size width is shorter than its expected.
You can get the correct size in layoutSubviews
- (void) layoutSubviews {
[super layoutSubviews];
CGFloat width = self.pageContainerView.bounds.size.width;
CGSize size = CGSizeMake(width, 321);
self.layout.itemSize = size;
[self.layout invalidateLayout];
}
I believe the issue here is that you are setting the size of the cell before it is actually displayed on the screen, therefore the whole cell isn't actually the size of the screen yet. I would try setting the cell size when you configure the cell (in cellForItemAt).

How to set dynamic UIImageView height and also UITableViewCell height according to UIImageView height?

Want to set UIImageView size dynamically according to image size and also want to set UITableViewCell height according to above mentioned UIImageView height, which is in UITableViewCell using AutoLayout in Objective c.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
And my code under cellForRowAtIndexPath method is given below:
[cellRecImg.imgMessage sd_setImageWithURL:[NSURL URLWithString:[dictMessage objectForKey:#"msg_attachment"]] placeholderImage:[UIImage imageNamed:#"Image-33"]];
CGFloat imageHeight = cellRecImg.imgMessage.image.size.height;
CGFloat imageWidth = cellRecImg.imgMessage.image.size.width;
float ratio = cellRecImg.imgMessage.frame.size.width / cellRecImg.imgMessage.frame.size.height;
float newHeight = imageHeight / ratio;
float newWidth = imageWidth / ratio;
cellRecImg.constImageHeight.constant = newHeight;
cellRecImg.constImageWidth.constant = newWidth;
[self.view layoutIfNeeded];
This is my UITableViewCell's xib design where can you see the view' constant.
This is my UIImageView, here you can see the constants of UIImageView's.
This the result I got from simulator.
In this result Image you can see that UIImageView create lots of extra gaps form UIImage to UIImageView edge. Actually I don't want that gap and also want to set the UITableViewRow height dynamic according to UIImageView height.
Please answer in Objective c language

Adjusting UICollectionViewFlowLayout cells on rotation

So I'm working on an app that is part of an ePub framework. The app embeds the reader into its view and allows a user to scroll zoom and page by swipe. Im trying to modify it so that the list of ePubs comes into a collectionview as cells displaying the cover image of the epubs. I can create the cells for the flowlayout and using the frame bounds I can create cells but when I try and rotate from portrait to landscape they dont adjust in size and position. My code for the cells is this:
//Set Collection View Cell Size and Orientation
-(CGSize)
collectionView:(UICollectionView *) collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
//Set Landscape size of cells
if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){
CGFloat cellWidth = [[UIScreen mainScreen] bounds].size.width;
CGFloat cellHeigt = [[UIScreen mainScreen] bounds].size.height-350;
NSLog(#"Is Landscape");
return CGSizeMake(cellWidth, cellHeigt);
}
//Set Potrait size of cells
else{
NSLog(#"Is Portrait");
CGFloat cellWidth = [[UIScreen mainScreen] bounds].size.width-80;
CGFloat cellHeigt = [[UIScreen mainScreen] bounds].size.height-240;
return CGSizeMake(cellWidth, cellHeigt);
}
}
and I use this code to position them:
//Collection View Cell Position
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
if(UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)){
return UIEdgeInsetsMake(0,10,0,20); // top, left, bottom, right
}
else{
return UIEdgeInsetsMake(0,20,0,20); // top, left, bottom, right
}
}
When I rotate the device the cells top boundary goes over the frame.
Please help, how can I update the frame dynamically?
You need to refresh collection while rotation . try following code :
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[yourCollectionview performBatchUpdates:nil completion:nil];
}

tableHeaderView with Autolayout not working correctly

Hey everybody i have a TableHeaderView and everything gets managed by Autolayout:
The UIImageView at the top should be always 2:1, so i set the Aspect ration and the Rest of the needed Constraints.
The 4 UIButtons should be always horizontal and should have the same Height and Width. So i worked with Equal Width and Equal Height and also with a Aspect Ratio of 1:1
And i have two UILabels with numberOfLines set to 0. I also made a Subclass of my UILabel, because of the preferredMaxLayoutWidth, like this:
- (void) layoutSubviews
{
[super layoutSubviews];
if ( self.numberOfLines == 0 )
{
if ( self.preferredMaxLayoutWidth != self.frame.size.width )
{
self.preferredMaxLayoutWidth = self.frame.size.width;
[self setNeedsUpdateConstraints];
}
}
}
This is my Code:
- (void)initializeHeaderViewLabels
{
//After the Response from my server arrived i set the tableHeaderView with the Textdata
self.tableView.tableHeaderView = nil;
if((self.contentDict[#"title"]) != [NSNull null])
{
self.headerTitleLabel.text = (self.contentDict[#"title"]);
}
if((self.contentDict[#"shortDescription"]) != [NSNull null])
{
self.headerDescriptionLabel.text = (self.contentDict[#"shortDescription"]);
}
[self.headerView setNeedsLayout];
[self.headerView layoutIfNeeded];
CGFloat height = [self.headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect headerFrame = self.headerView.frame;
headerFrame.size.height = height;
self.headerView.frame = headerFrame;
[self.tableView setTableHeaderView:self.headerView];
}
I get my Image and the Text for the UILabels from my Server, so i have to wait until the Response arrives, then i call initializeHeaderViewLabels.
**My Problem is that the tableHeaderView is way too large during Runtime and so my UILabels get stretched and there is a lot of whiteSpace. Maybe i miss something?
In order to make it work you'll need some magic or migrate away from table header view. I've already answered on a similar question here. The trick is to magically reset tableHeaderView after evaluating it's height via autolayout. I've created sample project for that: TableHeaderView+Autolayout.
Try below solution
- (void)sizeHeaderToFit
{
UIView *header = self.tableView.tableHeaderView;
[header setNeedsLayout];
[header layoutIfNeeded];
CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect frame = header.frame;
frame.size.height = height;
header.frame = frame;
self.tableView.tableHeaderView = header;
}
Source:
table header view height is wrong when using auto layout, IB, and font sizes
Also refer below question...!
How do I set the height of tableHeaderView (UITableView) with autolayout?
My problem was that I was setting constraints on the my header view that were mapping some frame values to superview frame values. When I removed the constraints and just set the frame directly, everything worked.
Header view height is set in the table view delegate. By default it is the same size as in interface builder which is too large when run in app since the width for interface builder is 600.
So what you need is to implement this method in UITableViewDelegate
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 200.0 // Set the desired height based on your device or what ever you are using.
}
And Objective-C version:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 200.0f;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 200;
}

Setting dynamic UITableViewCell height

I've got a UITableView with two dynamic rows. Each of the rows is a subclass of UITableViewCell and is loaded from nib. As my rows contain dynamic content, I use layoutSubviews to reposition all subviews:
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat initialHeight = titleLabel.bounds.size.height;
CGSize constraintSize = CGSizeMake(titleLabel.bounds.size.width, MAXFLOAT);
CGSize size = [titleLabel.text sizeWithFont:titleLabel.font constrainedToSize:constraintSize];
CGFloat delta = size.height - initialHeight;
CGRect titleFrame = titleLabel.frame;
titleFrame.size.height += delta;
titleLabel.frame = titleFrame;
locationLabel.frame = CGRectOffset(locationLabel.frame, 0, delta);
dayLabel.frame = CGRectOffset(dayLabel.frame, 0, delta);
timeLabel.frame = CGRectOffset(timeLabel.frame, 0, delta);
}
The problem is that I can't find a way to determine the height in table view delegate's tableView:heightForRowAtIndexPath: method.
The trick is that I load cell from nib, so just after it's loaded titleLabel.bounds.size.width is 300 px (as in nib), not taking into account type of the device (iPhone/iPad) and current orientation, so it seems impossible to calculate the height without conditional checks for orientation and device type. Any ideas?
Your layoutSubviews doesn't resize the cell, so the following should work:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return cell.frame.size.height;
}
If the cell needs to be resized due to the content changing then you can set self.frame = newFrame inside layoutSubviews.
You can also manual cause layoutSubviews to be called by calling setNeedsLayout.

Resources