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

6voto

Mike Gledhill Punkte 25646

In diesem Thread gab es schon viele Antworten, aber hier ist die Version, die ich bevorzuge.

Es erweitert die bestehenden UITextView Klasse und ist daher leicht wiederverwendbar, und sie nicht die Ereignisse abfangen wie textViewDidChange (was den Code des Benutzers stören könnte, wenn er diese Ereignisse bereits an anderer Stelle abgefangen hat).

Mithilfe meines Codes (siehe unten) können Sie ganz einfach einen Platzhalter in jede Ihrer UITextViews wie diese:

self.textViewComments.placeholder = @"(Enter some comments here.)";

Wenn Sie diesen neuen Platzhalterwert setzen, fügt er stillschweigend eine UILabel auf der Spitze Ihres UITextView und blendet sie dann je nach Bedarf ein oder aus:

enter image description here

Okay, um diese Änderungen vorzunehmen, fügen Sie eine Datei "UITextViewHelper.h" hinzu, die diesen Code enthält:

//  UITextViewHelper.h
//  Created by Michael Gledhill on 13/02/15.

#import <Foundation/Foundation.h>

@interface UITextView (UITextViewHelper)

@property (nonatomic, strong) NSString* placeholder;
@property (nonatomic, strong) UILabel* placeholderLabel;
@property (nonatomic, strong) NSString* textValue;

-(void)checkIfNeedToDisplayPlaceholder;

@end

...und eine UITextViewHelper.m-Datei, die dies enthält:

//  UITextViewHelper.m
//  Created by Michael Gledhill on 13/02/15.
//
//  This UITextView category allows us to easily display a PlaceHolder string in our UITextView.
//  The downside is that, your code needs to set the "textValue" rather than the "text" value to safely set the UITextView's text.
//
#import "UITextViewHelper.h"
#import <objc/runtime.h>

@implementation UITextView (UITextViewHelper)

#define UI_PLACEHOLDER_TEXT_COLOR [UIColor colorWithRed:170.0/255.0 green:170.0/255.0 blue:170.0/255.0 alpha:1.0]

@dynamic placeholder;
@dynamic placeholderLabel;
@dynamic textValue;

-(void)setTextValue:(NSString *)textValue
{
    //  Change the text of our UITextView, and check whether we need to display the placeholder.
    self.text = textValue;
    [self checkIfNeedToDisplayPlaceholder];
}
-(NSString*)textValue
{
    return self.text;
}

-(void)checkIfNeedToDisplayPlaceholder
{
    //  If our UITextView is empty, display our Placeholder label (if we have one)
    if (self.placeholderLabel == nil)
        return;

    self.placeholderLabel.hidden = (![self.text isEqualToString:@""]);
}

-(void)onTap
{
    //  When the user taps in our UITextView, we'll see if we need to remove the placeholder text.
    [self checkIfNeedToDisplayPlaceholder];

    //  Make the onscreen keyboard appear.
    [self becomeFirstResponder];
}

-(void)keyPressed:(NSNotification*)notification
{
    //  The user has just typed a character in our UITextView (or pressed the delete key).
    //  Do we need to display our Placeholder label ?
   [self checkIfNeedToDisplayPlaceholder];
}

#pragma mark - Add a "placeHolder" string to the UITextView class

NSString const *kKeyPlaceHolder = @"kKeyPlaceHolder";
-(void)setPlaceholder:(NSString *)_placeholder
{
    //  Sets our "placeholder" text string, creates a new UILabel to contain it, and modifies our UITextView to cope with
    //  showing/hiding the UILabel when needed.
    objc_setAssociatedObject(self, &kKeyPlaceHolder, (id)_placeholder, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    self.placeholderLabel = [[UILabel alloc] initWithFrame:self.frame];
    self.placeholderLabel.numberOfLines = 1;
    self.placeholderLabel.text = _placeholder;
    self.placeholderLabel.textColor = UI_PLACEHOLDER_TEXT_COLOR;
    self.placeholderLabel.backgroundColor = [UIColor clearColor];
    self.placeholderLabel.userInteractionEnabled = true;
    self.placeholderLabel.font = self.font;
    [self addSubview:self.placeholderLabel];

    [self.placeholderLabel sizeToFit];

    //  Whenever the user taps within the UITextView, we'll give the textview the focus, and hide the placeholder if necessary.
    [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap)]];

    //  Whenever the user types something in the UITextView, we'll see if we need to hide/show the placeholder label.
    [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(keyPressed:) name:UITextViewTextDidChangeNotification object:nil];

    [self checkIfNeedToDisplayPlaceholder];
}
-(NSString*)placeholder
{
    //  Returns our "placeholder" text string
    return objc_getAssociatedObject(self, &kKeyPlaceHolder);
}

