macOS: NSToolbar with translucency effect in Big Sur - xcode

I am working with a new Xcode project for Big Sur, with a "Split View with Sidebar" scene in the main storyboard. I want to make the window title and toolbar have the translucency effect that you see in the toolbars in Safari or Finder. In my storyboard, I specify "Full Size Content View" and "Hide Title Text", and in the storyboard it looks like what I want:
But when I build and run it, the window's toolbar is plain white:
Now if I disable the "Hide Title Bar" checkbox, it looks fine in the storyboard with the title and the toolbar items on the same line:
Now when I build and run it, the toolbar has the translucency effect I want, but the title is on a 2nd level above the toolbar items:
I'm not sure what else I can do to control this. Ideally, I would hide the title bar and keep the translucency, but it doesn't seem to be working. Is there anything else I can try to control this?
If not, I would prefer the title to be on the same level as the toolbar items, like it does in the storyboard. But even that isn't working as desired.
Any ideas on what I can try? I've tried changing the toolbar styles, but they all have similar results.
EDIT:
I've tried using Apple's own code for "Navigating Hierarchical Data Using Outline and Split Views" and after tweaking the storyboard with enabling both "Full Size Content View" and "Hide Title Bar" checkboxes, I'm seeing the same issue: i.e. the toolbar turns white. So it's likely an Apple framework bug? I'm not sure, so I have filed a bug to find out.

I created an app that build fine on High Sierra and Catalina, it may build on OX11. It removes the titlebar, but I don't use a toolbar. Try this, it may do similar to what you want - you may have to comment-out some settings, etc.
Create a file "MainWindow" that is a subclass of NSWindowController. Fill the file with:
class MainWindow: NSWindowController {
var controller: ViewController?
override func windowDidLoad() {
super.windowDidLoad()
controller = self.contentViewController as? ViewController
self.smartWindow()
self.activateWindowDrag()
}
}
// you may prefer the below as a separate file
extension NSWindowController {
func smartWindow() {
self.window?.styleMask.insert(NSWindow.StyleMask.unifiedTitleAndToolbar)
self.window?.styleMask.insert(NSWindow.StyleMask.fullSizeContentView)
self.window?.styleMask.insert(NSWindow.StyleMask.titled)
self.window?.toolbar?.isVisible = false
self.window?.titleVisibility = .hidden
self.window?.titlebarAppearsTransparent = true
}
func activateWindowDrag() {
self.window?.isMovableByWindowBackground = true
}
}

Related

Big Sur Toolbar Items in the Sidebar

In Big Sur, Xcode and Calendar have toolbar items that stay over the sidebar when open but remain visible on the left side when the sidebar's collapsed.
Sidebar open:
Sidebar collapsed:
In "Adopt the New Look of macOS" at 13:55, John says "items placed before the separator [sidebarTrackingSeparator] will appear over the full-height sidebar", just as they are in Xcode and Calendar. I haven't been able to make this work.
Here's a sample project that demonstrates the issue. I used the IB-defined "Window Controller with Sidebar" and added a toolbar item for toggling the sidebar. In a subclass of NSWindowController I insert .sidebarTrackingSeparator after the .toggleSidebar item:
override func windowDidLoad() {
// Sometimes the toolbar items aren't loaded yet--async is a quick and dirty way to prevent a crash
DispatchQueue.main.async {
self.window?.toolbar?.insertItem(withItemIdentifier: .sidebarTrackingSeparator, at: 1)
}
}
Sometimes this has no effect (the toggle button remains to the right of the sidebar). Sometimes the sidebar toggle get put in an overflow menu:
I haven't seen any discussion of implementing this toolbar design outside that WWDC session. Has anyone been able to get this to work?
This is a IB/Code timing disagreement. Interface Builder configures and installs the toolbar before you add the .sidebarTrackingSeparator toolbar item.
So you're doing the right thing, just too late. And too later with the dispatch. I think the important thing is to have the item in there before the toolbar is set on the window.
Unfortunately, that isn't really possible with IB, unless I believe, you create a whole new toolbar and reassign it. But that's a bad idea, because then you may run into trouble auto-saving the state of your toolbar.
The trick is to configure the separator in Interface Builder. If you look at the ObjC documentation for this constant, you'll see a longer name: NSToolbarSidebarTrackingSeparatorItemIdentifier.
The best we can do here is hope that the symbol's name is the same value as the identifier. If you really want to verify this, you can just print the symbol's value in the debugger:
(lldb) po NSToolbarSidebarTrackingSeparatorItemIdentifier
NSToolbarSidebarTrackingSeparatorItemIdentifier
If we create a custom toolbar item in IB, and add that according to John's video...
low and behold:

