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.
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
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.
theTextView.perform(Selector(("setPlaceholderAttributedString:")), with: someAttributedString)
) but the foregroundColor
key of the attributed string is being ignored; the placeholder is getting rendered in black whatever I do. Have others had more success in setting the placeholder color? –
Alamo 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
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))
}
}
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))
}
}
[NSAttributedString.Key.foregroundColor: NSColor.placeholderTextColor]
–
Pigling private var placeholderAttributedString: NSAttributedString? = NSAttributedString(string: "Placeholder string", attributes: [NSAttributedString.Key.foregroundColor: NSColor.placeholderTextColor, NSAttributedString.Key.font: NSFont.systemFont(ofSize: 20, weight: .light)])
–
Stopped One of the previous answers suggests subclassing NSTextView
so that an @objc var placeholderAttributedString: NSAttributedString?
property can be added to it (which normally isn't publicly exposed).
However, this subclass isn't necessary. Instead, because NSTextView
conforms to NSObject
, you can just use setValue
to set this property, without having to subclass:
let attributes: [NSAttributedString.Key: Any] =
[.foregroundColor: NSColor.secondaryLabelColor]
textView.setValue(NSAttributedString(string: placeholder, attributes: attributes),
forKey: "placeholderAttributedString")
The best way to do it if you are using storyboards is to place an NSTextView
and bind its value to a
@objc dynamic var myString: String?
property in your controller. In the binding inspector you then can set a Null Placeholder
value and the text view will use that without you having to use any explicitly private API at all.
© 2022 - 2024 — McMap. All rights reserved.