Set the placeholder string for NSTextView

2019-01-24 09:57发布

问题:

Is there any way to set the placeholder string for NSTextView like that in NSTextField? I have checked the property but couldn't find it. I have searched some questions but there isn't a proper explanation.

回答1:

I found this answer online. Philippe Mougin made this.

static NSAttributedString *placeHolderString;

@implementation TextViewWithPlaceHolder

+(void)initialize
{
  static BOOL initialized = NO;
  if (!initialized)
{
     NSColor *txtColor = [NSColor grayColor];
     NSDictionary *txtDict = [NSDictionary dictionaryWithObjectsAndKeys:txtColor, NSForegroundColorAttributeName, nil];
     placeHolderString = [[NSAttributedString alloc] initWithString:@"This is my placeholder text" attributes:txtDict];
 }
}

- (BOOL)becomeFirstResponder
{
  [self setNeedsDisplay:YES];
  return [super becomeFirstResponder];
}

- (void)drawRect:(NSRect)rect
{
  [super drawRect:rect];
 if ([[self string] isEqualToString:@""] && self != [[self window] firstResponder])
 [placeHolderString drawAtPoint:NSMakePoint(0,0)];
}

- (BOOL)resignFirstResponder
{
   [self setNeedsDisplay:YES];
   return [super resignFirstResponder];
}

@end


回答2:

Swift 4

As it turns out, there already seems to be a placeholderAttributedString property in NSTextView that isn't exposed publicly. Thus, you can simply implement it in your own subclass and get the default placeholder behaviour (similar to NSTextField).

class PlaceholderTextView: NSTextView {
     @objc var placeholderAttributedString: NSAttributedString?
}

And if this property will be made available in the future, you only need to use NSTextView instead of this subclass.



回答3:

Swift 2.0

var placeHolderTitleString: NSAttributedString = NSAttributedString(string: "Place Holder Value", attributes: [NSForegroundColorAttributeName : NSColor.grayColor()])

override func becomeFirstResponder() -> Bool {
    self.needsDisplay = true
    return super.becomeFirstResponder()
}

override func drawRect(rect: NSRect) {
    super.drawRect(rect)

    if (self.string! == "") {
        placeHolderString.drawAtPoint(NSMakePoint(0, 0))
    }
}


回答4:

Look for this. It's may be a better approach!

final class CustomTextView: NSTextView {

    private var placeholderAttributedString: NSAttributedString? = NSAttributedString(string: "Your placeholder string here")
    private var placeholderInsets = NSEdgeInsets(top: 0.0, left: 4.0, bottom: 0.0, right: 4.0)

    override func becomeFirstResponder() -> Bool {
        self.needsDisplay = true
        return super.becomeFirstResponder()
    }

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        guard string.isEmpty else { return }
        placeholderAttributedString?.draw(in: dirtyRect.insetBy(placeholderInsets))
    }
}

extension NSRect {
    func insetBy(_ insets: NSEdgeInsets) -> NSRect {
        return insetBy(dx: insets.left + insets.right, dy: insets.top + insets.bottom)
        .applying(CGAffineTransform(translationX: insets.left - insets.right, y: insets.top - insets.bottom))
    }
}