Self sizing Cells,. Autolayout and hidden UIViews - ios

i am using Autolayout to set automatically the height of a cell. But i want to use some hidden UIViews in my Cells. So in some rows they should be hidden. The problem here is, if the label is still hidden it gets recognized by autolayout and it uses the space.
So i guess i need to update the height of my label, or the height of my Constraints.
What is the correct way if i am using Autolayout to hide UIElements in a Cell?
How can i update an existing (from Storyboard) Constraint?
Edit: Found out that i am able to update Constraints with Storyboard, is that the correct way to handle that? - but which is the correct one to setup the height? (This is just a Demo Project)

This is standard task with autolayout. Currently, there are two ways of solving this task:
Removing hidden views
Changing constraints priority
Removing of hidden views
Looks pretty easy and you won't have any problems if you don't use UITableView (you have to put it back in prepareForReuse), UICollectionView or your data can appear while you're on screen, where you've just removed views.
Removing of views is "heavy" operation, so you need to think twice, if you pick this way.
In CustomCell.m:
- (void) prepareForReuse {
[super prepareForReuse];
// add removed views again
// establish constraints
}
- (void) configureCell {
// check if you need to hide a view
[view removeFromSuperview];
}
Changing constraints priority
Assume, you have following cell:
View A
View B
If B sometimes can be hidden, then specify for View A following constraints:
Space to B with 750
Bottom Space to superview with 500
If you set B as hidden, change space to B = 500, bottom space to superview = 750.
Undo that change in prepareForReuse

Related

UITableViewCell dynamic height + hidden elements take up space in Swift?

This is the scenario: I have a Table in which there are Cells with dynamic height. In each cell I have a label and a switch. When I run the App only these two can be seen but then I set the switch to true then a (hidden?) textview appears under these two elements making the height of the cell bigger.
How can I do this? Because when I try hidden elements take up place as well.
This is what I want:
Reality:
How can I do this?
I tried using the new Stack View which can handle it fine, BUT NOT in a table cell....
How can I solve this?
I solved it mixing this answer: Dynamic Height Issue for UITableView Cells (Swift) for the dynamic height and then for the views that show or not I added a height constraint to the view and then on cellForRowAtIndexPath just set the constant of the constraint to 0 if you need to hide it or to your height if you show it.
Hope it helps!
I think it could be solved using constraints:
- set the height constraint for your text view,
- create the outlet for that constraint in your view controller,
- change the constant property of the constraint in your view controller when the switch is used.
If you hide your text view, your text view is still there, text length is as long as it is not hidden.
So instead of hide/show the text of the text view, you'd better to update the text of your text view from "" -> "what ever you want to show."
In this case, the auto layout can handle your query fair easily. You only need the set
self.tableView.estimatedRowHeight = 65 //whatever number
self.tableView.rowHeight = UITableViewAutomaticDimension
and in the cell xib/storyboard, add constraints on thetop andbottom of your text view, don't also forget to make your text view not scrollable as well.
Actually, I recommend you to simply useUILabel in stead ofUITextField, you just need to set thelineNumber of theLabel to be 0, and you can neglect the scroll and size setting of the text view.

UIView position does not respect NSLayoutConstraint when altered from viewDidLoad