NSTabView: Toolbar does not display

macOS 10.12.6; Xcode 9.3, storyboards
I have an NSTabView (tabless) that in itself contains two NSTabViews. One is tabless, the other one uses the 'toolbar' style.
When I start my app with the toolbar visible, everything is fine: it displays my tabs in the toolbar, I can change them, etc etc. Once I change to the other branch of my storyboard, the toolbar disappears... and when I come back, instead of a toolbar proper, with buttons and all that, I get a slightly widened bar that has no content in it.
I've set up a sample project to show my problem, where - for ease of switching - I have left the other two tabViewControllers to show their tabs (bottom/top, but this makes no difference).
1) First run (starting with 'toolbar' branch):
2) (not shown): switch to 'top' branch
3) After switching back to 'toolbar':
As a diagnostic aid, I've created a 'displayToolbarStatus' IBAction in the AppController:
#IBAction func displayToolbarStatus(_ sender: NSMenuItem){
if let window = NSApplication.shared.windows.first {
print(window.toolbar?.isVisible)
}
}
The results are as follows:
1) optional(true)
2) nil
3) optional(true)
which is very much in line with how things should work: the toolbar exists and is displayed, there is no toolbar, the toolbar exists and is displayed. Only, of course, it is not usable as a toolbar. (turning visibility off and on, or trying to force a size change with window.toolbar?.sizeMode = .regular has no effect whatsoever, nor does assigning icons to the toolbar items; the toolbar remains squashed and without functioning buttons.
I haven't worked in any depth with NSToolbar: is this a known problem with a workaround; is this new to Xcode 9.2 (which, after all, thinks that no window is valid, so obviously has some problems in that field)?
I really want to use the NSTabView 'toolbar' functionality: how do I proceed?
I've now had more time to play with toolbars. The 'weird' appearance of the non responsive toolbar is simply an empty toolbar, which gave me a clue as to what was going on.
0) The NSTabView overrides the window's toolbar; it does not hand back control when it vanishes; this means that if you have another toolbar in your window that will never show up the moment you're using an NSTabView with 'toolbar' style.
1) I have added a print statement to every relevant method in the ToolbarTabViewController and a 'Switching Tabs' in the containing TabViewController's DidSelect TabViewItem, as well as logging when Toolbar items are added to the window.
(The ToolbarTabViewController is the second controller in the containing TabViewController; it is selected. Otherwise the stack looks slightly different):
ViewDidLoad
Switching tabs
viewWillAppear
viewDidAppear
Switching tabs
Toolbar will add item
Toolbar will add item
viewWillAppear
viewDidAppear
Switching away to the other tab:
viewWillDisappear
Switching tabs
Toolbar did remove item
Toolbar did remove item
viewDidDisappear
So far, so good.
Switching back to the ToolbarTabController, we get
viewWillAppear
Switching tabs
viewDidAppear
Whatever method is called that adds the tabs-related items to the toolbar on first appearance does never get called again. (Note also that the the order of switching tabs and viewDidAppear is not consistent between the first and subsequent appearances.)
2) So, the logical thing to do seems to be to capture the items that are being created and to add them back for future iterations. In the ToolbarTabViewController:
var defaultToolbarItems: [NSToolbarItem] = []
#IBAction func addTabsBack(_ sender: Any){
if let window = NSApplication.shared.windows.first {
if let toolbar = window.toolbar{
for (index, item) in defaultToolbarItems.enumerated() {
toolbar.insertItem(withItemIdentifier: item.itemIdentifier, at: index)
}
}
}
}
override func toolbarWillAddItem(_ notification: Notification) {
// print("Toolbar will add item")
if let toolbarItem = notification.userInfo?["item"] as? NSToolbarItem {
if defaultToolbarItems.count < tabView.numberOfTabViewItems{
defaultToolbarItems.append(toolbarItem)
}
}
}
3) The last question was when (and where) to call addTabsBack() - I found that if I try to call it in viewWillAppear I start out with four toolbarItems, though the number of tabViewItems is 2. (and they do, in fact, seem to be duplications: same name, same functionality). Therefore, I am calling addTabsBack()in the surrounding TabViewController's 'didSelect TabViewItem' method - willSelect is too early; but didSelect gives me exactly the functionality I need.
4) There probably is a more elegant way of capturing the active toolbarItems, but for now, I have a working solution.