#pragma mark - Add a "UILabel" to this UITextView class

NSString const *kKeyLabel = @"kKeyLabel";
-(void)setPlaceholderLabel:(UILabel *)placeholderLabel
{
    //  Stores our new UILabel (which contains our placeholder string)
    objc_setAssociatedObject(self, &kKeyLabel, (id)placeholderLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(keyPressed:) name:UITextViewTextDidChangeNotification object:nil];

    [self checkIfNeedToDisplayPlaceholder];
}
-(UILabel*)placeholderLabel
{
    //  Returns our new UILabel
    return objc_getAssociatedObject(self, &kKeyLabel);
}
@end

Ja, es ist eine Menge Code, aber sobald Sie ihn zu Ihrem Projekt hinzugefügt und die .h-Datei eingebunden haben...

#import "UITextViewHelper.h"

...können Sie einfach Platzhalter verwenden in UITextViews .

Allerdings gibt es einen Haken.

Wenn Sie dies tun:

self.textViewComments.placeholder = @"(Enter some comments here.)";
self.textViewComments.text = @"Ooooh, hello there";

...wird der Platzhalter erscheinen oben auf den Text. Wenn Sie die Option text Wertes wird keine der regulären Benachrichtigungen aufgerufen, so dass ich nicht herausfinden konnte, wie ich meine Funktion aufrufen kann, um zu entscheiden, ob der Platzhalter angezeigt oder ausgeblendet werden soll.

Die Lösung ist die Einstellung der textValue statt text :

self.textViewComments.placeholder = @"(Enter some comments here.)";
self.textViewComments.textValue = @"Ooooh, hello there";

Alternativ können Sie auch die text Wert, dann rufen Sie checkIfNeedToDisplayPlaceholder .

self.textViewComments.text = @"Ooooh, hello there";
[self.textViewComments checkIfNeedToDisplayPlaceholder];

Ich mag Lösungen wie diese, da sie die Lücke zwischen dem, was Apple uns zur Verfügung stellt, und dem, was wir (als Entwickler) tatsächlich benötigen in unseren Anwendungen. Sie schreiben diesen Code einmal, fügen ihn Ihrer Bibliothek von .m/.h-Hilfsdateien hinzu, und mit der Zeit wird das SDK tatsächlich weniger frustrierend.

(Ich habe ein ähnliches Hilfsmittel geschrieben, um meinen UITextViews eine "clear"-Schaltfläche hinzuzufügen, eine andere Sache, die ärgerlicherweise in UITextField aber nicht in UITextView ...)

0 Stimmen

Ich mag, wie sauber dies ist, aber ich mag nicht, wie es eine zweite UIView/UILabel erfordert (und nicht wirklich erben die Attribute/Farben/Schriftart leicht von der UITextView). Netter Beitrag aber

6voto

Amagrammer Punkte 6410

Sie könnten auch eine neue Klasse TextViewWithPlaceholder als Unterklasse von UITextView erstellen.

(Dieser Code ist etwas grob - aber ich denke, er ist auf dem richtigen Weg).

@interface TextViewWithPlaceholder : UITextView
{

    NSString *placeholderText;  // make a property
    UIColor *placeholderColor;  // make a property
    UIColor *normalTextColor;   // cache text color here whenever you switch to the placeholderColor
}

- (void) setTextColor: (UIColor*) color
{
   normalTextColor = color;
   [super setTextColor: color];
}

- (void) updateForTextChange
{
    if ([self.text length] == 0)
    { 
        normalTextColor = self.textColor;
        self.textColor = placeholderColor;
        self.text = placeholderText;
    }
    else
    {
        self.textColor = normalTextColor;
    }

}

Fügen Sie in Ihrem Delegierten dies hinzu:

- (void)textViewDidChange:(UITextView *)textView
{
    if ([textView respondsToSelector: @selector(updateForTextChange)])
    {
        [textView updateForTextChange];
    }

}

1 Stimmen

Um das genaue Verhalten zu erhalten, sollten Sie Ihren eigenen Platzhalter zeichnen, indem Sie drawRect: überschreiben (Platzhalter nur zeichnen, wenn ![self isFirstResponder] && [[self text] length] == 0), und setNeedsDisplay innerhalb von becomeFirstResponder und resignFirstResponder aufrufen

6voto

Ich empfehle die Verwendung des Pods 'UITextView+Placeholder'.

pod 'UITextView+Placeholder'

zu Ihrem Code

#import "UITextView+Placeholder.h"

////    

UITextView *textView = [[UITextView alloc] init];
textView.placeholder = @"How are you?";
textView.placeholderColor = [UIColor lightGrayColor];

6voto

TheNeil Punkte 2533