I have two views, one visible (grey) and one hidden (red). The visible view is constraint to the superview top with a constant of 32, and the other constraint to the superview top with a constant of 16.
The top of the visible view is also constrained to the bottom of the hidden view, with a constant of 8. This constraint has a priority of 749, because it is initially unsatisfiable.
The idea is that the visible (grey) view should be 32 points below the superview normally, but when the hidden (red) view is made visible, the original (grey) view should be 8 points below the other view (red).
I'm achieving this by keeping a strong reference to the 32-point constraint, and making it active/inactive as I'm hiding/unhiding the view (red).
Here's a picture of my layout:
This works very well normally, but I've been trying to set constraint.active = NO and redView.hidden = NO in viewDidLoad, as I need the textfield to display an error if a certain condition has not been met. For some reason, this does not work. The red view is displayed as expected, but the second view (grey) does not move down as it should (it does not respect the 749 constraint, even if the main constraint is no longer active). Here's a picture of the result:
However, I made the code to inactivate the constraint and display the view run after a small delay (using dispatch_after();), and then it suddenly works as expected:
My question is: why doesn't the view respect the constraint and move down when it is run immediately from viewDidLoad? Why does it suddenly work after a small delay? Is this a decent solution of achieving my goal, given I can get it to work properly?
call it in viewDidLayoutSubviews methode not in viewdidload.
autolayout it take some time to load so call it in viewDidLayoutSubviews.
While using autolayout - (void)viewDidLoad will return the frame which you gave in storyboard.
You have to use - (void)viewDidLayoutSubviews to update the frame according to constraints.
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
//Replace self.view by your view whose constraints need to update
[self.view layoutIfNeeded];
}

UITableView resize cell based on content

Hi I need help with understanding how to resize cell based on its content.
So first of all of course I found many links:
iOS: Multi-line UILabel in Auto Layout
https://www.youtube.com/watch?v=CkvZEJ7dIfw
https://github.com/williamhqs/GSTableViewDynamicHeight
As we said about git example (last link) I can't understand how to change some label and make it works. For example if I delete UILabel and create new one and bind it with content property (content - it is IBOutlet property of bottom label). I seems lost some setting and cell won't stretch.
So I think I don't know to much understanding how to do it.
What I want to understand:
How to setup auto layouts in the storyboard or programmatically.
Which thing I should handle programmatically to make it done.
How the preferred size affects on label. Do we need every time use bonds of superview as a preferred size?
Also in the git example we have one label that changes itself size. What if we have 2 UILabels with dynamic content how to setup it?
If you have some links or videos please drop them here, because I really stuck. Thank you!
I know it's duplicated question but I can't understand how to setup it.
To make Self Sizing Cells works there is three steps:
Setup correctly the constraints of the cell (most important the top and bottom constraints)
Specify the estimatedRowHeight of your table view
Set the rowHeight of your table view to UITableViewAutomaticDimension
for step 2 and 3 it's so easy just add these two lines in you viewDidLoad method
tableView.estimatedRowHeight = 44.0 // or whatever you want
tableView.rowHeight = UITableViewAutomaticDimension
for step 1 which is the most important part of self sizing process
what you need to keep in mind is that "self-sizing needs to get its size from your constraints."
Basically we need to make sure that top space and bottom space constraints of our cell is correctly set up here is an example :
just two labels with the constraints top,bottom,right and left space to each other and to container (see image) the UILabels Lines property is 0 so that you allow have multiple lines
Another example from a project that I am working on:
bottom line:
The label constraints should push against the size of the table view cell and make it taller. So always check the top and bottom constraints.
Also you may run intro trouble working with UILabel with multi-lines because
The intrinsic content size of UILabel and NSTextField is ambiguous for
multi-line text.
so make sure always to setup the preferredMaxLayoutWidth property of yout label:
- (void)layoutSubviews
{
[super layoutSubviews];
self.contentLabel.preferredMaxLayoutWidth = self.contentLabel.frame.size.width;
}
for more infrmation about this issue here read :
iOS Autolayout multi line UILabel
iOS multi-line UILabel in Auto-layout
preferredMaxLayoutWidth
And for more information about Dynamic Table View Cell Height in general here is some useful resources:
UITableView Tutorial: Dynamic Table View Cell Height
Understanding Self Sizing Cells and Dynamic Type in iOS 8
Self Sizing Table View Cells
Mysteries of Auto Layout, Part 1 (wwdc 2015)
Not sure if it will apply to AutoLayout, although when laying out a cell programmatically, running "layoutIfNeeded()" fixed my cell content stretch issue.
layoutIfNeeded was ran at the end of a configure method, used to map values (view model) to UI objects (views)

hide a view and remove blank spaces

