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
Related
I'm building a FeedViewController for my app.
This screen consists in a tableView (or a collectionView), that shows users' posts. A post always have a content, and it can include or not an image.
I was wondering what is the best way to handle the case when there is no image to display, how do you handle the height of the table view cell and assure that the spacing between each item remains the same?
What I've tried :
I created a subclass of table view cell and inside I added some constraints. Within the cellForRowAtIndexPath method of my FeedViewController, I added an "if statement" to check whether the postImageView.image is nil or not, and update the height constraint of the post image accordingly. The problem is, as you can see in the screenshot below, the spacing slightly differs from a cell with an image, to a cell without an image. I would like the spacing between elements to be exactly the same, no matters if there's an image attached to the post or not.
How would you guys solve that problem ?
Thanks for your help,
J.
If you use the autolayout then u need to give bottom and top constraints to buttonlabel. OR if you use the autoresizing then you need to fix the position of buttonlabel. #jellyfish6
I think you have given BottomConstraint for "Bottom Label" that is the reason why it is having different spacings.
I guess instead of giving bottom constraint provide it with top constraint or both and manage it with priority.
I've been trying for days to make one layout of my app to work well, and after days of learning and mistakes I still can't get the table cell layout to look how I want it to be.
This is how my cell .xib looks like in the editor:
http://i.stack.imgur.com/VEr3r.png
And this is how my app looks like when running with suggested constraints:
http://i.stack.imgur.com/wiK1f.png
Why is that? How I can find my mistake and make the layout like it supposed to be, in the view?
Suggested constraints are rarely what I actually wanted to see.
For each label with fixed text, lock the horizontal and vertical positions either to the view or to the next adjacent item.
For imageViews, choose the size you want and lock the height and width.
For labels that you will be dynamically changing the text on, pick a size that will hold the longest string and lock the width. You'll need a vertical position constraint.
You have many options to simplify your layout.
you can use the stakview or create a static UITableView and insert your component inside the cells and enter the Constraint. excellent tutorial http://www.runtimecrash.com/2015/09/17/exploring-uistackview/
I have a cell that contains a container with 10 subviews (two of them are simply bounds and the others are labels). The scheme looks like this.
Dynamic labels may contain huge text so the cells should conform the appropriate size to fit the content. The question is how to set up all the constraints manually... I've tried a dozen of times to do it myself but seems I'm not that good at this. The table view supports auto dimension for row height and uses custom estimated height.
In Storyboard it looks this way.
Where blue views are a subviews of View C. A grey view behind is a View B. Bold labels are static and the others are dynamic.
Demo project.
How to setup constraints?
Thank you very much in advance!
I managed to setup your constraints so that you get the result you needed. This is what I get:
I hope this is how you wanted it to look like.
Here is a link with the project.
I will try to explain how I added the constraints so that it makes more sense.
First of all, you have view B which needs to be as big as the contentView. For this you add top/bottom/left/right constraints to the superView. Because you are using automatic dimensions, if you add all constraints with priority 1000(the maximum one), you will get some error with the constraints while running. This is because, before the cell size can be calculated automatically it is zero, so the constraints crash. Therefore, I set the priority for top and trailing space with a priority of 999 so that you don't see the error log anymore. The result is the same.
Then views C needs (top or bottom)/left/right and height constraint
Then you need to add the constraints for the labels. Since you need the right ones to have multiple lines, the constraints need to specify the vertical layout for this particular case. So, you have as follows: first label: top/left to name label and right to super view. All the other have top to the previous one,and bottom to the next one.
for the labels that don't need to resize you just need leading space to parent,horizontal space to the right label and static width. Also, you will need a constraint to align the top with the label on the right.
This is the result I get:
Hope my explanation made sense, just let me know if you have questions. Good luck with your project!
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.
I have been struggling with IB and auto layout and figure there must be an easier way to create a simple scrollable form with multiple fields on it. The width can adjust to the device screen width (or in the case of the iPad to the details view of a split view.
The basic layout is simple a label and underneath a field (in some cases the field must have a minimum height) repeated for each attribute.
I think I must be doing something completely stupid or IB's autolayout is hopeless, I suspect the former. In any event whatever I do in IB fields just adopt whatever constraints they feel like it seems. Even when I set a constrain it seem IB just replaces it sometimes.
Currently I am using a view with a fixed height and width that fits the screen and laying out fields on this form, however its a complete nightmare having to pin every field in almost every direction. And then IB complains about a million constraints that it can't satisfy.
Hopefully someone has a better way of doing this they are willing to share - perhaps it might be best just to write some code to set up the constraints rather than relying on IB ?
Thanks
You are right UIScrollView and autolayout is not clear at first look.
You have to understand that when you are adding layout constraints for a view inside scroll view, the superview is content view of scroll (not the view of the UIScrollView) that can be more or less then current view of the ScrollView in IB.