Dynamic scrollView size for variable content - ios

I stand in front of a new problem for me. I have the following layout in my storyboard.
In this Layout you see a scrollView that have always the same content on top and some boxes at the bottom. These boxes should be variable, so I want some of them turned off and some turned on. I already tried to say something like mapBox.hidden = true or mapBox.removeFromSuperview().
The problem with that is if I do that the box is hidden, but the space of it is always there, because of the constraints I think.
I already done it on Android, there you can give them boxes just a margin and when you make dem hidden the following box have just its margin to whatever was on top of the hidden box.
What I want is the possibility to turn some of the boxes on and off with always the same distance between all not hidden boxes and a scrollview thats just big as its content.
I hope you can read my maybe unintelligible english and can give me a hint.

What you could do here instead: Make the whole layout a table view. Then, the top part (that always stays the same) could be added as the table header. The mapbox and headline boxes would both be table cells (use custom XIB files). Then, you can have one array that represents which boxes, along with which other cells you would like to display, and update that array depending on the situation. A Table view will adjust the size of its scroll view based on the size of content.

You probably know that the big issue here is the basic design. As #IanRichard said, this should be done using a table view. However you still can make some workarounds if there's no other way out.
You can set the constraints in such way so that an "undesired" view gets hidden. Here's an example for textBox and mapBox, but can use the same for all boxes:
You probably have one constraint connecting the bottom of the textBox and the top of the mapBox, and the priority is probably 1000. Change this priority to 999. Then add one more constraint connecting the TOP of the textBox and TOP of the mapBox. Set the priority to 1 and constant to 0. Next, in the same way as you were making outlet connections for other view elements, make two more outlet connections for this both constraints. You'll need them later when you will switch the priorities.
Here's how your outlets should look like:
IBOutlet var myConstraintBotTop : NSLayoutConstraint!
IBOutlet var myConstraintTopTop : NSLayoutConstraint!
Then in your code you can "turn your views off" by just setting the appropriate constraints:
func turnOffMyBox() {
myConstraintBotTop.priority = 1
myConstraintTopTop.priority = 999
}
And here's the inverted version for "turn on" in case you need it:
func turnOffMyBox() {
myConstraintBotTop.priority = 999
myConstraintTopTop.priority = 1
}
Note: this approach works by just overlapping your boxes. Those boxes still exists. You may want to hide them to prevent from being seen by the user.

Related

iOS: How to have the container view automatically shrink its height when the content label is hidden?

I have a view with two Labels contain in a view as below. They are all constraint 8' from it's side to it's parent view (in grey color). The size of the view basically wrap around the 2 Labels. (like wrap_content in Android)
When both of them coexist, it should display as
Sometime one of them would exist, and I want the container view to shrink as below
or
Notice the size of the container view should shrink to just wrap the contain.
(Note: I'm an Android Developer, and starting to learn some iOS work. The above could be easily achieve in Android by hiding one of the Label, the container view would then shrink accordingly, as per show above desired result.)
However, when I do the hide as below
labelTwo.isHidden = true
It shows as
And when I do
labelOne.isHidden = true
It shows as below
I ask around, seems like I have to manually code in swift set the height = 0 of the hidden Label and remove the relevant constraint programmatically. I find this seems too complicated for what I think should be simple. So asking around to see if there's a simple way to achieve this (e.g. can we use padding instead of constraint, like in Android?, is there a GONE feature as in Android's view?)
Is there a way to easily achieve what I want?
You have two easy ways to do this.
1) Use UIStackView
2) Use height constraint
let heightConstraint = secondLabel.heightAnchor.constraint(equalToConstant: 0)
later disable the height constraint when you want to show the view
heightConstraint.isActive = false
You can also create an #IBOutlet on the height constraints and use that variable.
#IBOutlet weak var someConstraint:NSLayoutConstraint!

JSQMessagesViewController Custom Cell Auto layout Issue - IOS

