754 Stimmen

Platzhalter in UITextView

Meine Anwendung verwendet ein UITextView . Jetzt möchte ich die UITextView einen Platzhalter zu haben, der dem Platzhalter ähnelt, den Sie für eine UITextField .

Wie kann man das tun?

0 Stimmen

Der TTTextEditor von Three20 (der seinerseits UITextField verwendet) unterstützt sowohl Platzhaltertext als auch das Wachsen nach Höhe (er wird zu einem UITextView).

0 Stimmen

24 Stimmen

Wie wäre es mit der Kategorie UITextView+Placeholder? github.com/devxoul/UITextView-Platzhalter

0voto

Einfach erstellen @IBDesignable Unterklasse Ihrer UITextView :

@IBDesignable class AttributedTextView: UITextView {

    private let placeholderLabel = UILabel()

    @IBInspectable var placeholder: String = "" {

        didSet {

            setupPlaceholderLabelIfNeeded()
            textViewDidChange()
        }
    }

    override var text: String! {

        didSet {
            textViewDidChange()
        }
    }

    //MARK: - Initialization

    override func awakeFromNib() {
        super.awakeFromNib()

        setupPlaceholderLabelIfNeeded()
        NotificationCenter.default.addObserver(self, selector: #selector(textViewDidChange), name: .UITextViewTextDidChange, object: nil)
    }

    //MARK: - Deinitialization

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    //MARK: - Internal

    func textViewDidChange() {

        placeholderLabel.isHidden = !text.isEmpty
        layoutIfNeeded()
    }

    //MARK: - Private

    private func setupPlaceholderLabelIfNeeded() {

        placeholderLabel.removeFromSuperview()
        placeholderLabel.frame = CGRect(x: 0, y: 8, width: frame.size.width, height: 0)
        placeholderLabel.textColor = UIColor.lightGray
        placeholderLabel.text = placeholder

        placeholderLabel.sizeToFit()

        insertSubview(placeholderLabel, at: 0)
    }
}

und richten Sie dann einfach Ihren Platzhalter in Identitätskontrolleur :

enter image description here

0voto

tiritea Punkte 1069

Nachdem ich die meisten der vorgeschlagenen Lösungen für diese scheinbar offensichtliche - aber fehlende - Funktion von UITextView durchgesehen (und ausprobiert) habe, war die "beste" Lösung, die ich gefunden habe, die von BobDickinson. Aber ich mochte es nicht, auf eine ganz neue Unterklasse zurückgreifen zu müssen [ich bevorzuge Drop-in-Kategorien für solch einfache funktionale Ergänzungen], und auch nicht, dass sie UITextViewDelegate-Methoden abfängt, was wahrscheinlich Ihren bestehenden UITextView-Verarbeitungscode durcheinanderbringen wird. Hier ist also mein Vorschlag für eine Drop-in-Kategorie, die mit jeder bestehenden UITextView-Instanz funktionieren wird...

#import <objc/runtime.h>

// Private subclass needed to override placeholderRectForBounds: to correctly position placeholder
@interface _TextField : UITextField
@property UIEdgeInsets insets;
@end
@implementation _TextField
- (CGRect)placeholderRectForBounds:(CGRect)bounds
{
    CGRect rect = [super placeholderRectForBounds:bounds];
    return UIEdgeInsetsInsetRect(rect, _insets);
}
@end

@implementation UITextView (Placeholder)

static const void *KEY;

- (void)setPlaceholder:(NSString *)placeholder
{
    _TextField *textField = objc_getAssociatedObject(self, &KEY);
    if (!textField) {
        textField = [_TextField.alloc initWithFrame:self.bounds];
        textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        textField.userInteractionEnabled = NO;
        textField.font = self.font;

        textField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
        textField.insets = UIEdgeInsetsMake(self.textContainerInset.top,
                                            self.textContainerInset.left + self.textContainer.lineFragmentPadding,
                                            self.textContainerInset.bottom,
                                            self.textContainerInset.right);
        [self addSubview:textField];
        [self sendSubviewToBack:textField];

        objc_setAssociatedObject(self, &KEY, textField, OBJC_ASSOCIATION_RETAIN);

        [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(updatePlaceholder:) name:UITextViewTextDidChangeNotification object:nil];
    }
    textField.placeholder = placeholder;
}

- (NSString*)placeholder
{
    UITextField *textField = objc_getAssociatedObject(self, &KEY);
    return textField.placeholder;
}

- (void)updatePlaceholder:(NSNotification *)notification
{
    UITextField *textField = objc_getAssociatedObject(self, &KEY);
    textField.font = self.font;
    [textField setAlpha:self.text.length? 0 : 1];
}

@end

Es ist einfach zu bedienen, nur das Offensichtliche

UITextView *myTextView = UITextView.new;
...
myTextView.placeholder = @"enter text here";

Es funktioniert durch Hinzufügen eines UITextField - an der richtigen Stelle - hinter Ihrer UITextView, und nutzen Sie Es ist Platzhalter statt (daher müssen Sie sich nicht um die richtige Farbe usw. kümmern), dann hören für Benachrichtigungen, wann immer Ihr UITextView geändert wird, um dieses UITextField anzuzeigen/auszublenden (und daher stört es nicht mit Ihren bestehenden UITextViewDelegate-Aufrufen). Und es sind keine magischen Zahlen involviert... :-)

