nstableviewappkitnsoutlineviewmacos-big-sur

Remove NSTableView Floating Group Row Underline in Big Sur


I have NSOutlineViews with floating group rows as a heading. My headers are semi-transparent so scrolled content can just be seen underneath:Header in Catalina

In Big Sur, the headers look like this:

enter image description here

They have an underline below them, and all transparency is removed - so it looks as though a background is being added somewhere.

I am subclassing NSTableRowView and NSOutlineView to stop any drawing:

override func draw(_ dirtyRect: NSRect) {}

I am disabling 'Group Style' on the NSTableRowView too:

override var isGroupRowStyle: Bool { get { false } set {} }

Can anyone tell me where the line and background may be coming from? Thank you.

EDIT

Further investigation shows the background and line rendering is part of the NSScrollView floating content view (_NSScrollViewFloatingSubviewsContainerView). There don't seem to be any options associated with this.


Solution

  • The following extreme hack works currently for me to change the background of the floating header in a NSTableView, and to remove the underline:

    extension YourViewController: NSTableViewDelegate {
        func tableView(_ tableView: NSTableView, didAdd rowView: NSTableRowView, forRow row: Int) {
            if row == 0, rowView.isGroupRowStyle {
                DispatchQueue.main.async {
                    if let scroll = tableView.enclosingScrollView {
                        for sub in scroll.subviews {
                            if sub.className.contains("Float"),
                               let effect = sub.subviews.first?.subviews.first?.subviews.first as? NSVisualEffectView,
                               let line = sub.subviews.first?.subviews.first?.subviews.last {
                                effect.material = .menu
                                line.isHidden = true
                            }
                        }
                    }
                }
            }
        }
    }
    

    When row 0 is added, the sub views of the .enclosingScrollView of the tableview are being iterated (after giving the tableview some time to render the floating header by calling the rest of the code async) until we encounter the views we want to change.

    Of course, this kind of code is an example of 'bad practice', and will stop working as soon as Apple changes the implementation of the sticky header, but I don't expect anything to crash due to all specific conditions.

    In the meanwhile it's probably the best idea to file a Feedback with a request to make the floating header of NSTableView and NSOutlineView adjustable.