How To Properly Show/Hide UI Controls & Handle Constraints - ios

I'm building a realtime IOS dashboard and I need to dynamically display UI elements (currently a UISlider or UISwitch) inside a UITableViewCell depending on the data retrieved. The tableview cell (and associated XIB) has a label on the left side and either a UISwitch or UISlider on the right.
I'm able to show/hide the UI elements via the isHidden property of each component but the autolayout constraint always places the UI elements next to each other even though in the interface builder I placed the UI components on top of each other (because I need to show either the slider or switch not both). BTW - I can't use multiple UITableViewCells due to some RXSwift issues.

The 'hidden' property will not change auto layout constraints.
The control will be hidden but will still take up the space it's meant to take.
Having said that, the UIStackView component tracks it's children's 'hidden' property and changes the constraints whenever the property changes.
You could put your slider and switch inside a UIStackView and set either one to visible or not.
I wouldn't do it that way though.
I'd construct two kind of cells, one with a UISwitch, and one with a UISlider and use a different cell based on the content.

In Swift, The 'hidden' property is not a dynamic var. you can't observe it, but you can try to observe property setter.
details:http://simcai.com/2017/03/29/2017-03-29/
let view = UIView()
view.rx.methodInvoked(#selector(setter: showAllView.isHidden)).subscribe { (isHidden) in
print("\(isHidden)")
}
view.isHidden = true

Related

Cannot move content view in cells in Interface Builder

I can't change a position and size of title and subtitle label in Interface Builder. What should I do?
You can't edit the position of the default UITableViewCell subviews in interface builder. You can change the text alignment, content insets, and other related properties but you can't explicitly change their frames. You can do this in code when you are displaying the cells themselves as some other answers point out, but I recommend against doing this as it can cause some other side effects when Apple makes changes to these components.
If you need to customize the position of these subviews, you should instead just build them manually. You can do this in interface builder by selecting the cell, then selecting the 4th tab on the right (Attributes Inspector), then change the Style to Custom. Once you do this, the default subviews will disappear in interface builder and you can just add your own.
You have chosen the default cell style for your cell. The Title and Subtitle labels for the chosen style you see are some basic UI controls that are meant to be used for typical scenarios of displaying content in a tableView usually. If the framing of the labels are comfortable and okay to you, then it is fine. If not, you need to make your own custom style cell.
Basically you cannot modify the default cell style that Apple provides. Just make the cell style Custom and do whatever you want with the layout.

hide/ show controls in View controllers

My application gathers input from users and hence it is full of Labels, text boxes and buttons and I have to show or hide set of labels and text boxes based on certain conditions.
To accomplish it, I did the following.
Set fixed height (lets say 30) for all the controls
Set height constraint on each of the controls and created an outlet to the height constraint in the ViewController
Alter the heightConstraint.constant value programatically (between 0.0 and 30.0) based on the scenarios.
Having programmed like this, it is very difficult for me if there is any change in layout. (i.e., if user requested to add/remove any particular control from the view Controller).
I am using Auto Layout constraints. Could anyone suggest if there is a better way to accomplish my goal.
I am using IOS9 and Swift.
Many thanks in advance.
You can use UITableViewController with static cells for this case.
For hide/show row or section, you can change the size in the tableView:heightForRowAtIndexPath method.
UITableViewController automatically manages the layout and with static cell you can even create outlet for all the controls.
Have you considered using a table for this? It has mechanisms for inserting and deleting rows and would manage the layouting for you - only part you'd need to care about are the contents of the cells.
Instead of making IBOutlets to the height constraints of all the views that you might need to hide, you can just use the hidden property of UIViews to hide/show the view.
In case you need the view to make space for other views, you could set a simple animation and move the view out of screen bounds. You might face issues with layout constraints but it's surely worth the effort from a UI/UX perspective.
Additionally, if you know that you don't need a view any more you can even remove the view from it's superview.

Can't see elements from storyboard inside viewcontrollers

some elements from my storyboard don't appear since I change the viewcontroller size to 4.7inch. But if I create another viewcontroller and I put some object inside, they are appearing. What's wrong with these viewcontrollers?
This is because the UI elements or constraints you have added to the view controller with specific size class will become inactive while to change to some other size class. for example the UI elements or constraints added to view controller with compact width | Any height will become inactive while you change to Any width | Any height.
You can enable it by checking the option in your attribute inspector[scroll down to the bottom]. Please refer to the screen shot.
If you want to display all your objects in different size classes, you should use auto layout....it manage your object to display in different size classes...
So, The solution to prevent your object to hidden from different size classes, use autolayout
Here is the image...that explains better than words
In this image I gave autolayout to button using wAnyhAny...for best practice..

