I've spent several days trying to figure this out, but there doesn't seem to be a solution. I have a very basic UITableView cell with two labels in it. One of them will be one line, the second will be multiline. The second one will be varying in heights. Here is an example of what I'm trying to produce ( UIStackViews inside of UITableViewCells ) :
From reading hundreds of SO posts, hundreds of blogs, scouring the Apple Developer sites, there seems to be an unlimited amount of ways one could write this. After having experimented with hundreds of different ways, I still can't manage to display the text like so. I think some of the trouble comes from the fact that I'm using 3 different UITableView cell variations in one UITableView.
Here is my code from my latest attempt cellForRowAtIndexPath :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : UITableViewCell!
let (parent, isParentCell) = self.findParent(indexPath.row)
if !isParentCell {
let categories = ["words", "translation","commentary"]
if categories[parent] == "words" {
cell = tableView.dequeueReusableCellWithIdentifier(childWordsCellIdentifier, forIndexPath: indexPath) as UITableViewCell
// Reset content
for subview in cell.contentView.subviews {
subview.removeFromSuperview()
}
cell.prepareForReuse()
let words = self.page.valueForKey("words")!.allObjects as! [Word]
let wordsInOrder = words.sort({Int($0.order!) < Int($1.order!) })
let word = wordsInOrder[indexPath.row - 1]
let labelWidth = (self.view.frame.width - 80) / 2
let wordLabel = UILabel(frame: CGRectZero)
wordLabel.text = word.valueForKey("sanskrit") as? String
wordLabel.font = UIFont(name: "EuphemiaUCAS-Bold", size: 16)
wordLabel.numberOfLines = 0
wordLabel.translatesAutoresizingMaskIntoConstraints = false
wordLabel.layer.borderColor = UIColor.greenColor().CGColor
wordLabel.layer.borderWidth = 1.0
let widthWordConstraint = wordLabel.widthAnchor.constraintEqualToConstant(labelWidth)
widthWordConstraint.priority = 300
widthWordConstraint.active = true
let englishWordLabel = UILabel(frame: CGRectZero)
englishWordLabel.text = "Foobar don't want to play my game with my anymore."
englishWordLabel.font = UIFont(name: "STHeitiTC-Light", size: 16)
englishWordLabel.numberOfLines = 0
englishWordLabel.preferredMaxLayoutWidth = labelWidth
englishWordLabel.translatesAutoresizingMaskIntoConstraints = false
let englishWordConstraint = englishWordLabel.widthAnchor.constraintEqualToConstant(labelWidth)
englishWordConstraint.priority = 300
englishWordConstraint.active = true
englishWordLabel.layer.borderColor = UIColor.blueColor().CGColor
englishWordLabel.layer.borderWidth = 1.0
let stackView = UIStackView()
stackView.axis = .Horizontal
stackView.distribution = .FillProportionally
stackView.alignment = .FirstBaseline
stackView.spacing = 15
stackView.layoutMargins = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
stackView.layoutMarginsRelativeArrangement = true
stackView.addArrangedSubview(wordLabel)
stackView.addArrangedSubview(englishWordLabel)
stackView.translatesAutoresizingMaskIntoConstraints = false
englishWordLabel.topAnchor.constraintEqualToAnchor(stackView.topAnchor).active = true
englishWordLabel.bottomAnchor.constraintEqualToAnchor(stackView.bottomAnchor).active = true
cell.contentView.addSubview(stackView)
cell.contentView.layoutIfNeeded()
} else {
cell = tableView.dequeueReusableCellWithIdentifier(childCellIdentifier, forIndexPath: indexPath) as UITableViewCell
// Reset content
cell.textLabel!.text = ""
for subview in cell.contentView.subviews {
subview.removeFromSuperview()
}
cell.prepareForReuse()
cell.textLabel!.text = self.page.valueForKey(categories[parent]) as? String
cell.textLabel!.textColor = UIColor(red: 35/255.0, green: 31/255.0, blue: 32/255.0, alpha: 1.0)
cell.textLabel!.font = UIFont(name: "STHeitiTC-Light", size: 16)
}
}
else {
// Parent
cell = tableView.dequeueReusableCellWithIdentifier(parentCellIdentifier, forIndexPath: indexPath)
cell.textLabel!.text = self.dataSource[parent].title
cell.textLabel!.textColor = UIColor(red: 66/255.0, green: 116/255.0, blue: 185/255.0, alpha: 1.0)
cell.textLabel!.font = UIFont(name: "STHeitiTC-Light", size: 20)
}
cell.selectionStyle = .None
cell.textLabel!.translatesAutoresizingMaskIntoConstraints = false
cell.textLabel!.numberOfLines = 0
cell.textLabel!.lineBreakMode = .ByWordWrapping
return cell
}
Which produces this :
I suggest you don't use stack view for this . Just take custom cell with Label according to your requirement and cell will resize automatically according to Label text size.
Check , here i have attached demo.
UITableview cell Autoresize According to textsize
Output :-
In viewdidload
super.viewDidLoad()
self.tblView.estimatedRowHeight = 100;
self.tblView.rowHeight = UITableViewAutomaticDimension;
self.tblView.setNeedsLayout()
self.tblView.layoutIfNeeded()
Dont forget to set Numberoflines=0 of UILabel property.
Edit :- If you need step by step guide regarding how to set constrain to UILabel ,
check this link ,
Adjust UILabel height depending on the text
Edit :- Here i have take 2 label in cell according to your above image. Just set constrain like this .
Label 1 :- Top , Leading , (Height and width According to your requirement)
Label 2 :- Top , Bottom , Leading from Label 1, Trailing from Superview
The height of a table view cell is decided by the table based on the rowHeight property, or on the return value of optional func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat from the table view delegate.
The height that may be set by the programmer for the UITableViewCell through its frame property is ignored!
Hence you need to figure out the desired height of each cell programatically. Then you need to implement optional func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat from the table view delegate for each of the cells.
If the size of a cell changes while the table view is displayed, you need to either:
reload the table with reloadData() from UITableView, or
update the cell with func reloadRowsAtIndexPaths(_ indexPaths: [NSIndexPath], withRowAnimation animation: UITableViewRowAnimation) from UITableView.
Edit
Actually since you are using constraints in you view it should work without using ``.
Try to replace the code in if categories[parent] == "words" { .. } with:
cell = tableView.dequeueReusableCellWithIdentifier(childWordsCellIdentifier, forIndexPath: indexPath) as UITableViewCell
// Reset content
for subview in cell.contentView.subviews {
subview.removeFromSuperview()
}
cell.prepareForReuse()
let words = self.page.valueForKey("words")!.allObjects as! [Word]
let wordsInOrder = words.sort({Int($0.order!) < Int($1.order!) })
let word = wordsInOrder[indexPath.row - 1]
let wordLabel = UILabel(frame: CGRectZero)
wordLabel.text = word.valueForKey("sanskrit") as? String
wordLabel.font = UIFont(name: "EuphemiaUCAS-Bold", size: 16)
wordLabel.numberOfLines = 0
wordLabel.translatesAutoresizingMaskIntoConstraints = false
wordLabel.layer.borderColor = UIColor.greenColor().CGColor
wordLabel.layer.borderWidth = 1.0
let englishWordLabel = UILabel(frame: CGRectZero)
englishWordLabel.text = "Foobar don't want to play my game with my anymore."
englishWordLabel.font = UIFont(name: "STHeitiTC-Light", size: 16)
englishWordLabel.numberOfLines = 0
let stackView = UIStackView()
stackView.axis = .Horizontal
stackView.distribution = .FillProportionally
stackView.alignment = .Fill // EDIT
stackView.spacing = 15
stackView.layoutMargins = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
stackView.layoutMarginsRelativeArrangement = true
stackView.addArrangedSubview(wordLabel)
stackView.addArrangedSubview(englishWordLabel)
stackView.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addSubview(stackView)
cell.contentView.leadingAnchor.constraintEqualToAnchor(stackView.leadingAnchor).active = true
cell.contentView.topAnchor.constraintEqualToAnchor(stackView.topAnchor).active = true
cell.contentView.trailingAnchor.constraintEqualToAnchor(stackView.trailingAnchor).active = true
cell.contentView.bottomAnchor.constraintEqualToAnchor(stackView.bottomAnchor).active = true
cell.contentView.layoutIfNeeded()
Also I would have used two different cells classes for this task rather than removing the views in the contentView.
Please let me know how it goes!
First of all, unless you need a UIStackView for some other purpose that you're not mentioning in your question, don't use them. Multi-line labels and dynamic height cells work well without them (don't needlessly complicate the code if they are not necessary).
There are no bugs in iOS that stop this from working, that I'm aware of. Dynamically sized cells work great with Auto Layout, all you need to do is set the correct constraints in the cells and set the rowHeight and estimatedRowHeight properties of the table view.
The most likely reason this is not working for you is that you have not put all the needed constraints in your cell. The needed constraints are:
A top constraint from your cell content (i.e. your multi-line label) to the top of the cell content view
A leading constraint from your single-line label to the left of the cell
A trailing constraint from your multi-line label to the right of your cell
A bottom constraint from the bottom of your multi-line label to the bottom of your cell
I think you're missing point 4.
Edit
According to your comments, you're using a UIStackView so as to align the top baselines between the single and the multi-line labels. By this, I understand you want your labels to align like this:
To get this behaviour, you don't need a UIStackView. Just give the labels constraints to allow the multi-line label to define the cell height. The following image shows the top baselines aligned between the two labels (i.e. the first lines of each label are aligned).
Notice how the left label only needs a leading and top constraint, while the right label needs a top, trailing and bottom, because it defines cell height.
In summary, dynamic table view cells require three things:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100
The cell content must have all four constraints (leading, trailing, top and bottom) to define cell height.
What you want to achieve can be done by a simple implementation of heightForRowAtIndexPath from the tableView delegate.
If you're unsure what cell should have what height you can just calculate it on runtime.
For this you need to make use of Self sizing table view cell i.e. table view itself calculates height required for each cells to display it's content it can be achieved in two lines of code:
Step1: set estimate height for table view
tableView.estimatedRowHeight = 33.0
step2: set tableView's row height to UITableViewAutomaticDimension
tableView.rowHeight = UITableViewAutomaticDimension
Here is the tutorial for detail description http://www.appcoda.com/self-sizing-cells/
The approach i will be following:
I will create a UIView SubClass as a container view which will contain "word label" and "english word label". it's much easier, seperate code and maintanable.
I will create a cell subclass and use this container view as subView of cell'scontent view.
I will then use this whole set up in cellForRowAtIndex.
I will also make some code implementation in heightForRow. As to make cell row dynamic height at run time u must implementing this method heightForRow.
The sample Output will some thing like below, it has one UIImageView, and Two UILabel and custom gray seperator. This dynamic cell height is based on what ever image height and what ever string length to be shown in UILabel:
I will share some code snippet for you help. So here goes some conceptual code example for container view:
Most important constraint setup for container view say (VenueViewContainer:UIView) is as below, (for your case you can make labels horizontally, instead of vertical):
"V:|-0-[venueImage]-10-[venueName]-2-[sportName]-10-[lblSeperator(10)]",
"H:|-0-[venueImage]-0-|",
"H:|-20-[venueName]-20-|",
"H:|-20-[sportName]-20-|",
"H:|-0-[lblSeperator]-0-|",
Be sure to set these two properties for your labels:
[lbl setNumberOfLines:0];
[lbl setLineBreakMode:NSLineBreakByWordWrapping];
In your VenueViewContainer implementation file make a method:
/*!This method is responsible for getting view dynamic height .*/
-(float)getViewHeight
{
[self layoutIfNeeded];
CGFloat maxY = 0;
for (UIView *subview in self.subviews) {
maxY = MAX(CGRectGetMaxY(subview.frame),maxY);
}
return maxY;
}
/*!
This method is responsible for set up Venue.
#param venue object
*/
#pragma -mark data population
- (void)setupViewWithVenue:(Venue *)venue
{
self.venueLabel.text = #"my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue last";
self.sportName.text = #"my sport my sport my sport my sport my sport my sport my sport my sport my sport my sport my sport my sport my sport my sport last";
[self.venueImage setImageWithURLString:venue.venueImageUrl defaultImage:[UIImage imageNamed:#"venueinfo_main"]];
}
Now lets talk about custom cell. the UITableViewCell subclass. The implementation is some thinh like this:
#implementation VenueCellTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self setUpContainer];
[self setUpConstraints];
}
return self;
}
/*!
This method is responsible for set up Container
*/
-(void)setUpContainer{
aViewContainer = [[VenueViewContainer alloc] initWithFrame:CGRectZero];
[aViewContainer setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:aViewContainer];
}
/*!constraints setup*/
-(void)setUpConstraints{
/*!
dictionary of views for autolayout
*/
NSMutableDictionary* views;
views = [NSMutableDictionary new];
UIView *parentView = self.contentView;
views[#"aViewContainer"] = aViewContainer;
views[#"parentView"] = parentView;
NSArray* constraints;
NSString* format;
/*!
layouting horizontal
*/
format = #"|-0-[aViewContainer]-0-|";
constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];
[parentView addConstraints:constraints];
/*!
layouting vertical
*/
format = #"V:|-0-[aViewContainer]-0-|";
constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];
[parentView addConstraints:constraints];
}
/*!
This method is responsible for set up venue
#param venue object
*/
- (void)setupCellWithVenue:(Venue *)venue
{
[aViewContainer setupViewWithVenue:venue];
}
/*!
This method is responsible to get cell height dynamically
#param venue object
*/
-(float)getCellHeight
{
return [aViewContainer getViewHeight];
}
Thats it related to customixation of your cell.
now talk about cellForRow and heightForRow:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
VenueCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kVenueCellIdentifier];
if (nil == cell) {
cell = [[VenueCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:kVenueCellIdentifier];
}
[cell setBackgroundColor:[[AWPViewFactory sharedInstance]getColor:#"colorWhite"]];
#pragma uncomment below line as per ur need
// Venue *venue = [_dataSourceArray objectAtIndex:indexPath.row];
[cell setupCellWithVenue:nil];
if ([cell respondsToSelector:#selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
return cell;
}
#pragma mark - UITableViewDelegate methods
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Use the dictionary of offscreen cells to get a cell for the reuse identifier, creating a cell and storing
// it in the dictionary if one hasn't already been added for the reuse identifier.
// WARNING: Don't call the table view's dequeueReusableCellWithIdentifier: method here because this will result
// in a memory leak as the cell is created but never returned from the tableView:cellForRowAtIndexPath: method!
VenueCellTableViewCell *cell = [self.offscreenCells objectForKey:kVenueCellIdentifier];
if (!cell) {
cell = [[VenueCellTableViewCell alloc] init];
[self.offscreenCells setObject:cell forKey:kVenueCellIdentifier];
}
// Configure the cell for this indexPath
#pragma uncomment below line as per ur need
// Venue *venue = [_dataSourceArray objectAtIndex:indexPath.row];
[cell setupCellWithVenue:nil];
return [cell getCellHeight];
}
couple of things i have to not use in above aproach:
1. No use of automatic row height calculation property.
2.No use of estimated height
3.No need of unnecessary updateConstraints.
4.No use of Automatic Preferred Max Layout Width.
5. No use of systemLayoutSizeFittingSize (should have use but not working for me, i dont know what it is doing internally), but instead my method -(float)getViewHeight working and i know what it's doing internally.
i have shared you most relevant code blocks, i have not still worked on swift. But basics remains same.
Thanks
This is very easy.lets go step by step.
1. set the estimatedRowHeight of table view.It makes easy and fast to load the cell.
2.set the rowHeight property of tableview as UITableViewAutomaticDimension.and don't use heightForRowAtIndexPath.
3.put the all top bottom leading and trailing constraint on both Label.its important.
Lets rock and roll
no need to use stackView
As of iOS 9.1 UIStackView doesn't implement intrinsicContentSize: so the table view can't calculate the height of each cell, thus they are displayed at the estimated height instead.
So, ideally you would simplify your code to mean you don't use a stack view and you don't keep adding and removing (and creating and destroying) views all the time. The root of the solution is to not use a stack view though.
You can continue to use a stack view if you want, but you'll need to create a subclass and implement intrinsicContentSize:. Your reason for using the stack view shouldn't be required though as you can configure the constraints to match first baselines.
As others have mentioned, make sure you're letting the table view cells dynamically resize with:
tableView.estimatedRowHeight = <estimatedHeightValue>
tableView.rowHeight = UITableViewAutomaticDimension
But you've mentioned that you're already doing this.
The rest of the problem is a case of missing constraints. You've already told autolayout that you want your multi-line label to match the top and bottom of the stack view, as in the code below:
englishWordLabel.topAnchor.constraintEqualToAnchor(stackView.topAnchor).active = true
englishWordLabel.bottomAnchor.constraintEqualToAnchor(stackView.bottomAnchor).active = true
But you haven't mentioned to autolayout how this stack view relates to the cell's content view (its superview). This is necessary for dynamically-sized cells because according to Apple:
To define the cell’s height, you need an unbroken chain of constraints and views (with defined heights) to fill the area between the content view’s top edge and its bottom edge. If your views have intrinsic content heights, the system uses those values. If not, you must add the appropriate height constraints, either to the views or to the content view itself.
Your labels have intrinsic content, so that's no problem, but in order to complete the "unbroken chain," you need to tell autolayout that the stack view's top and bottom should be equal to the content view's top and bottom, like so:
// stackView.superview! is the table view cell's content view
stackView.topAnchor.constraintEqualToAnchor(stackView.superview!.topAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(stackView.superview!.bottomAnchor).active = true
Add these two lines after you've added the stack view to the content view, and I believe you'll be in business.
FYI, even if you're programmatically adding these views to your cells like you are, you can still visually debug layout issues quite well with Xcode's awesome Capture View Hierarchy ability. While your app is running from Xcode, click the menu item Debug > View Debugging > Capture View Hierarchy. It's very easy to see what's going on in your view hierarchy, what constraints are active, where your disappearing views went, etc..
2nd FYI, destroying views and then reinstantiating new ones every time a cell appears on screen significantly degrades performance while scrolling. As much as you can, you'll want to take existing views from dequeued cells and reassign their contents with the proper content for that row (and thus avoid view instantiation). You can still do this using your purely-programmatic way of doing things by dequeueing a cell and calling cell.viewWithTag for each possible view. If the method returns nil, you do a one-time instantiation of the view for the cell and give the view a tag (let's say 1 for wordLabel and 2 for englishWordLabel). Then assign the proper content for the row to the view.
I've had very similar problems with autoLayout time and time again. I don't use stackViews much, I typically use them when I have a requirement to add / remove or show / hide a view. When not doing that I opt for just using constraints. I feel the stackviews are quite buggy in quite a few circumstances. Particularly in xib's. I don't know why that makes a difference, but it seems to always cause warnings that I can't remove, when using more than 1 label.
That being said, autoLayout isn't without its issues either, and they all mainly center around preferredMaxLayoutWidth.
To explain, in order for AutouLayout to calculate the height of a label, it needs to know what width the label can be. When you have multiple labels together, particularly in a tableViewCell, this causes all manner of issues.
I asked and subsequently answered a related question here several days later.
What I did is added a subclass of UILabel that always ensures preferredMaxLayoutWidth is updated whenever the label is modified. I've recently updated it for iOS 8, iOS 9 and a separate issue I found with modal views.
So the full steps are:
Create the UIlabel subclass.
Create a cell with your labels laid without UIStackViews.
Set the number of Lines to 0 for one or both labels depending on your usecase.
Set the Labels to be of the type of your subclass.
Implement the estimatedHeightForRowAtIndexPath method to make a guess at what the height might be.
Calculate the height of the cell inside heightForRowAtIndexPath.
To Calculate the height, you can use something like this (which I have abstracted away into a helper method that I can reuse more easily)
// Set the cell data first, i.e. the label text, any programmatic fonts, font sizes etc.
if let tempCell = cell as? UITableViewCell
{
tempCell.width = tableView.width
let size = tempCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
if tableView.separatorStyle != UITableViewCellSeparatorStyle.None
{
// +0.5 for seperator
return size.height+0.5
}
else
{
return size.height
}
}
I have combined this with a protocol that makes all cells take in a dictionary to set their data. Then I can wrap up this method to take in and pass in a dictionary and reuse the code over and over again.
This has been working seamlessly for me for a very long time.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *firstLable = firstLable.text;
NSString *secondLable = SecondLable.text;
CGSize constraint = CGSizeMake(cell.frame.size.width/2, 20000.0f);
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
CGRect firstLableRect = [firstLable boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"Your App Font" size:16.0f],
NSParagraphStyleAttributeName: paragraphStyle.copy} context:nil];
CGRect secondLableRect = [secondLable boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"Your App Font" size:16.0f], NSParagraphStyleAttributeName: paragraphStyle.copy}context:nil];
float max = MAX(firstLableRect.size.height, secondLableRect.size.height) + 20;
//20 for spacing 10 pc above and 10 pc below
return max ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier=#"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.selectionStyle =UITableViewCellSelectionStyleNone;
NSString *lable1 = #"first label text";
NSString *lable2 = #"second lable text";
CGSize constraint = CGSizeMake(cell.frame.size.width/2-10, 20000.0f);
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
CGRect firstLableRect = [lable1 boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"Your App Font" size:16.0f],
NSParagraphStyleAttributeName: paragraphStyle.copy} context:nil];
CGRect secondLableRect = [lable2 boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"Your App Font" size:16.0f], NSParagraphStyleAttributeName: paragraphStyle.copy}context:nil];
UILabel *firstLable = [[UILabel alloc]initWithFrame:CGRectMake(5,10,constraint.width,firstLableRect.size.height)];
[firstLable setLineBreakMode:NSLineBreakByWordWrapping];
firstLable.minimumScaleFactor = 15.0f;
[firstLable setNumberOfLines:0];
firstLable.textAlignment = NSTextAlignmentLeft;
[firstLable setFont:[UIFont fontWithName:#"your App font" size:16.0f]];
[cell.contentView addSubview:firstLable];
UILabel *secondLable = [[UILabel alloc]initWithFrame:CGRectMake(cell.frame.size.width/ 2+5,10,constraint.width,secondLableRect.size.height)];
[secondLable setLineBreakMode:NSLineBreakByWordWrapping];
secondLable.minimumScaleFactor = 15.0f;
[secondLable setNumberOfLines:0];
secondLable.textAlignment = NSTextAlignmentLeft;
[secondLable setFont:[UIFont fontWithName:#"your App font" size:16.0f]];
[cell.contentView addSubview:secondLable];
return cell;
}
I have a UICollectionView cell, which has multiple items
I need to implement its dynamic height depending on the data of 1st bold label
I have tried multiple code snippets but not working for my case.
as most of them are checking a specific label height and assigning it to the cell size..
Thanks
I have written this function in Xamarin.iOS to calculate the height of cell.
Hope this will help you.
CGRect GetRectOfItemNameLabel(ActivityTaskModel item , UITableView tableView)
{
nfloat width = tableView.Frame.Width;
UIStringAttributes attrs1 = new UIStringAttributes ();
attrs1.Font = UIFont.FromName("Helvetica", 17);
CGRect frameName = ((NSString)item.TaskDescription).GetBoundingRect (new CGSize (width, 100000), NSStringDrawingOptions.UsesLineFragmentOrigin, attrs1, null);
return frameName;
}
Make sure you don't provide any height constraint to that label/TextView.
Note : If your text is larger then rather than using Label use TextView
I need to resize my UITableView with the height of his contentSize for this i made this:
private void ajustHeightOfTableView()
{
nfloat height = tableViewCores.ContentSize.Height;
nfloat maxHeight = tableViewCores.Superview.Frame.Size.Height - tableViewCores.Frame.Y;
if (height > maxHeight)
height = maxHeight;
UIView.Animate(0.25, new Action (() => {
this.tableViewAjustHeight.Constant = height;
this.contentView.SetNeedsUpdateConstraints();
}));
}
and
public override void ViewDidAppear (bool animated)
{
base.ViewDidAppear (animated);
ajustHeightOfTableView();
}
i have a IBOutlet with de Height Constraint of my UITableView... so i resize the tableview calling after reloadData() my function ajustHeightOfTableView...
The problem is: Below my UITableView i have another UIView with buttons and textfields WHEN i resized my tableView my another View does not work! she does not respond for the user interaction... i thing that my problem is that after the resize the view is not in the correct position.
i have another constraint with the Vertical Spacing between the UITableView and UIView like this:
IMAGE 1
this constraint is to put my view in the correct space another my uitableview resize...
here my UITableView Constraint Height:
IMAGE2
someone please know what am i doing wrong here?
I don't know if you can adjust the height and width separately, but I know of a method to scale the webpage to your view in both directions. This is done using the ScalesPageToFit.
UIWebView webView = new UIWebView (new RectangleF (0, 0, cellWidth, cellHeight));
webView.ScalesPageToFit = true;
webView.ScrollView.MinimumZoomScale = 1f;
webView.ScrollView.MaximumZoomScale = 5f;
webView.LoadRequest (new NSUrlRequest(new NSUrl(URL)));
Adjusting the Frame of the UIWebView won't work.
I hope this short information helps. Good luck!
Love and regards,
Björn
I have a list of phone rates, the textLabel is the country/territory and the detailTextLabel is the rate I have to display.
For some strings, the textLabel is too long and the detailTextLabel becomes hidden. Is there a setting to automatically adjust the text with … if it's too long?
Here is an example where Central African Republic (Mobile) has this issue:
On laying out a cell with UITableViewCellStyle.Value1 style the title label seems to get priority and push the detail label out of view. The solution might be to subclass UITableViewCell and override its layoutSubviews():
override func layoutSubviews() {
super.layoutSubviews()
if let detail = self.detailTextLabel {
// this will do the actual layout of the detail
// label's text, so you can get its width
detail.sizeToFit()
// you might want to find a clever way to calculate this
// instead of assigning a literal
let rightMargin: CGFloat = 16
// adjust the detail's frame
let detailWidth = rightMargin + detail.frame.size.width
detail.frame.origin.x = self.frame.size.width - detailWidth
detail.frame.size.width = detailWidth
detail.textAlignment = .Left
// now truncate the title label
if let text = self.textLabel {
if text.frame.origin.x + text.frame.size.width > self.frame.width - detailWidth {
text.frame.size.width = self.frame.width - detailWidth - text.frame.origin.x
}
}
}
}
Note that although detail.textAlignment = .Left we account for detail's width and the actual text ends up aligned to the right.
So what you probably need to do is manually fix the width of the textLabel, since by default it takes up the whole width of the cell. To do this, you can do the following:
CGRect textLabelFrame = cell.textLabel.frame;
textLabelFrame.size.width -= DETAIL_LABEL_WIDTH;
cell.textLabel.frame = textLabelFrame;
In your cellForRowAtIndexPath, where DETAIL_LABEL_WIDTH is the width you want for the detailTextLabel. Assuming the label is auto-ellipsizing, which it should be, this will cause the text to add a "..." at the end of the label right before the detail text label if the width is longer than the width you are setting above.
I'm having a problem with what I thought was a simple UIView slide animation from a UINavigationBar. I have a UIView with a UIButton and I would like to simulate a slide
down/up effect from the Navigation Bar by animating the View height. The problem is the View animates but any SubViews e.g. UIButton stay fixed.
I'm coding in Xamarin (C#) but I'm sure it's simple enough to read for Objective-C coders
if (_menuView == null)
{
// set initial frame
_menuView = new MenuView{Frame = Window.Frame};
// store original "expanded" height for later
_expandedMenuHeight = _menuView.Frame.Height;
// set the frame to underneath the NavigationBar
var frame = ((UINavigationController)Window.RootViewController).NavigationBar.Frame;
var y = frame.Bottom;
// Add to Window View
menuView.Frame = new RectangleF(_menuView.Frame.X,y,_menuView.Frame.Width,0);
Window.Add(_menuView);
}
// Toggle View Height - if collapsed, expand, if expanded, collapse
var height = _menuView.Frame.Height == 0 ? _expandedMenuHeight : 0;
// Animate the height
UIView.Transition (_menuView,0.2,UIViewAnimationOptions.CurveEaseIn | UIViewAnimationOptions.LayoutSubviews,() => {
_menuView.Frame = new RectangleF(0,_menuView.Frame.Y,_menuView.Frame.Width,height); },null);
Any pointers are greatly appreciated!
I am not so clear with Xamarin. But in objectiveC, you could use,
view.clipsToBounds = YES;
So when you are trying to reduce the height the subviews would also be hidden.