I am using JSQMessagesViewController and I created a custom cell according to this answer.
How to add custom view to JSQMessagesViewController cell so that it includes one view with some buttons and text view?
Now I am struggling to set auto layout constrains correctly. So, the message bubble not display correctly. Please help me set the constraints correctly
So lets take a stab at this. So first things that I would do it set a constraint for the first button to be equal hight of the other. You can accomplish a couple of ways but I will only describe one here for brevity. You can do hold the control button on your computer and select button1 and drag to button2. This will present you with a couple of options that look like this.
You want to select Equal Heights this will make it so both your buttons have the same hight. Then you will want to give it a hight. Once again hold down the control button on your keyboard but this time click button1 drag and release within button1. you should get something along the lines of this.
If you do not get the desired options try dragging in a diagonal direction. Xcode is tying to guess what constraints you want based on the direction of your drag. I.E. If you drag vertically you should get the Height option.
Then you can go to the properties inspector on the right and set a number for how high you would like. Text is normally around 12pt so I would go with about 30pt or more for the hight of a button. Then add a constraint for spacing between them and leading and trailing to the containing view or you could give them a standard width and center them in the view. Which ever fits best for you.
Edit:
You should also adjust the bubble size calculation.
It can be found in the JSQMessagesBubblesSizeCalculator class.
Eg: In the
- (CGSize)messageBubbleSizeForMessageData {
if([messageData isOptionMessage]){
// add button height also (In this case i have set constant 200. But we have to calculate the actual button heights instead)
finalSize = CGSizeMake(finalWidth, stringSize.height + verticalInsets + 200)
} else {
finalSize = CGSizeMake(finalWidth, stringSize.height + verticalInsets)
}
}
Let me know if you need any more help and keep up the good work. 👍🏼 🚜

UIScrollView and variable text size

I'm creating an app with quite a lot of text. It will be of variable size, so I was wondering if there is a way to adapt my ScrollView to the size of the UILabel, not knowing in the IB what will be the number of lines of that label. I'm doing it from the IB, drag n dropping it, then I'm putting 4 elements inside : an image for the logo, a title, another image, and then the label.
My question is : how can I tell my ScrollView to adapt to the text ? With constraints ? In the code ? I'm sooooo lost with that scrolling thing…
I think I need a very very good tutorial about autolayout…
Here's some screenshots of my project
The project on simulator
The layout
Thanks a lot!
You have to add the constraints to your label so that it will always have the same spacing to the scroll view. Also, you will have to set your labels lines to 0.
Don't press Add Missing Constraints because it will probably set your height and you don't want that to happen. Use the Pin button to set the spacing to nearest neighbor.
These are the buttons you will have to use, they are bottom right.
First of all, press the one in the right and select All Views > Clear Constraints.
Then, select your label in the storyboard and press the button with a square Pin, here you will have to select everything until you have something like this with different values... Also click in the red lines so that you get a continuous red line. Don't check any of the boxes you see.
After this, you have to do the same process for your Scroller.
It should be enough. I will also need to know where your scroller is.
If you have anything else in your view, do the same.

Fill UIScrollView with its content using autolayout in iOS

I am making a form based UIScrollView, which will contain some labels and text fields.
My ScrollView Height will increase as per the iOS device height.
PS: I do not want to add constraint to each and every element of the Scrollview, because in my case there could be 100 form fields.
What I want is, the inner content to fully occupy my scrollView like this:
Till now there a are no special constraints, the button is tagged with the bottom edge and the scroll view is pinned from the top edge. Also, the vertical spacing between scrollview and button is defined.
This is the autolayout constraint screenshot.
If the number of labels is variable, I recommend doing them in code, rather than in Interface Builder.
In code, you can use a loop to set every label to have the same width/height as the one above it. You may want to set their height to be >= a minimum value. Be sure to anchor the first label with the top, and the last label with the bottom.
But this can be cumbersome, why not just use a UITableView? you may modify the row height to let the cell fully occupy the view.
- tableView:heightForRowAtIndexPath:
- tableView:estimatedHeightForRowAtIndexPath:
I just face the same issue and already write a pod called TLFormView that do exactly that: a form based on UIScrollView.
It also has some nice features like:
declarative form taxonomy with TLFormModel Just extend it, add the properties you want and that's it. No delegate, no event handling, no boilerplate.
a nice way to handle different layouts for iPhone and iPad
conditional visibility with an NSPredicate that can access all the values in the other fields (e.g: show field A when field B has certain value)
in place help with a popover
all the fields are TLFormFields that extend UIView so you can place whatever you need.
You can try it right from the command line with pod try TLFormView.
If you want to know more I wrote some blog post about it here.
Please let me know your thoughts about it here or as a comment in the blog posts. Also any contribution is extremely welcome in the GitHub repo

How to make a fluid layout in iOS?

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.

Resources