I'm developing an app for iOS and I'm using the Storyboard with AutoLayout ON. One of my view controllers has a set of 3 labels, and in certain circumstances i would like to make the second one disappear.
If I use the setHidden:TRUE method the label become invisible but it still obviously take space in the view.
can someone point me to the right direction?
The simplest solution is to put the views that you want to hide inside a StackView. Then to hide the element simply make it hidden:
_myElement.hidden = YES;
StackView will squash hidden elements and they will become invisible.
I think you can link the constraint with the header file of your viewController. Then modify the constraint and commit changes.
Edited:
1) Create the IBOutlet for the constraint.
2) Modify the constraint, for example: self.yourConstraint.constant = 0.0;
3) Commit the new constraint: [viewForUpdate setNeedsUpdateConstraints];
The easiest and most effective way to handle this is using Stack Views. Insert the label in a horizontal/vertical (orientation they appear on your UI) stack view and stack view will internally take care of the spacing. Additional properties like alignment, spacing can be tweaked as per requirement. Make sure you re-establish the constraints between stack view and adjacent elements because once the views are added to a stack view all if its constraints are cleared
You will need to move the other views by adjusting their frames. This can be done directly, or if using auto layout, by giving them a vertical spacing constraints to the view being hidden.
If there are many other views that depend on the hiding/showing view, create another subview that contains all of the dependent views. The dependent views can layout statically on that parent, and that parent can have it's frame adjusted (again, either directly or via auto layout).
view
|
--- view to hide
|
--- common parent (move this with auto layout or directly)
|
--- subview's with position dependent on view to hide
--- ...
This is a late answer/solution, but I have just built a category which does just that - hiding the view without blank spaces.
https://github.com/neevek/UIView-Visibility

AutoLayout or not? How to position 3 subviews?

I can't figure out how to correctly position subviews in a Navigation Controller.
I am trying to position a view, table and another view.
If I turn off AutoLayout than top view and table are ok but my bottom view is pushed off the screen.
With autolayout I get both the table and bottom view in the wrong place:
I try to set frame in viewDidLoad as follows (calendarPicker is position at the top below navigation bar), I want the configPanel to be on the bottom, I hide bottom bar on Push.
self.eventsTable.frame = CGRectMake(0, CGRectGetMaxY(self.calendarPicker.frame),
self.eventsTable.bounds.size.width,
self.view.bounds.size.height - self.calendarPicker.bounds.size.height
);
self.configPanel.frame = CGRectMake(0, self.view.bounds.size.height,
self.configPanel.bounds.size.width,
self.view.bounds.size.height - self.configPanel.bounds.size.height
);
Should I rely on autolayout? How should I make my constraints?
I believe my problems arise due to autosizing of the table mostly, but given that I am setting its frame size why would it not change? I do not want to remove auto layout since it is used on other views designed in the storyboard and from what I understand it applies to all?
Is there something that I am missing that needs to be done on top of setting the frames of individual controls?
EDIT:
I think my biggest problem is autolayout and inability to size table appropriately. If I add constraint to the bottom view to be 0 from bottom of the view, it will originally appear correctly. However consequently when resizing table and top view, the table will push bottom view down sizing itself to occupy all available space.
I need to force UITableView to be no more than height between the bottom of the top view and lower view, but still not sure how to do this.
Somewhat closer
Removing code for frame change of the table fixes the issue of the bottom view being pushed off. However in this case top view overlapps table when it changes size at the same time not being drawn correctly:
Uncheck autolayout and then set frames of all three subviews.
Or
If you want constraints then you can use NSLayoutConstraint class to add constraint to your subviews.
I recommend against switching off autolayout, especially because you can't do it on a view by view basis. Autolayout is a must if you tend to do i18n or want to make sure your app does well in different screen resolutions/orientation.
Try This!
disable use Autolayout in storyboard. Place your three views on view controller(view1, view2, view3). Next go to size inspector and use autosizing masks for all three views. Check this, which will help you
http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1

Resources