How to customize disclosure cell in view-based NSOutlineView

前端 未结 4 1899

I\'m trying to customize the disclosure arrow appearance in my view-based NSOutlineView. I saw that it\'s recommended to use

- (void)outlineView:(NSOutlineVi         


        
相关标签:
4条回答
  • 2020-12-05 03:47

    Solution 1:

    Subclass NSOutlineView and override makeViewWithIdentifier:owner:

    - (id)makeViewWithIdentifier:(NSString *)identifier owner:(id)owner {
        id view = [super makeViewWithIdentifier:identifier owner:owner];
    
        if ([identifier isEqualToString:NSOutlineViewDisclosureButtonKey]) {
            // Do your customization
        }
    
        return view;
    }
    

    For Source Lists use NSOutlineViewShowHideButtonKey.

    Solution 2:

    Interface Builder

    The button is added to the column and the identifier set to NSOutlineViewDisclosureButtonKey.

    Official documentation from NSOutlineView.h

    /* The following NSOutlineView*Keys are used by the View Based NSOutlineView to create the "disclosure button" used to collapse and expand items. The NSOutlineView creates these buttons by calling [self makeViewWithIdentifier:owner:] passing in the key as the identifier and the delegate as the owner. Custom NSButtons (or subclasses thereof) can be provided for NSOutlineView to use in the following two ways:
     1. makeViewWithIdentifier:owner: can be overridden, and if the identifier is (for instance) NSOutlineViewDisclosureButtonKey, a custom NSButton can be configured and returned. Be sure to set the button.identifier to be NSOutlineViewDisclosureButtonKey.
     2. At design time, a button can be added to the outlineview which has this identifier, and it will be unarchived and used as needed.
     
     When a custom button is used, it is important to properly set up the target/action to do something (probably expand or collapse the rowForView: that the sender is located in). Or, one can call super to get the default button, and copy its target/action to get the normal default behavior.
     
     NOTE: These keys are backwards compatible to 10.7, however, the symbol is not exported prior to 10.9 and the regular string value must be used (i.e.: @"NSOutlineViewDisclosureButtonKey").
     */
    APPKIT_EXTERN NSString *const NSOutlineViewDisclosureButtonKey NS_AVAILABLE_MAC(10_9); // The normal triangle disclosure button
    APPKIT_EXTERN NSString *const NSOutlineViewShowHideButtonKey NS_AVAILABLE_MAC(10_9); // The show/hide button used in "Source Lists"
    
    0 讨论(0)
  • 2020-12-05 03:58

    For Swift 4.2 macOS 10.14, @WetFish's answer can be implemented as follows:

    class SidebarView: NSOutlineView {
    
      override func makeView(withIdentifier identifier: NSUserInterfaceItemIdentifier, owner: Any?) -> NSView? {
        let view = super.makeView(withIdentifier: identifier, owner: owner)
    
        if identifier == NSOutlineView.disclosureButtonIdentifier {
          if let btnView = view as? NSButton {
            btnView.image = NSImage(named: "RightArrow")
            btnView.alternateImage = NSImage(named: "DownArrow")
    
            // can set properties of the image like the size
            btnView.image?.size = NSSize(width: 15.0, height: 15.0)
            btnView.alternateImage?.size = NSSize(width: 15.0, height: 15.0)
          }
        }
        return view
      }
    
    }
    

    Looks quite nice!

    0 讨论(0)
  • 2020-12-05 03:59

    Swift2 version of @Monolo's answer:

    override func didAddSubview(subview: NSView) {
        super.didAddSubview(subview)
        if let sv = subview as? NSButton {
            sv.image = NSImage(named:"icnArwRight")
            sv.alternateImage = NSImage(named:"icnArwDown")
        }
    }
    
    0 讨论(0)
  • 2020-12-05 04:04

    This answer is written with OS X 10.7 in mind, for newer versions of OS X/macOS, refer to WetFish's answer

    That method does not get called because it is only relevant for cell based outline views.

    In a view based outline view, the disclosure triangle is a regular button in the row view of expandable rows. I don't know where it gets added, but it does, and NSView's didAddSubview: method handles exactly that situation of a view being added somewhere else.

    Hence, subclass NSTableRowView, and override didAddSubview:, like this:

    -(void)didAddSubview:(NSView *)subview
    {
        // As noted in the comments, don't forget to call super:
        [super didAddSubview:subview];
    
        if ( [subview isKindOfClass:[NSButton class]] ) {
            // This is (presumably) the button holding the 
            // outline triangle button.
            // We set our own images here.
            [(NSButton *)subview setImage:[NSImage imageNamed:@"disclosure-closed"]];
            [(NSButton *)subview setAlternateImage:[NSImage imageNamed:@"disclosure-open"]];
        }
    }
    

    Of course, your outline view's delegate will have to implement outlineView:rowViewForItem: to return the new row view.

    Despite the name, frameOfOutlineCellAtRow: of NSOutlineView still gets called for view based outline views, so for the positioning of your triangle, you might want to subclass the outline view and override that method, too.

    0 讨论(0)
提交回复
热议问题