Xcode IB: UIButton hidden but have still buttons space

I have the following issue in my iPhone app.
I have 4 buttons in my IB also linked to my UIViewController (IBOutlet)
When I for example hide the second button which is AfvalSoorten with [self.btnAfvalSoorten setHidden:YES]; then it disappears, that's what I want, but I still got the button space when I debug the app on the simulator.
How can I get rid of that?
Below there is an example.
Is there an option on the Storyboard for the buttons to clip together?
You should use autolayout. Otherwise it's a nightmare with the new screen sizes.
With autolayout you can do what you ask programmatically: setup the buttons with certain constraints and then when you decide to hide the button remove the constraints that are not needed. It's flexible and powerful but not the easiest way for a beginner.
One simple way to do it is with additional constraints. For instance, if you have buttons 1, 2 and 3 (see screenshot), and you plan to remove button 2, you can add an extra constraint between 3 and 1:
That constraint should have less priority (250 in my example) than the others (1000 by default). That mean that the constraint won't be applied when button 2 is in place (with higher priority constraints).
Then, remove the button instead of hiding it.
[self.button removeFromSuperview];
When you hide the button it still considered by the layout system to take decisions, and it makes layout more complex. If you want to keep the button around make sure it's using strong modifier in the property declaration.
A better approach for above scenario - You dont need to set any autolayout or frames :)
Use UITableView and create custom cell with UIButtons in it.
Set UITableViewCellSelectionStyle to None
Here your button background is same for all cell
Create an array with above button titles
When ever you want to hide buttons just remove it from array.
The modern preferred way of doing so is to use Stack Views. Great tutorial. Requires iOS 9.
You'll find the icon of stack view in the Auto Layout toolbar at the bottom right of the storyboard canvas.
You had just make it hidden.
You have to set the frames according to your need.
OR
You can set autolayout.
maybe there is a solution with autoLayout in IB but I'm not sure about that. Programmatically you can add all your button to an array in order. and whenever you hide a button or not you loop trough the array of button and each time you find one that is not hidden you set the y coordinate on the frame to a a value and you increment this value by what you need so the next not hidden will be placed according to the last position used.
You can add the buttons programmatically -> you will have the array
of Btns and method to add array to the view controller.
You can play with the Constraints and set Height Constraint for 2nd button when hide it to 0 but all buttons should be connected with the constraints in this case.

What do these settings do in Interface Builder?

This is for a UIButton specifically. I understand that the alignment options pertain to the label inside the UIButton, but what does the 'content' settings do? They seem like they correspond to the setEnabled:, setSelected:, setHighlighted: methods of the UIButton class, however clicking Highlighted or Selected doesn't seem to change the button's behavior outside of interface builder. Also, what would be the use-case for having a button always show highlighted or selected?
There are several practical uses for these methods. As #MHUMobileInc. pointed out, it can be used for a game like Minesweeper. It can also allow you to use the button as a sort of switch, where the selected button has "ON" and the non-selected version has "OFF". It seems that Apple wants developers to shy away from this, and to use either UISwitches or a custom view. However, Apple does contradict itself in some of its apps.
These settings set the initial state of the UIButton- so if in your viewDidLoad you set it not selected nor highlighted, this Interface Builder setting will not be seen on screen when you run the app. If you want to ensure that these settings are kept, it might be easier to say so in code (viewDidLoad) rather than Interface Builder.
It may be easier not to use these settings too much. They can lead to confusion for you (the developer), other programmers who are working on the project (if any) and the user. Use the built-in UIKit views when it works and create your own subclasses when there is nothing that fits best for the situation.
The upper portion addresses the alignment of the content within the view. For example, if you have a large UIButton with an image that's smaller than the bounds of the button, by default the image will be centered vertically and horizontally inside the button. However, if you want the image to hug the left/right/top/bottom, you can set the alignment using those options.
All of these controls pertain to the UIControl, not UIButton, as indicated by the header in that screenshot.
Alignment refers to contentHorizontalAlignment and contentVerticalAlignment. Many controls return a fixed width or fixed height, or both, from sizeThatFits:. For example a UISwitch object has a fixed size, whereas a UISlider object has a fixed height. If you assign a frame to a control object that does not correspond to these fixed dimensions, these properties determine where in that frame the control interface should be drawn. Instances of UIButton do fill their frame, so the UIButton class interprets these properties differently to apply to the button's content, but the properties themselves are not specific to the UIButton class.
Similarly the selected, highlighted and enabled properties are defined by UIControl not UIButton, not all subclasses of UIControl utilise them.

Resources