I have a label that is in a custom uitableview cell. I am using auto layout to position the label. My question is how can one set the height of the label to zero when it does not have any text. Or how to to make the label height 0. The project supports ios 8 so using stackview is out of the question. The label is also expansive i can't set a constant height constraint.My layout is given below .
You can set label's height constraint >= 0. Label will update it's size to the content, and if text is missing height will be 0.
Another solution is possible that, set height constraint and take outlet of it and set it's constant to zero when text is nil.
Just ctrl + drag from height constraint to class to connect outlet to constraint.
then you can programatically change it's height when needed by changing it's constant.
for example,
#IBOutlet weak var labelHeightConstraint: NSLayoutConstraint!
and change constant like,
self.labelHeightConstraint.constant = 0
Hope this will help :)
In tableviewcell give height constraints except UILabel which one you need to hide.Change your Tableviewcell height it works.
For example, Your UILabel height is '30' and tableviewcell height is 130.You can give 130-30 = 100 in cell height.
//only sample code
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0
return 130
else
return 100
}
First set Height Constraint to Label. ctrl + drag the height Constraint to class to connect outlet to constraint. i.e
#IBOutlet weak var LabelHeightConstraint: NSLayoutConstraint!
and in implementation set the Height Constraint of Label to zero. As shown below....
self.LabelHeightConstraint.constant = 0;
if(check the label contains data)
{
self.LabelHeightConstraint.constant = 20;
}
else
{
self.LabelHeightConstraint.constant = 0;
}
This Logic will surely work......
Set the text as nil as and when required and set the content hugging priority high
Related
in my app i am working on UITableView in which i am using UIImageView by setting up constraint on storyboard to display image. All i need is when there is no image available the height of ImageView will become 0 otherwise if image available height will be 150.
Try adding constraints to left, top, right. Add a IBOutlet in your viewController for NSContraint for height. And when initialising cell check for image is available or not. Depending on that set the IBOutlet value.
Add that IBOutlet to your height constraint of UIImageView.
Set TableView cell height to automaticDimensions.
Let me know if it helps or having any issue.
In storyboard
Set your imageView constraint height <= 150
in heightForR0w
return UITableViewAutomaticDimension
in estimateHeight
return 200
Give your ImageView to FixHeight Constraint
Create IBOutlet of that FixHeight Constraint
#IBOutlet weak var imgviewHeightConstraint: NSLayoutConstraint!
in your cellForRowAtIndexPath
check this way
if image available {
cell.imgviewHeightConstraint.constant = 150
} else {
cell.imgviewHeightConstraint.constant = 0
}
I have a view and table view design using Autolayout and Constraints. I have successfully design view using Autolayout.
But I have one more requirement in table view cell content. ** I want to increase LABEL height accordingly text (Depend on content of label text- Label 1). Please review attached screen shot. I have set CELL into the table view using Storyboard. Table view cell into I have taken 3 Labels.**
Label -2 : I have set constraint label-2, Leading edge constraint-5, Trailing edge constraint-5, Top edge constraint-10, Bottom constraint-0. Here I set height of Label-2 20. It fixed and I do not want to increase them.
Label -3 : I have set constraint label-3, Leading edge constraint-5, Trailing edge constraint-5, Top edge constraint-0, Bottom constraint-5. Here I set height of Label-3 20. It fixed and I do not want to increase them.
I want to increase height of Label 1 according to text.
**_Label -1 :_** I want to increase size of Label 1. I have set constraint label-1, Leading edge constraint-5, Trailing edge constraint-5, Top edge constraint-5, Bottom constraint-10. Here I set height of Label-1 35.
Right now, I have not set constraint of Label-1 height constraint. I have also tried set height constraint but it’s cannot take effect on height increases issues.
I have created method for Label-1. It was count label-1 size and increases it accordingly. But it was not return current height.
Here, I set table view cell size 95. And it will be increase dynamically using table view height delegate method.
_
Source Code :-_
UITableViewSource Method:
//Count Height of table view cell
public override nfloat GetHeightForRow (UITableView tableView, NSIndexPath indexPath){
TableViewCellClass cell = null;
cell = (TableViewCellClass)tableView.DequeueReusableCell(cellIdentifier);
return cell.RequiredTableViewCellHeight(tableView.Bounds.Size.Width);
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath){
TableViewCellClass cell = (TableViewCellClass)tableView.DequeueReusableCell(cellIdentifier,indexPath);
//Add Data In Cell
cell.Updatecell (tableItems [indexPath.Row].Label1Data, tableItems [indexPath.Row].Label2Data, tableItems [indexPath.Row].Label3Data);
return cell;
}
TableView Cell Method:-
partial class TableViewCellClass : UITableViewCell{
public TableViewCellClass (IntPtr handle) : base (handle)
{
}
public void Updatecell (string lbl1Data, string lbl2Data, DateTime lbl3Data){
Label1.Text = lbl1Data; //I want to increases height of label1
Label2.Text = lbl2Data;
Label3.Text = lbl3Data.ToString();
//Here Below, fixed text and size for Label-2 and Label-3. It was fixed and never increase it's height
Label2.SizeToFit();
Label2.AdjustsFontSizeToFitWidth = true;
Label3.SizeToFit();
Label3.AdjustsFontSizeToFitWidth = true;
}
//RequiredTableViewCellHeight Method For Count Label Hight and Increase Cell According to it.
public float RequiredTableViewCellHeight(nfloat screenWidth){
Console.WriteLine("screenWidth : {0}",screenWidth); //Here we get the screen size of table view WIDTh
//Here make dynamic lable
Label1.Lines = 0;
Label1.AdjustsFontSizeToFitWidth = false;
UIFont cellFont = Label1.Font;
nfloat lbl1widthVal = screenWidth - 10; //Here we Minus 10 due to leading and trailing constraint. So Width not effected.
//Below Count the size of label height accordingly text and font size. Size not return actuall size. It's some time return always same.
CGSize lbl1Size = ((NSString) Label1.Text).StringSize(cellFont,constrainedToSize:new CGSize(lbl1widthVal,400.0f),lineBreakMode:UILineBreakMode.WordWrap);
Console.WriteLine("lbl1Size Total Size: {0}",lbl1Size);
int rowHeight = (int)lbl1Size.Height; //Get the Height of table cell
Console.WriteLine("rowHeight: {0}",rowHeight);
rowHeight += 60; //Add extra 60 due to label-2, label-3 size and spacing value in cell
Console.WriteLine("After Final Edit rowHeight value: {0}",rowHeight);
return (float)rowHeight;
}
}
Can i fetch issues due to autolayout or I do make mistake somewhere in code?
Please note that, I do not want to remove autolayout in project.
Please review that and let us know your suggestions. Thank in advance!
Self sizing views (tableviewcells) might be of use to you.
You set the constraints, then set tableView.estimatedRowHeight = 44.0 (for example)
Then set tableView.rowHeight = UITableViewAutomaticDimension
Here is a tutorial about this: http://www.appcoda.com/self-sizing-cells/
I have a UITableView with custom UITableViewCell designed to have automatic height.
The behavior is that in the first load of my UIViewController with UITableView displays my labels with partial texts. Then when I scroll to bottom then scroll to top, I get the desired look for height and for texts.
Here is the screenshots:
Initial look for the view controller:
Here is the look after scrolling bottom then top (This is the correct look for my implementation some Lorem text is removed by me):
Edit 1:
Code:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 101 // much heigher than most cells. But no use.
In the UI Builder, the UITableViewCell's "Row Height" set to "Default" (Custom not checked)
In the UI Builder, the UITableView's "Row Height" set to "101" (also tried to set it to "0" but same result.)
Getting auto layout to work on a UITableViewCell is to ensure you have constraints to pin each subview on all sides — that is, each subview should have leading, top, trailing and bottom constraints.
Furthermore, you need a clear line of constraints going from the top to the bottom of the contentView. This ensures that auto layout correctly determines the height of the contentView based on its subviews.
The tricky part is that Interface Builder often won’t warn you if you’re missing some of these constraints; auto layout simply doesn’t return the correct heights when you run the project. For example, it may return 0 for the cell height, which is a clue that your constraints need more work.
If you run into issues when working with your own projects, try adjusting your constraints until the above criteria are met.
check the link for details:http://www.raywenderlich.com/87975/dynamic-table-view-cell-height-ios-8-swift
I think you can use heightForRowAtIndexPath method
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var heightToReturn : CGFloat = 0
heightToReturn = StringUtil.findHeightForText("your text", havingWidth: "your label width" , andFont: UIFont.systemFontOfSize("font size")) + // add some buffer for padding
if heightToReturn < 101
{
heightToReturn = 101
}
return heightToReturn
}
}
and use this method to calculate the height of the text
+ (CGFloat)findHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font {
CGFloat result = font.pointSize+4;
if (text) {
CGSize size;
CGRect frame = [text boundingRectWithSize:CGSizeMake(widthValue, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil];
size = CGSizeMake(frame.size.width, frame.size.height+1);
result = MAX(size.height, result); //At least one row
}
return result;
}
In iOS 8 you can seemingly set UILabels to have a preferredMaxLayoutWidth of automatic, which just figures it out via Auto Layout. However, I cannot seem to figure out how to calculate the height of the view the label is inside of. Basically I have a multi-line UILabel pinned to the sides of a UIView, and I want to know how tall the UIView is. (In this case it is a cell.)
If I write:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as! MyTableViewCell
cell.label1.text = "some sample text to test it out, and it resolves to two lines long"
let height = cell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
return height + 1.0 // Extra 1.0 is for separator height
}
The height of the cell is always what it would be if the UILabel was only one line long. I have numberOfLines set to 0, so it should be returning a higher number for the multi-line nature. The systemLayoutFittingSize call is clearly not working here.
What am I doing wrong?
You can always reside on Autolayout by setting the content hugging priority to a value more than the height constraint priority. Or you can use the following code to calculate the height that fits.
CGSize sizeThatFits = [YourString boundingRectWithSize:CGSizeMake(yourDesiredWidth,MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:[UIFont systemFontOfSize:15]} context:nil].size;
Edit:
You have constraints priorities. That means each constraint has a priority in case of conflicts. A higher priority means it will be satisfied first. You just need to set a priority to your content hugging higher than your normal heigh constraint.
I've not been able to find much in the way of AutoLayout with individual .xib files...
I've got a standalone .xib file that has 3 views - a header view (which contains two labels), an input, and a footer (which contains two buttons). It looks like this:
The labels in the header view have constraints which should affect the vertical size of the header view, and in turn the size of the entire view. The subheader is a label with 0 lines, which means it is multi-line and dynamic. Everything else has a set height with horizontal constraints to superview and top constraints to sibling (or superview in header view's case).
The issue I am having is that when I load this .xib file in code for display, the height is always static based on what is defined in Xcode's inspectors. Is it possible to make the height of the entire view dynamic based on the width (which affects dynamic label height and therefore rest of the view)?
For example - if I load this view from the .xib and set its width to 300, how do I then have it resize its height to accommodate the dynamic label's new height? Do I need to use the intrinsicContentSize method to define this size?
After much experimentation and reading, I have found the answer. When loading the .xib in some sort of constructor (in my case a class level convenience method), you must make sure to call [view setTranslatesAutoresizingMaskIntoConstraints:NO]; For example, I've done the following:
+ (InputView *)inputViewWithHeader:(NSString *)header subHeader:(NSString *)subHeader inputValidation:(ValidationBlock)validation
{
InputView *inputView = [[[NSBundle mainBundle] loadNibNamed:#"InputView" owner:self options:nil] lastObject];
if ([inputView isKindOfClass:[InputView class]]) {
[inputView setTranslatesAutoresizingMaskIntoConstraints:NO];
[inputView configureWithHeader:header subHeader:subHeader inputValidation:validation];
[inputView layoutIfNeeded];
[inputView invalidateIntrinsicContentSize];
return inputView;
}
return nil;
}
Then, it's necessary to override layoutSubviews and intrinsicContentSize. Overriding layoutSubviews allows me to set the preferredMaxLayoutWidth of my label, while overriding intrinsicContentSize allows me to calculate the size based on constraints and subviews! Here is my implementation of those:
- (void)layoutSubviews {
[super layoutSubviews];
self.subHeaderLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
[super layoutSubviews];
}
- (CGSize)intrinsicContentSize {
CGFloat height = self.headerView.bounds.size.height;
height += self.headerInputSpacer.constant;
height += self.inputField.bounds.size.height;
height += self.inputButtonSpacer.constant;
height += self.buttonView.bounds.size.height;
CGSize size = CGSizeMake([UIScreen mainScreen].bounds.size.width - 20, height);
return size;
}
I'm sure there are ways to improve this, or better ways to make it happen, but for now it is at least sized correctly! Very useful for views that should not have user-defined frames.
This is my approach (Swift version):
Embed everything inside a view. Your xib hierarchy should be:
Your xib
View
Everything else, your labels, buttons etc.
View's constraint should constraint to Top, Leading and Trailing to superview(your xib), and inside your "everything else", there should be an object's bottom constraint to the superview (View).
In your code:
Load the nib
nib.frame.size.width = 80 // Set your desired width here
nib.label.text = "hello world" // Set your dynamic text here
nib.layoutIfNeeded() // This will calculate and set the heights accordingly
nib.frame.size.height = nib.view.frame.height + 16 // 16 is the total of top gap and bottom gap of auto layout
For my case, I'm loading this xib into collection view's cell, the xib's height is to be dynamically adjusted, and the width is to follow cell's width. Lastly, the above code block is inside my cellForItemAt method of the collection view.
Hope it helps.
Unfortunately, I am not sure what I was missing. The above methods don't work for me to get the xib cell's height or let the layoutifneeded(), UITableView.automaticDimension to do the height calculation. I've been searching and trying for 3 to 4 nights but without an answer.
Some answers here or on another post do give me hints for the workaround though. It's a stupid method but it works. Just add all your cells into an Array. And then set the outlet of each of your height constraint in the xib storyboard. Finally, add them up in the heightForRowAt method. It's just straight forward if you are not familiar with the those APIs.
Swift 4.2
CustomCell.Swift
#IBOutlet weak var textViewOneHeight: NSLayoutConstraint!
#IBOutlet weak var textViewTwoHeight: NSLayoutConstraint!
#IBOutlet weak var textViewThreeHeight: NSLayoutConstraint!
#IBOutlet weak var textViewFourHeight: NSLayoutConstraint!
#IBOutlet weak var textViewFiveHeight: NSLayoutConstraint!
MyTableViewVC.Swift
.
.
var myCustomCells:[CustomCell] = []
.
.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Bundle.main.loadNibNamed("CustomCell", owner: self, options: nil)?.first as! CustomCell
.
.
myCustomCells.append(cell)
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let totalHeight = myCustomCells[indexPath.row].textViewOneHeight.constant + myCustomCells[indexPath.row].textViewTwoHeight.constant + myCustomCells[indexPath.row].textViewThreeHeight.constant + myCustomCells[indexPath.row].textViewFourHeight.constant + myCustomCells[indexPath.row].textViewFiveHeight.constant
return totalHeight + 40 //some magic number
}