ios autolayout constraints to resize view for screen size - iphone

I am new to ios development and still trying to get hang of autolayout. The problem that I am facing can be better explained with images below
Now I am removing the "Login with a social network" on iphone 4. What I want is how to center the google plus icon between the "OR Label" and "Start without registering" button
and it should also resize to fit between them.
what kind of constraints does it need to achieve that. If someone can point me in the right direction that would be great help. I have been breaking my head over this entire day. Thanks.

to center [g+] between [or] and [start ..] buttons:
you need to do two things.. on the storyboard:
select [g+] and [or]
select editor->pin vertical spacing
and then
select [g+] and [start]
select editor->pin vertical spacing
you should see a vertical line show up between the two objects each time. This is to indicate that that space will always be the same weather on a 3.5" or a 4" iPhone display.
I don't see why you want the g+ button to resize.. that actually goes agains the UI guidelines which instruct that different users shouldn't have different user experiences (see the reason behind why there isn't a replacement for the iOS 7.0 deprecated sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode: method)
The same logic that discourages changing font sizes on labels/buttons depending on form factor etc resulting in different users having different experiences, is the same logic that would discourage you from scaling up or down your [g+] button depending on form factor circumstances as well.

If you're just trying to get the "g+" graphic centered between the "OR" label and the "Start without registering" label, you can:
Add a view (that you won't really see because you'll make it transparent, but it's useful for alignment purposes) whose top constraint is linked to the "OR" label and whose bottom constraint is linked to the "Start without registering" label:
Then put the "g+" graphic inside that view, aligning its center vertical and horizontal constraints with its superview's.
If you do that, the "g+" button will stay in the middle between those two labels (assuming, of course, that the "Start without registering" label has a bottom constraint to its superview, i.e. It's pinned to the bottom of the view).
In terms of resizing that button, I'd personally advise against that, if you wanted, you could, for example, remove that transparent view we created above, and just do that trick with the "g+" image/button itself. You will want to set the content size of that imageview to be "Aspect Fit" (so it doesn't get distorted).
Again, I really don't like that latter approach, but you can do it.
I gather that you want to remove the "Log in with social network" label at runtime. There are two approaches for that:
A simple approach is to create an IBOutlet for the height constraint for that label, e.g., logInWithSocialNetworkHeightConstraint and then you can do:
self.logInWithSocialNetwork.text = nil;
self.logInWithSocialNetworkHeightConstraint.constant = nil;
[self.view layoutIfNeeded];
The alternative is to define a constraint between the "OR" label and the "g+" graphic's appropriate view. This, itself, has two possible approaches:
You could define this in IB, but define it with a priority less than 1000. Because the constraints for the "Login with ..." label will have higher priority, when that label is there, those constraints will take precedence. If you you remove the label:
[self.logInWithSocialNetwork removeFromSuperview];
[self.view layoutIfNeeded];
Then the new constraint you defined will then come into play.
You could alternatively remove the "Login with ..." label and then programmatically add a new constraint between the "OR" button and the "g+" graphic's view.

Related

Xcode: align objects with the View Controller margins

I'm starting to study Swift with the help of this Apple's guide : https://itunes.apple.com/it/book/app-development-with-swift/id1219117996?mt=11
Now i am stuck on a small problem that i would like to understand how to solve, but from the guide it is not very clear.
I'm at the 398 page : “Guided Project: Personality Quiz”.
Initially i have to place 4 labels in all the corners of the view controller.
From the guide:
“To hold your emoji in their respective corners on all screen sizes,
you'll need to add two constraints to each label. Begin by selecting
the top-left label and clicking the Add New Constraints button. Enable
the top and leading constraints and set them both to 0 pixels,
ensuring there's no space between the edges of the label and the
margins of the view. By default, the top of a view has a 20-pixel
margin, and the left and right sides have 16 pixels of margin. So when
you enter 0 pixels, you're actually telling the label to position
itself 20 pixels from the top and 16 pixels from the left edge of the
view. Add these two constraints”
So, following the guide, i place the first label in the upper left corner, and add the two constraints
And this is the result. The label is aligned to the Safe Area and not to the view margins.
Looking to another project (not mine), i think the two constraints that i need are these (or something similar):
I'd describe that as a bug in Xcode. You asked for margin-relative constraints and you didn't get them. That's not very nice!
You'll just have to edit the constraints afterward. In your final screen shot, double click a constraint. Use the pop-up menu to change the Safe Area constraint to a Superview constraint. Then choose from the menu again to check Relative to Margin. Then you might have to fix the Constant value. Do that for the other constraint too.
Either that or just don't use the constraint popover to begin with. Instead, draw your constraint by control-dragging from the button and use the HUD that appears. Hold Option in the HUD to get superview margin constraints.
EDIT Ooooh, here's another workaround; before you form your constraints, hide the safe area layout guides (uncheck the 4th checkbox in this screen shot):
Now the constraint popover works correctly.

NSOutlineView disclosure triangle vertically off center

I'm working with an NSOutlineView on a macOS app and it provides disclosure triangles for items that can be expanded.
I'm also creating custom NSTableCellView items rather than using basic cell items. This allows me to create the cell how I want visually.
My issue is that when they're displayed, the disclosure triangle on the left is not centered vertically.
Notice how the disclosure triangles are not aligned properly. They're a bit lower than they should be. If you scroll away and come back, sometimes, they automatically align themselves correctly. Has anyone been able to fix this issue before?
For what it's worth, I'm using the following code as well for the cells.
self.outlineView.rowHeight = CGFloat(integerLiteral: 66)
self.outlineView.usesAutomaticRowHeights = true
It's hard to figure out what the problem is without seeing how you've set up your project, but I'm going to give it shot.
First, when usesAutomaticRowHeights is set to true, the outline view uses Auto Layout to position the cell views. Thus, you need to be utilizing constraints in your Storyboard or Nib file, or things will behave strangely (see: your picture). If I had to guess, the prototype cell view you set up in Interface Builder is having its autoresizingMask translated into Auto Layout constraints (which, generally, causes a boatload of problems).
What I would do is this:
Open up the Storyboard or Nib document containing the outline view.
Locate the prototype NSTableCellView instance that contains the street name text field in the Document Outline to the left of the canvas. (If you don't see the Document Outline, you can open it by clicking the item at Editor » Show Document Outline in the main menu).
Next, see if you have any constraints in place. If you do, remove them by selecting Editor » Resolve Auto Layout Issues » Clear Constraints under the menu item "section" that's titled All Views in ${YOUR_SCENE}.
Now, depending on what you're going for, there are different ways to go about setting up constraints, but here's what I would suggest. Assuming you want the street name to be centered vertically with the disclosure triangle, I would add a vertical constraint between the text field and its parent cell view like so:
With the text field selected in the Document Outline, click the Align icon in the lower right-hand corner of Interface Builder's main canvas area (see image).
In the popover that appears, check the checkbox next to Vertically in Container.
In the text field on the right side of the popover, enter a value of “0”.
Finally, click the “Add 1 Constraint” button.
You’ll probably see a red error (or yellow warning) sign show up, as the view has now opted into Auto Layout, but it only has a metric for its vertical position. So we now need to add some constraints to describe where the text field should be positioned on the x axis. Like before, we’ll define the constraints using the popover buttons on the lower right-hand side of the canvas:
Click the Add New Constraints button (the one to the right of the Align button).
On the diagram at the top of the popover, click the faint red lines on the left and right side of the white rectangle. This is telling Interface Builder we want to add leading and trailing constraints.
Now, enter the desired padding you want on each side of the text field. In the example image, I went with “4” points on both sides, but obviously, you can use whatever value(s) you think works best with your layout.
Finally, click the “Add 2 Constraints” button.
Any warning(s) that were present should now disappear, as we've added enough constraints to describe the position of the text field. In theory, you should now be able to build and run your project, and the text fields should be aligned with the disclosure triangles. With that said, there are plenty of other reasons a layout can get finicky, and considering usesAutomaticRowHeights is a new API in macOS High Sierra (and Steve Jobs is no longer there to beat it into Apple developers to make everything Just Work™), there could be issues that I'm unaware of.
Alternatively, you can set usesAutomaticRowHeights to false and have some object (e.g. a view controller, a NSObject subclass, etc.) conform to the NSOutlineViewDelegate protocol and implement the outlineView(_:heightOfRowByItem:) method to return any arbitrary height you want for different rows. The nice thing about sizing rows this way is that you can allow certain rows to be larger or smaller, depending on the role of the corresponding item. There are lots of tutorials on this, so I won't regurgitate a half-baked explanation here, but feel free to Google “Conforming to NSOutlineViewDelegate protocol” for more info.
Anyway, try the steps above, and see if they do anything for you, and if they don't, let me know. I can go as deep into the rabbit hole with you as you need, so just ask. Good luck!
For those like me who stumbled upon this issue many years later, here's the fix that worked for me, and requires a lot less work.
NSOutlineView has a function frameOfOutlineCell(atRow:) and the documentation states: You can override this method in a subclass to return a custom frame for the outline button cell
You can override the method in order to provide a frame that's actually in the vertical center of the row. And an important point that I learned from trial and error, is that you don't even need to provide that updated frame. Not sure if this is a bug or what, but for me, just calling super.frameOfOutlineCell(atRow: row) in the function override was enough to make the disclosure indicator appear in the correct location.
So my subclass of NSOutlineView is this:
class MyOutlineView: NSOutlineView {
override func frameOfOutlineCell(atRow row: Int) -> NSRect {
super.frameOfOutlineCell(atRow: row)
}
}
That's all. Hopefully that works for others as well!

AutoLayouts, Contraints, UIView and re-sizing

I have attempted to search for AutoLayout, Contraints and several other items, but I can't seem to find an easy answer to what appears to be a simple issue. Below are two screenshots. The first one is a 4" iPhone in Storyboard, the second is the 3.5".
At the bottom, I have a "UIView" that sits on top of all the other layers and will only pop-up when I hit a "share" button. See my problem? I want to maintain the same size for the UIView on both the 3.5" and 4". As you can see, it grows and doesn't look as good on the 4" screen. What settings need adjusted in order to make this happen. I know it's going to be a constraint setting.
Simply select the black top UIView, and in the IB window add a height constraint.
To do so, search for "Pin" menu in the bottom right corner of the window, and select "Pin Height".
This tells Xcode that you want your view to always keep the same height. Note that this will probably make one of the previous constraints of your view useless (in my case I deleted the "Top Space" one).

Vertically add elements to a scrollview: diffs between Java and iPhone SDK?

Folks,
coming from the Java/Swing world, I am sometimes puzzled by the UI programming on the iPhone. I've spent the last hours with Googling for information but it seems that I asked the wrong questions by thinking too much in Java. Could you please point me to resources to get more familiar with the GUI concepts to be able to achive the following functionality:
Basically, I want to create a vertically scrollable view that represents structured text (for example, a recipe). Each step consists of a title and a textual description. As I want to fold and unfold such steps, the title would be somehow interactive and by clicking it the description would be displayed or hidden.
In Java, I would create a component that renders one such section. The layout manager would compute the components preferred height (with or without description being displayed).
Then, in Java, I would create a panel with a vertical layout manager and sequentially add my components. This panel would be placed in a scroll pane; the scroll pane would ask the panel to layout itself and then show a viewport on it, if for example the height is bigger than the scroll pane's height.
What Java provides me is:
layouting of elements (computing their preferred height and width), thus no need to deal with coordinates and dimensions
dynamic creation of UIs by creating and adding components during runtime
What I understood on the iPhone:
I can dynamically add views as subview to a view, e.g. a scrollview by calling addSubview
I can even remove that stuff using removeFromSubview (as explained here Clear content of UIScrollView)
What I don't understand on the iPhone:
does one view always correspond to a visible screen (I did use tab and navbar navigation so far and there whenever I set a new view, it fills the current visible screen minus the space needed for the two bars)?
or is it possible to define a view that contains a label on top ("north") and a text in center; if so, could such a view automatically determine its height?
can I realize my example in a similar way like in Java or would I need to calculate all dimensions and coordinates of the individual components on my own? (This example seems to touch on that topic: iPhone scrollView add elements dynamically with id)
Alternatively, could I use a WebView and render my stuff as local HTML using JavaScript to show or hide nodes?
Thanks for any hint or link!
There are no layout managers in Cocoa, views are being reposition according to their struts and springs settings. For information on that read the documentation: http://developer.apple.com/library/ios/#documentation/DeveloperTools/Conceptual/IB_UserGuide/Layout/Layout.html
To create a "view that contains a label on top and a text in center" you create a view with subviews - one being a label at the top, second the textview in center. If you configure struts/springs for all of subviews properly, they will autoresize when the container view is resized.
You should also get accustomed to Interface Builder, creating views in code is real pain in the ass.

distribute option in interface builder of iPhone

i have following buttons in my application.
Now i want to set equal spacing among all buttons.
Suppose If I am using corelDraw or Photoshop, there is always an option for align & distribute.
Here I need to distribute my objects vertically.
How is that possible in interface builder of iPhone?
Sample image is given below, in which distribution is required.
alt text http://img268.imageshack.us/img268/4146/problem13.png
I know this post is ages ago, but for the sake of simplicity (maybe) and to avoid using table views (for sure)...
In your example, if you select the first UIButton, keyword, and press option key, interface builder shows you the relative distance from the center to any other object you hover with the mouse. So if you decide the optimal distance is the one between keyword and category buttons, you can apply that distance for the rest of objects simply adding or substracting the appropriate amount of pixels from the button size inspector.
Hope it helps!
Depending on the type of object, you might do this.
Select all implied objects.
Select Editor->Embed in->Matrix;
this will place the objects regularly.
Then select the option Editor->Unembed
and the objects will keep their new positions. Hope this helps!
I dont think there an option to do it automatically, you can do some math though and get them to have equal spacing by setting their frames...
Another option is to place all of these in a table (since they look like table view cells anyway), and adjust an empty footer view height to get the spacing you want between elements.
Of course that means you don't get to view the layout in IB.
It's even simpler - Simply drag a "Flexible Space Bar Button Item" from the Object Library in Xcode into each gap. It will automatically expand to equispace your other items.
&