Set toolbar button width appropriately in Interface Builder - swift

I've created a blank project, and added a toolbar to the main window. To it, I've added two "Textured Rounded Button[s]" from the object library. I've left one as-is, and the other I've customized by setting the image.
At runtime, they look correct, with the correct width automatically inferred:
However, this doesn't match the interface builder preview:
The button's width was set when it used to have the title "Textured Rounded", but it didn't readjust its width after removing the title and adding the icon.
It bugs me that my IB preview and runtime UI don't match. Of course, I can hand-tweak the button width, but that:
Suggests to me I'm doing it wrong
Is going to break in the future, similar to how my mis-configured toolbar buttons started looking wonky in Big Sur.
What's the correct way to add a button to a toolbar, in interface builder?

Related

View Container with View Single Title

I have a singular view residing in a view container, and I wish to have one title encompassing them. For instance, this view's default position is in the panel, but when moved to the activity bar in another view container, the title is displayed as [view container title]:[view title]. While this makes sense, it would be nice to display my view as [view or view container title], without a colon expecting a second part. The VSCode standard views like Problems, Output, Debug Console exhibit the wanted behavior. They just display as "Output" or "Problems" when placed in another container, rather than something like "Panel:Output". Is it possible to have a single title with no colon/second part? Thanks.
You may try to use the contextualTitle property of the view. Based on its documentation when launched, it should fit your needs:
https://code.visualstudio.com/updates/v1_46#_flexible-layout
For extension authors contributing views or view containers
When views are moved around the workbench, they sometimes need to be presented differently, either with an icon or extra context if they aren't in their default location. When contributing a view, authors may now provide an icon property and a contextualTitle. If not provided, these will default to the icon and title of the view container to which they are contributed.
I'm not sure they updated the API or updated the behavior since then but, if not, you will probably face the same issue I had while trying to use it. I even opened an issue to the VS Code team (https://github.com/microsoft/vscode/issues/102447), but they marked the issue as designed and I gave up on using it.
Hope this helps

How to avoid NSTrackingSeparatorToolbarItem from overflowing when resizing a SplitView?

I am working on a macOS app and I programmatically adding NSToolbarItems following Apple's documentation and I am adding the new NSTrackingSeparatorToolbarItem to support the new macOS 11 toolbar look and feel.
The tracking separator seems to work fine as long as I don't resize the split view below a certain width, then the separator breaks out and just looks out of place.
The tracking separator working as expected
And the separator breaking out when the split view size is below a certain width.
Is there a way to avoid this?? I know that I can set a minimum size for the split view, but is there a way to keep them synchronized (I don't want to hard code a minimum width)?? Especially if the user adds toolbar items dynamically.
Thanks in advance.
Ok I think I figured it out...
I noticed a interesting behavior when playing around with the Mail app, which when the preview pane is showing the NSTrackingSeparatorToolbarItem follow the resizing of the split views but the moment the preview is collapsed the toolbar changes appearance and becomes like a static toolbar. Furthermore the NSTrackingSeparatorToolbarItem stays in place and looks just like a normal toolbar separator (like you might find on other OS's).
So I played around in IB with my toolbar and discovered my error, my NSWindow had the titlebar set to transparent!!
I unchecked the option and voila I could replicate the look and feel of the Mail app, all automatically.
this property has to be set to false in NSWindow
#available(macOS 10.10, *)
open var titlebarAppearsTransparent: Bool
And of course the toolbar style should be set to unified
#available(macOS 11.0, *)
public enum ToolbarStyle : Int {
// The default value. The style will be determined by the window's given configuration
case automatic = 0
// The toolbar will appear below the window title
case expanded = 1
// The toolbar will appear below the window title and the items in the toolbar will attempt to have equal widths when possible
case preference = 2
// The window title will appear inline with the toolbar when visible
case unified = 3
// Same as NSWindowToolbarStyleUnified, but with reduced margins in the toolbar allowing more focus to be on the contents of the window
case unifiedCompact = 4
}
Please note that the break out behavior still occurs but when this happens the toolbar changes look and feel and you don't see any ugly split view divider line like I had experienced. Hope this helps anyone else who might run into this issue.

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!

Swift - Auto constraints

I am trying to use the auto size classes from the storyboard on xcode 7 to position UI elements in a controller. The problem that I'm running into is that when I try to use the "Add missing constraints" function (located at the bottom right corner of the console), it positions my UI elements correctly except for the last elements (pictures describe better). The first image below shows the storyboard file where I just want 3 buttons (stacked above eachother) to be the same width and length to be on the top right corner of any screen.
However, when I add constraints and run the simulations, it seems like the top two buttons are positioned correctly with the correct length and width but the third button is out of place (image below).
So my question is, am I forgetting a step to make all buttons position themselves? Or should I try to convert everything to a percentage and place UI elements based on the percentage of the screen (if so, how would I go about doing that)?
I've also tried adding another blank button (removing the button label) underneath the 3rd button and adding constraints like that but it didn't work for me. Let me know if you have any suggestions, thanks!
In you case, Autolayout the constraints you need to give to UIButton is 4 constrains.
Leading
Trailing
Width
Height
If you miss any of them, then surely you will get an error. So, what's your error is?
To the third UIButton, you have not given the height, while to the above two buttons you have given.
So, just remove the bottom constraint of UIButton and give the equal height to above UIButton.
FYI, never use Add Missing Constraints without any confirmation from your side.
Update:
Check this video to remove trailing or leading margin:
http://sendvid.com/1h8deg18
You can actually see the solution in action if you use the Preview screen while setting up your auto layout constraints. I just created a similar view and buttons and stepped through the process. I coloured the buttons and named them to make things obvious.
I added the three buttons. At this point, none of the buttons show up in the preview.
I then setup the auto layout constraints for Button1. If you want the buttons anchored to the top right, then you don't need to worry about the leading constraint. You need width, height, top, and trailing.
Now Button1 will snap to it's position in the top right corner of the preview screen.
Now do the same thing for Button2. Set width, height, top (vertical space to Button1), and trailing.
Button2 will now snap into place in the preview.
Now the same thing again for Button3. You anchored the first button to the top right of the screen. Then Button2 to the bottom of Button1 and the right edge of the screen. Then again for Button3. You could also align the edges of the 2nd and 3rd buttons, if you prefer that to trailing space.
Now you'll see in the preview that your buttons are correctly positioned, regardless of device.
As long as you specify height and width for each button, you don't need to worry about the left edge or the bottom edge of the screen at all. They each know to "stick" to the top right and they know what size to be.
** Note: If you're not familiar with the "Preview" option...
With your storyboard open, hold Option and select storyboard again to get another copy of the storyboard on the right side. Highlight the view controller you are interested in on the left side. On the right side, select the Preview option as shown below.
Now you have your storyboard and the preview side by side, so you can see the exact impact of any auto layout changes you make. You can also add or remove devices to the preview.

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.