UICollectionViewFlowLayout - How do I get even row and column spacing? - iphone

UICollectionViewFlowLayout has two properties which state the minimum spacing for rows and columns:
minimumLineSpacing
minimumInteritemSpacing
How can I set a constraint where the spacing is equal? Setting both properties the same dose not do the trick since they are minimums.

Part of the issue here, of course, is that you are assuming that all items are the same size. That makes the idea of "evenness" pretty easy. But the flow layout does not make that assumption; it works the way it does because it is prepared to layout items of varying sizes.
You say "even" but you do not specify the conditions of evenness. How is this evenness to be attained? You have to consider what, exactly, you are after.
If you accept that the flow layout is going to space the items out so as to full justify them on both sides of the screen, then obviously the flow layout will use a larger horizontal spacing value than your minimumInteritemSpacing in order to make that happen. Clearly, in that case, you need a larger minimumLineSpace value if you want it to be more like the horizontal spacing that the flow layout is using. Alternatively, increase the sectionInset on both sides to reduce the horizontal spacing throughout.
If you do not accept that the flow layout is going to space the items out to justify them on both sides, then you can set the horizontal spacing exactly, but then clearly the items will need to be left justified (or centered), not full justified. You can do that by subclassing UICollectionViewFlowLayout.

Related

gtk height_for_width leading to unreasonable window heights for given width due to smaller minimum width

I am implementing a container which algins its children in a row and does kind of a linebreak when there is no horizontal space left. Thus, the required height depends on the available width. For larger widths, more content fits in one line and less lines are needed leading to less height. For smaller widths, less content fits in one line and more height is needed.
I subclassed the container and implemented the needed logic. The minimum width of the container is set to the minimum width of the widest child which would display one extreme case where there are stacked lines, some of them with only a single child inside them.
The problem is as follows: The window displaying the container has a very large height, for some cases even larger than my monitor. I am able to resize the window except that I cannot decrease the width. It turns out that the documentation for height-for width geometry management says:
Next, the toplevel will use the minimum width to query for the minimum height contextual to that width using gtk_widget_get_preferred_height_for_width()[...]. The minimum height for the minimum width is normally used to set the minimum size constraint on the toplevel (unless gtk_window_set_geometry_hints() is explicitly used instead).
Thus, the behaviour is expected as the window uses the height for the minimum width as its minimum height leading to the previously mentioned extreme case. This seems to be counterintuitive as in my case and an example used in the documentation (textflow in labels) the height will be maximal when the width is minimal vice versa. Only when actually allocating the available space, gtk considers to assign smaller heights when a larger width allows that. Even when using high widths in the window's default size and size request only the minimum width of the container is considered to derive the required height of the window.
The documentation already somehow contains a workaround, namely the geometry hints. But this seems to be a verbose and static way of sizing the window when the default width of the window together with the height-for-width-function could theoretically be used to easily determine the size of everything. The size-allocation already works as intended, only the size-negotiation cancels the benefits the height-for-width function could bring here. Is there any nice way of implementing the functionality required to fix the window sizing?
It seems as there is no intended workaround for this problem the way I searched for. The gtk size negotiation goes from bottom to top when requesting sizes and top to bottom when allocating. Thus, my container has no way of knowing how much width its parent could assign to it.
I solved the problem by adding a property which defines the minimum of children per row. This can be used to increase the minimum width and therefore decrease the minimum height. I only use it for the minimum width calculation while actually ignoring it doing the real size allocation which only is a minor detail I will document.
This documentation will be part of the code example I will provide as an answer to my old post which was about implementing a FlowBox with the behaviour described above.

Width limitations with constraints when window resized

I am trying to add a custom view in an nswindow in my osx app.
I need to give a minimum and maximum width values for the custom view which is located in the centre. The view's width should expand until a certain point (maximum width value) but should stop expanding if user continues to expand the window.
Thanks in advance.
You can do all of this with layout constraints.
First, we need to specify where the view should be relative to the window. For the sake of this tutorial, I'm going to assume you want it centered:
Next, we add our constraint for the minimum width:
To make this a minimum instead of an absolute width, click on the constraint and change it to "Greater Than or Equal" in the Attributes Inspector:
Now do the same thing, making another width constraint for the maximum. This time, set it to "Less Than or Equal":
Now the width constraints are set up. But we're not done. We've now set a minimum and a maximum, but the width is still ambiguous—there is no way for the layout constraint system to decide what exact width between 300 and 700 that it should actually be using at any given point. There are two steps to fix this. First, we need to make sure that the view will be entirely within the window and not run off the edges, so create some Greater Than or Equal constraints making sure it stays within its bounds:
(Also, make a trailing constraint which is set up identically).
Finally, we need one last set of constraints; we want some leading and trailing constraints, marked Equal, but with a lower priority:
(Also add a trailing constraint, identically configured)
What does this one do? Well, it tells us that, unless our other constraints (specifically the maximum width, in our case) make it impossible, we'd like the edges of the view to be the standard distance from the window edge. The reason we use 499 as the priority is because that the value of NSLayoutConstraint.Priority.windowSizeStayPut is 500. The documentation has this to say about .windowSizeStayPut:
It's generally not appropriate to make a constraint at exactly this priority. You want to be higher or lower. Constraints with higher priorities can adjust the window’s size. Constraints with lower priorities must be fulfilled using the current window size.
If we set our constraint to higher than 500, the system would restrict us from making the window too wide for these constraints to be valid. That's not what we want, since we want the edge spacing to expand in this case. So since we want to be able to break this constraint by resizing the window, we set it to slightly less than 500—so, 499. This means that the constraint system will try to put the view here, but if it can't do it because we made the window too wide, it will allow this constraint to break, although it'll still try to get as close as it can without breaking the other constraints. So your view will be at its maximum width, and centered in the window.
Voilà!