Basierend auf einigen der großartigen Vorschläge, die hier bereits gemacht wurden, konnte ich die folgende leichtgewichtige, Interface-Builder-kompatible Unterklasse von UITextView die:

  • Enthält konfigurierbaren Platzhaltertext, der genauso gestaltet ist wie der von UITextField .
  • Erfordert keine zusätzlichen Unteransichten oder Beschränkungen.
  • Erfordert keine Delegation oder anderes Verhalten vom ViewController.
  • Es sind keine Benachrichtigungen erforderlich.
  • Dieser Text wird vollständig von allen anderen Klassen getrennt, die das Feld text Eigentum.

Verbesserungsvorschläge sind willkommen.

Bearbeiten 1: Aktualisiert, um die Platzhalterformatierung zurückzusetzen, wenn der tatsächliche Text programmatisch gesetzt wird.

Bearbeiten 2: Die Farbe des Platzhaltertextes kann jetzt programmatisch abgerufen werden.

Swift v5:

import UIKit
@IBDesignable class TextViewWithPlaceholder: UITextView {

    override var text: String! { // Ensures that the placeholder text is never returned as the field's text
        get {
            if showingPlaceholder {
                return "" // When showing the placeholder, there's no real text to return
            } else { return super.text }
        }
        set {
            if showingPlaceholder {
                removePlaceholderFormatting() // If the placeholder text is what's being changed, it's no longer the placeholder
            }
            super.text = newValue
        }
    }
    @IBInspectable var placeholderText: String = ""
    @IBInspectable var placeholderTextColor: UIColor = .placeholderText
    private var showingPlaceholder: Bool = true // Keeps track of whether the field is currently showing a placeholder

    override func didMoveToWindow() {
        super.didMoveToWindow()
        if text.isEmpty {
            showPlaceholderText() // Load up the placeholder text when first appearing, but not if coming back to a view where text was already entered
        }
    }

    override public func becomeFirstResponder() -> Bool {

        // If the current text is the placeholder, remove it
        if showingPlaceholder {
            text = nil
            removePlaceholderFormatting()
        }
        return super.becomeFirstResponder()
    }

    override public func resignFirstResponder() -> Bool {

        // If there's no text, put the placeholder back
        if text.isEmpty {
            showPlaceholderText()
        }
        return super.resignFirstResponder()
    }

    private func showPlaceholderText() {

        text = placeholderText
        showingPlaceholder = true
        textColor = placeholderTextColor
    }

    private func removePlaceholderFormatting() {

        showingPlaceholder = false
        textColor = nil // Put the text back to the default, unmodified color
    }
}

0 Stimmen

Es gibt ein Problem bei der manuellen Einstellung des Textes von uitextview, d.h. mein TextViewWithPlaceholder.text = "some text" zeigt diese Zeichenkette nicht als txt, sondern als Platzhaltertext an.

1 Stimmen

@AfnanAhmad Zum Einstellen der text programmatisch, machen Sie die showingPlaceHolder öffentlich, dann setzen Sie vor dem Setzen des Textes showingPlaceHolder auf false setzen und den Text einstellen. Er sollte dann erscheinen.

2 Stimmen

Danke für das Feedback @AfnanAhmad. Ich habe jetzt einige Änderungen vorgenommen, um programmatisch gesetzten Text besser zu unterstützen. Am besten macht man keine Komponenten öffentlich, die eigentlich privat sein sollten.

5voto

PJR Punkte 12924

Es ist nicht möglich, Platzhalter in UITextView zu erstellen, aber Sie können damit einen Effekt wie einen Platzhalter erzeugen.

  - (void)viewDidLoad{      
              commentTxtView.text = @"Comment";
              commentTxtView.textColor = [UIColor lightGrayColor];
              commentTxtView.delegate = self;

     }
       - (BOOL) textViewShouldBeginEditing:(UITextView *)textView
     {
         commentTxtView.text = @"";
         commentTxtView.textColor = [UIColor blackColor];
         return YES;
     }

     -(void) textViewDidChange:(UITextView *)textView
     {

    if(commentTxtView.text.length == 0){
        commentTxtView.textColor = [UIColor lightGrayColor];
        commentTxtView.text = @"Comment";
        [commentTxtView resignFirstResponder];
    }
    }

ODER Sie können eine Beschriftung in der Textansicht hinzufügen, wie

       lbl = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0,textView.frame.size.width - 10.0, 34.0)];

[lbl setText:kDescriptionPlaceholder];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setTextColor:[UIColor lightGrayColor]];
textView.delegate = self;

[textView addSubview:lbl];

und setzen

- (void)textViewDidEndEditing:(UITextView *)theTextView
{
     if (![textView hasText]) {
     lbl.hidden = NO;
}
}

- (void) textViewDidChange:(UITextView *)textView
{
    if(![textView hasText]) {
      lbl.hidden = NO;
}
else{
    lbl.hidden = YES;
 }  
}

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