Mit objc_setAssociatedObject()/objc_getAssociatedObject() soll vermieden werden, dass die Unterklasse UITextView verwendet werden muss. [Um das UITextField korrekt zu positionieren, war es leider notwendig, eine "private" Unterklasse einzuführen, um placeholderRectForBounds zu überschreiben:]

Angepasst von BobDickinsons Swift-Antwort.

0voto

LS_ Punkte 6394

Ich habe gerade festgestellt, dass ab dem iOS 10 können Sie jetzt tatsächlich eine UITextView zu einer Methode als UITextField und setzen Sie innerhalb der Methode den Platzhalter. Gerade versucht und es funktioniert ohne Unterklasse UITextView .

Dies ist ein Beispiel dafür, was bei mir funktioniert hat:

-(void)customizeTextField:(UITextField *)textField placeholder:(NSString *)pText withColor:(UIColor *)pTextColor{

        textField.attributedPlaceholder = [[NSAttributedString alloc]
                                          initWithString:pText
                                          attributes:@{NSForegroundColorAttributeName:pTextColor}];
    }

Und um es für eine UITextView müssen Sie es einfach mit einem Cast wie diesem an die Methode übergeben:

[self customizeTextField:(UITextField*)_myTextView placeholder:@"Placeholder" withColor:[UIColor blackColor]];

N.B: Nach einem Test habe ich herausgefunden, dass die Lösung auch unter folgenden Bedingungen gut funktioniert iOS9.x verursacht aber einen Absturz bei iOS8.x

0voto

Stephen J Punkte 2277

Einfacher und immer noch unter Berücksichtigung des vom Benutzer eingegebenen Textes

BOOL placeHolderTextVisible;

bei viewDidLoad auf YES setzen (oder DidMoveToSuperview, oder awakeFromNib)

dann, bei - (BOOL) textView:(UITextView*)textView shouldBeginEditing

    - (BOOL)textViewShouldBeginEditing:(UITextView *)textView;
{
   if (placeHolderTextVisible) {
    placeHolderTextVisible = NO;
    textView.text = @"";
   }
 return YES;
}

0 Stimmen

Es ist überhaupt keine Lösung - nach dem Tippen auf UITextView verschwindet der Platzhalter und erscheint nie wieder.

0 Stimmen

Wird der Benutzer vergessen, dass er tippen kann, wenn er den Text löscht?

0 Stimmen

Die Einfügemarke ist sichtbar und erklärt, dass der Benutzer tippen kann.

0voto

evya Punkte 3261

Sie können einfach eine Beschriftung für die Textansicht festlegen.

MyUITextView.h

@interface MyUITextView : UITextView {
    UILabel* _placeholderLabel;
}

@property(nonatomic, assign)NSString *placeholder;

MyUITextView.m

@implementation MyUITextView

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Create placeholder
        viewFrame = CGRectMake(0, 0, frame.size.width, 15);
        _placeholderLabel = [[UILabel alloc] initWithFrame:viewFrame];
        _placeholderLabel.textColor = [UIColor lightGrayColor];
        [self addSubview:_placeholderLabel];

        // Add text changed notification 
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
    }
    return self;
}

- (void)setPlaceholder:(NSString *)placeholder {
    _placeholderLabel.text = placeholder;
}

- (NSString*)placeholder {
    return _placeholderLabel.text;
}

#pragma mark UITextViewTextDidChangeNotification

- (void)textChanged:(NSNotification *)notification {
    _placeholderLabel.hidden = ([self.text lenght] == 0);
}

@end

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X