Auto Layout issues

I am trying to get a layout working where I have 9 squares set 3 x 3 and on all device sizes, they are square.
I have tried endless ideas to make it work but can't seem to get it to stay squares on all devices.
I attached below, a picture showing the results and current constraints on the top left corner square.
Any help would be awesome!
The best approach would be use the stackView. The advantage will be you do not have to deal with the much constraints. So select the first rows three view horizontally then click on the Embed in Stack button whose axis should be horizontal inside your storyboard. Follow the same for second and third rows. Also inside stackview you can mention the spacing you want.
So now you have three stackView for all the three rows. After that select all three stackView then click on the Embed in Stack button and whose axis should be vertical and you can mention the spacing you want.
So advantage of doing that is you do not have to worry about the constraints. Finally you only have to apply the constraint on your main stackView which hold all your child stackView
While I totally agree that UIStackView is a great option, you can also add Aspect Ratio constraints (with a Multiplier of 1) to your squares and ensure that they remain squared (as nothing about your current layout demands that your views should be squares).
If you want your 9 squares to remain in the center of the superview, I recommend adding them to an invisible intermediate view and center that within the superview.

What is wrong with these auto layout constraints?

What I aim:
I want to have a table cell, in which every cell is horizontally divided in two halves. The upper half will contain 4 labels, and the lower half will contain 4 values which correspond to these labels.
Of these 4 items in every horizontal half, each of the last 3 items will occuppy 2/7 of total width, and the remaining 1 item will occupy the remaining of the total width, which is 1/7 of total width.
What I tried:
Putting a horizontal stack view in the content view of table cell.
Which will contain two vertical stack views
Where the upper vertical stack view will contain the labels and the lower vertical stack view will contain the values.
In short, I did this:
But I am getting these conflicts:
I really don't understand why I am getting these conflicts. I feel like I have provided enough constraints for auto layout to do the layout correctly.
Could you please tell me what is wrong here?
I'm on Xcode 8 and using iPhone 7 Plus as view, if that would make any difference.
This is a simpler case, and it isn't working as well:
Conflicts:
As you have provided the detail nobody can get understand and help to resolve your auto-layout issues, I suggest you to clear all constraints and try re-apply all the constraints again , give proper leading and trailing with x and y position the constraints will definitely works good,
Once you will try to apply twice or thrice you ll get know the exact problem and it will be get resolved quickly.
For auto-layout more practice needed to understand it briefly.
Hope it will help to you,
Thanks.

UILabel Text Not Wrapping

I am working on a Swift project with Storyboards where I want text to wrap in a label. In the old Objective-C version where I did not use a Storyboard I used the following settings and things worked perfectly.
Here are the settings for Swift
I have been reading about the potential auto layout issues with preferred width settings. I currently have them set to auto layout and the label itself is set to a width of 560. I've added a constraint to keep the label 20 pixels from the trailing superview and while I thought this would work I still cannot get the text to wrap. The dimension settings are below.
Can someone explain how to get the text to wrap?
First, the good news: You have set the label to 2 lines and Word Wrap. So it can wrap. Excellent.
Now you must make sure the label is tall enough. Either give it no height constraint, or give it a big enough height constraint that it can accommodate two lines.
Finally, you must limit its width. This is what causes the text to wrap. If you don't limit the label's width, it will just keep growing rightward, potentially continuing off the screen. The limit on the label's width stops this rightward growth and causes the text to wrap (and the label to grow downward instead).
You can limit width in several ways. You can have an actual width constraints. Or you can have a leading constraint and a trailing constraint, to something relatively immovable, such as the superview. And there is a third way: on the Size inspector (which you do also show, at the bottom right of your question), set the Preferred Width (it is shown at the top of the Size inspector): this is the width at which, all other things being equal, the label will stop growing to the right and wrap and grow down instead.
Declare your UILabel programmatically and give
yourUILabel.contentMode = .scaleToFill
yourUILabel.numberOfLines = 0
yourUILabel.leadingMargin(pixel: 10)
yourUILabel.trailingMargin(pixel: 10)
This worked for me.
Your text will wrap if you have provided lines number more than 1. However you may not be able to see it wrap if the label height is not enough to show the content. I suggest you to remove the height constraint or increase its value.
In case this helps anybody: I had followed the advice given here to fix my label not wrapping to two lines but nothing worked. What worked for me was I first deleted some of the relevant constraints in storyboard (I'm using auto layout) and saw that the label wrapped properly. I slowly added back the constraints I needed and everything still seems to work fine. So deleting and remaking your constraints may help.
What fixed this problem was changing the label type to "Placeholder" under Intrinsic Size in IB. When I changed this the text wrapped and the warnings went away.
As I see you interface builder. There are two problems. First one is with your constraints, and another one is with the property.
You gave it a fixed height which is wrong while line wrap. You need to make the auto-resizing label, i.e. remove height and add the bottom constraint or simple remove height depend on your situation. Your text is moving to the next line, but due to fixed constraint, you can't see it.
You enable the option to clip subviews which is wrong as it cuts your view and you are unable to view wrap word.
Add a new case:
DO NOT add constraints to your label with a TEXTVIEW, or the label will expand to right without limitation.
In my case i set my parent stackview alignment from center to fill and set UILabel to
label.textAlignment = NSTextAlignment.right