tvOS: A way to have UISearchController not appear as a button?

This code
var searchController: UISearchController!
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
view.addSubview(searchController.searchBar)
getItems()
}
produces this:
Screeshot1
Note that the searchBar appears as a button stuck in the upper left (because this is a tabbed app it appears under the tab bar when first presented. The "Button" button is there to receive focus for testing).
This is how it looks after pressing the button: Screenshot2
The second image shows how I would like things to look when the search tab opens, and the way I though it was supposed to look in tvOS.
How do I get the searchController to appear as it does in the second screenshot? Many tvOS apps do this, so I know it must be possible. I have been over the documentation carefully, but I must have missed something.
A related is issue is that the collectionView below won't take focus from the searchController. One has to go back using the remote menu button to get the collectionView to focus.
How can I get the searchController to appear as it does in the second screenshot when the view appears?
How can I get the collectionView to take focus from the searchController without having to go back to the tab bar?
is I finally ran across this passage in the tvOS developer library
All of the iOS first responder mechanisms work on tvOS. This allows
developers to present a UI, visible or hidden, and then make one of
the text fields the first responder by calling the
becomeFirstResponder method on it. This action causes the text field
to put up the keyboard UI without the user having to navigate to a
text field and click on it.
so, adding
searchController.searchBar.becomeFirstResponder()
displays the inline keyboard that I wanted users to start with. However, one has to press the menu button on the remote before the focus engine kicks in again. The menu button also dismisses the keyboard and searchBar returns to its button state.
This an answer to the first of my questions. Still clueless about the second.

Status bar changing tint color when navigation bar going to hidden XCode

I'm using RKSwipeBetweenViewControllers
to switch between UIViewControllers by swipe, and it's all good, but here is a some strange thing i stuck with(look at the screen):
I made that if you scroll news feed down - navigation title going to hidden, and here is curious thing happening: when navigation title disappear - Status bar changing tint color to black! I just don't understand how it's possible?
I already added to to appDelegate
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
and
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
to every possible controllers, and of course navigation bar style i set to "black" but alas! Can anyone say me how to fix it? I will be really appreciate about it!
I had the same problem. What I did was add
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
inside the UIViewController.
This is in swift though. I guess you need to override the function.

How to get the source lists selection highlight to use the Dark Vibrancy appearance in OS X 10.10?

In OS X 10.10 source lists seem to use the light vibrancy appearance. In the Finder (and in some other third party applications, Things.app for example) the selected item in the source list is indicated by a dark vibrancy appearance. For example, see the Desktop row in the image below.
How can I replicate this behaviour? Do I need to use the delegate methods to specify the table row view,
-outlineView:rowViewForItem:
and attempt custom drawing myself or is there a more straight forward approach? If you make a standard source list UI in Xcode the default highlighting is remain the standard blue rectangle that we have seen in previous version of OS X.
After playing around for a while I found a way to accomplish this.
It turned out that I would get the "Finder highlight" style when using NSTableViewSelectionHighlightStyleSourceList and clicking outside my NSOutlineView. So I figured it would stay that way if you refuse making it first responder.
Simply make your NSOutlineView a subclass and override this method:
-(BOOL)acceptsFirstResponder{
return NO;
}
It works, but with some downsides. For example, using arrow keys in the NSOutlineView will no longer work. I downloaded the Things app, and it does not allow use of arrow keys either, so it's very likely that this is how they are doing it. If anyone finds a better way, please post it.
Here is the Swift equivalent :
func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView? {
return CustomTableRowView(frame: NSZeroRect);
}
And the subclass of NSTableRowView
import Cocoa
class CustomTableRowView: NSTableRowView {
override var isEmphasized: Bool {
set {}
get {
return false;
}
}
}
If you would like to keep arrow keys working, you can subclass NSTableRowView and override the following method:
- (BOOL)isEmphasized
{
return NO;
}
I am not sure, this is "Dark Vibrancy".
I would rather try setting the background color to something like "Alternate Selected Control Text Color"
Have a look at an NSTextField in InterfaceBuilder. there are many "Control Text" colors, which have a special appearance on visual effect views.
and for setting the selection color see this answer (untested):
NSTableview Change the highlight colour

Resources