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

8voto

SachinVsSachin Punkte 6312

Einfacher Weg, dies in einer Codezeile zu verwenden:

Nehmen Sie ein Etikett bis zu UITextView in .nib Verbinden Sie dieses Etikett mit Ihrem Code, Danach.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{

    if (range.location>0 || text.length!=0) {
        placeholderLabel1.hidden = YES;
    }else{
        placeholderLabel1.hidden = NO;
    }
    return YES;
}

7voto

Nailer Punkte 2428

Ich habe die Implementierung von Sam Soffes so geändert, dass sie mit iOS7 funktioniert:

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    if (_shouldDrawPlaceholder)
    {
        UIEdgeInsets insets = self.textContainerInset;        
        CGRect placeholderRect = CGRectMake(
                insets.left + self.textContainer.lineFragmentPadding,
                insets.top,
                self.frame.size.width - insets.left - insets.right,
                self.frame.size.height - insets.top - insets.bottom);

        [_placeholderText drawWithRect:placeholderRect
                           options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine
                        attributes:self.placeholderAttributes
                           context:nil];
    }
}

- (NSDictionary *)placeholderAttributes
{
    if (_placeholderAttributes == nil)
    {
        _placeholderAttributes = @
        {
            NSFontAttributeName : self.font,
            NSForegroundColorAttributeName : self.placeholderColor
        };
    }

    return _placeholderAttributes;
}

Denken Sie daran, die _placeholderAttribues = nil in Methoden, die die Schriftart und andere Dinge, die sie beeinflussen könnten, ändern. Vielleicht möchten Sie auch die "faule" Erstellung des Attributwörterbuchs überspringen, wenn Sie das nicht stört.

EDITAR:

Denken Sie daran, setNeedsDisplay in einer überschriebenen Version von setBounds aufzurufen, wenn Sie möchten, dass der Platzhalter nach Autolayout-Animationen und dergleichen gut aussieht.

0 Stimmen

Ich denke, Sie sollten insets.left zu dem Parameter offset x hinzufügen.

0 Stimmen

Heißt es nicht setFrame statt setBounds?

0 Stimmen

Nein! setFrame wird während Layout-Animationen nicht aufgerufen, wie es scheint.

7voto

AmitP Punkte 5193

Dies ahmt den Platzhalter von UITextField perfekt nach, bei dem der Platzhaltertext bleibt, bis Sie tatsächlich etwas eingeben.

private let placeholder = "Type here"

@IBOutlet weak var textView: UITextView! {
    didSet {
        textView.textColor = UIColor.lightGray
        textView.text = placeholder
        textView.selectedRange = NSRange(location: 0, length: 0)
    }
}

extension ViewController: UITextViewDelegate {

    func textViewDidChangeSelection(_ textView: UITextView) {
        // Move cursor to beginning on first tap
        if textView.text == placeholder {
            textView.selectedRange = NSRange(location: 0, length: 0)
        }
    }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        if textView.text == placeholder && !text.isEmpty {
            textView.text = nil
            textView.textColor = UIColor.black
            textView.selectedRange = NSRange(location: 0, length: 0)
        }
        return true
    }

    func textViewDidChange(_ textView: UITextView) {
        if textView.text.isEmpty {
            textView.textColor = UIColor.lightGray
            textView.text = placeholder
        }
    }
}

0 Stimmen

Benötigt, um ein paar weitere Zeilen hinzufügen, um meine SwiftUI app funktioniert mit UITextView SwuftUI Wrapper, aber es sieht aus wie die einfachste Lösung, die keine ObjC-Code, 3rd-Party-Framework oder Methode Swizzling speziell enthält.

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.

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