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
Related
Assume the following, simple layout:
Three views vertically stacked upon each other
Using simple vertical spacings between the views
Is it possible to hide the red view including its margins using constraints / AutoLayout only?
Settings redView.isHidden = true will hide the red view but will not change the position of the blue view. The blue view will stay at the same position as if the red view would be visible.
Using redView.removeFromSuperview() to completely remove the red view would show the desired result. Due to its optional spacing constraint to the gree view the blue view would move to where red view was. However it would be quite hard to re-show the red view because all its constraints would have to be set up from scratch.
In Android setting the visibility to View.INVISIBLE simply hides a view (as the first case described here) while View.GONE renders the remaining layout as if the view was not there at all.
Can this be done with iOS using constraints / AutoLayout only?
Of course I can achieve the same buy manually manipulating the constraints and setting up new constraints in code. But the question is, if there is a more convenient solution as in Android?
A VerticalStackView seems to fit your requirements. You can include all the views in the stack view and set the spacing directly on it.
Then, is one of the views is hidden, the stack view will automatically adjust all the constraints.
Take a look at the pictures:
If possible, wrap your views in a vertical UIStackView. You can then individual views and the other views will be rearranged as intended. You also don't need to add constraints between items, since the stackview handles the spacing between views.
The simplest way is to embed the views into a StackView and when one of them is hidden, the one below will move up into its place.
Follow these steps:
Add all the views you need in the storyboard/xib
Editor - Embed in stackView
Set the spacing in the stackView
Set the stackView constraints
Create outlets for the views you want to be hidden in a certain case
Set that views hidden property to true
Regarding the constraints, you can set them for the StackView and for the vertical one, just set the equal spacing and the space properties in the StackView.
Result:
I want to achieve this without adding height.
I tried using setHidden it works but leaves empty space.
is there any other way, after some googling i found that it is not possible?. i dont know may be .
There are multiple options to achieve this :
1) Use StackView with vertical orientation and add your views as arranged subviews in this stack view. Later you can remove the one you want and the height is adjusted automatically
2) Use constraints. Add a constraint from your 1st view to bottom with less priority initially. Later, when you call setHidden() on your second view, increase the priority of this constraint. In this way, the height will be adjusted.
You can try one the above approaches.
You can use view.alpha = 0 as an alternate to change its opacity to 0, which would "hide" the view from sight but the view will be loaded for all intents and purposes.
I have view with three button with equal size. Each button take 1/3 part portion of view.
Like this image:
If I remove/hide one button then two button width should increase equally and take 1/2 portion of view. if I remove two button then one button size should be equal size of view.
My question is, how it's possible using the Autolayout.
Best option is using stackView. StackView gives lots of flexibility in adding or removing items. If you wish to use only auto layouts, you can achieve it by connect it's width constraints as IBOutlet and change the values programatically.
Best way to do that is to use UISTACKVIEW.Place a stackview and add 3 buttons.You can give proper layout constraints to the stack view as you need
click on stack view-- select attribute inspector
change distribution--fill equally
spacing--0
Then after that if you hide any button,other buttons will be automatically adjusted in width
Other Possible sol to this problem is Adding or removing constraints during runtime is a heavyweight operation that can affect performance. However, there is a simpler alternative.
For the view you wish to hide, set up a width constraint. Constrain the other views with a leading horizontal gap to that view.
To hide, update the .constant of the width constraint to 0.f. The other views will automatically move left to assume position. and for equal width pervoid multiplier to width..
You have a few options:
UIStackView which was made exactly for this.
UICollectionView similar to UIStackView in a certain way, but not really meant for this. However, it does the job nicely and it's easy to implement. Sometimes easier than UIStackView.
NSLayoutConstraint by using multiple constraints with different priority so that you can activate/deactivate them as needed and get the desired result. This approach is a bit more complex by it gives you the highest degree of control and flexibility over the views in your hierarchy.
The best way to achieve what you are looking for is, like others have already mentioned, to use a UIStackView.
When the isHidden property of a UIView inside a stack view is set to true, that stack view will hide the view and take care of the layout, so you will only need to set the correct constraints for your stack view.
This is what I'm trying to do...
I have one view controller that needs to dynamically display different subviews based on the presence of some data.
Here is a simple mockup. Each colored block represents a unique subview.
Sometimes the green block needs to be at the top, sometimes the green block won't display at all, sometimes the light blue block will be something different, etc.
Each subview has interactive elements, so I've been creating and adding them like so:
Defining a new view controller
Defining its view
Calling addChildViewController and didMoveToParentViewController
Calling addSubview on myNewViewController.view
Using SnapKit to make auto layout constraints to position the view
I want to transition to UIStackView because it seems a good support system for this view because all I need to do is stack its subviews. I'm seeing many conflicting constraint errors and unexpected view frames when trying to add subviews with their own inner auto layout constraints.
Question
Am I setting myself up for failure here by embedding the views of 4-6 view controllers in the view of one view controller?
Also, how do I give the added views properties like minimum heights or content sizes without seeing many breaking constraints with UIStackView? (So they can stack, but one of them is say, 400 tall, and the other is 200 tall)
Answer
You can absolutely do this using UIContainerViews combined with UIStackViews and UIScrollViews, it's a complicated setup so here's a starter project to get you started:
https://github.com/Rnorback/ScrollingStackView
Here's what that project looks like:
You want the containers to have different sizes. In order to do that, simply add height constraints to the containers with Autolayout. If you want to change the height of the scrolling. Then you'll need to change the height constraint of the UIStackView.
Brief Explanation
When creating this setup, you have to make sure the UIStackView distribution setting stays in fill. That way you can set height constraints on UIContainerViews.
When setting up anything in a UIScrollView you have to make sure that the object is pinned to the edges of the scroll view and has a defined width and height, otherwise the scrollview will throw a constriant error. I think of it like the scrollview tries to press in on all sides of your content view and if any side gives, the scrollview won't be able to present it properly.
Hope this helps.
What is the proper way to make a fluid layout in iOS, in the sense that hidden elements do not take up space anymore?
I have a table view with in each cell a customized detail-type of view with title, subtitle and a row with some extra information:
The extra information can be up to three pairs of an icon and a label with a value. The layout of all views inside the cell is done using AutoLayout with no missing or ambiguous constraints.
What I would like to achieve is that when the value is 0, the icon and the label are not displayed and the views on the right are shifted to the left.
If I just use the setHidden: method, the width of the hidden parts are not changed, so that there is just whitespace, but no views are moved. Example:
It should look like this:
The following questions are related but do not seem to fit my case:
Fluid UI layout on iPhone
AutoLayout with hidden UIViews?
I have tried to follow the approach with creating layout constraints for the four frames that need to be set to zero: the width of the heart-shaped icon, the width of the label containing the value, the whitespace in between those and the whitespace between the label and the next icon. This did not work because I could not bind the layout constraints to the outlet in the code, and besides it seems a cumbersome method for something that should be a common scenario.
EDIT: I fixed the problem with the outlets to constraints: to do this it is necessary to create a subclass for the table cell and creating outlets for the constraints there.
With "common scenario" I refer to doing something similar in web design, where setting the display style to none is simple and has the desired effect. I expect that there is something similarly simple for this in iOS.
I have been thinking of using a collection view with reusable cells, but then I need to set up a delegate and a datasource and everything, and before I would go this way I wanted to make sure that that is the way to do it.
There is no need to remove a hidden view. Connect the constraint to an outlet in the code, and when you determine a view is hidden, subtract from the constraint's constant. Then, in the cell's prepareForReuse, remember to return the constraint's constant to the correct value.
Hidden views maintain their frame, so auto layout will have no reason to adjust the view. The correct way to do this would be to remove the views from the superview. The last thing you must do is double check the constraints. Since you will be removing views, you cannot use those views for auto layout. This will require quite a bit of constraint setting on your UI.