Моя програма використовує UITextView. Тепер я хочу, UITextViewщоб у заповнювача було схоже на те, яке ви можете встановити для UITextField.
Як це зробити?
UITextViewрішення стає зовсім іншим. Ось пара рішень. Плаваючий заповнювач і підроблені
Моя програма використовує UITextView. Тепер я хочу, UITextViewщоб у заповнювача було схоже на те, яке ви можете встановити для UITextField.
Як це зробити?
UITextViewрішення стає зовсім іншим. Ось пара рішень. Плаваючий заповнювач і підроблені
Відповіді:
Я вніс декілька незначних змін у рішення bcd, щоб дозволити ініціалізацію з Xibфайлу, обгортання тексту та підтримку кольору фону. Сподіваємось, це позбавить інших проблем.
UIPlaceHolderTextView.h:
#import <Foundation/Foundation.h>
IB_DESIGNABLE
@interface UIPlaceHolderTextView : UITextView
@property (nonatomic, retain) IBInspectable NSString *placeholder;
@property (nonatomic, retain) IBInspectable UIColor *placeholderColor;
-(void)textChanged:(NSNotification*)notification;
@end
UIPlaceHolderTextView.m:
#import "UIPlaceHolderTextView.h"
@interface UIPlaceHolderTextView ()
@property (nonatomic, retain) UILabel *placeHolderLabel;
@end
@implementation UIPlaceHolderTextView
CGFloat const UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION = 0.25;
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
#if __has_feature(objc_arc)
#else
[_placeHolderLabel release]; _placeHolderLabel = nil;
[_placeholderColor release]; _placeholderColor = nil;
[_placeholder release]; _placeholder = nil;
[super dealloc];
#endif
}
- (void)awakeFromNib
{
[super awakeFromNib];
// Use Interface Builder User Defined Runtime Attributes to set
// placeholder and placeholderColor in Interface Builder.
if (!self.placeholder) {
[self setPlaceholder:@""];
}
if (!self.placeholderColor) {
[self setPlaceholderColor:[UIColor lightGrayColor]];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}
- (id)initWithFrame:(CGRect)frame
{
if( (self = [super initWithFrame:frame]) )
{
[self setPlaceholder:@""];
[self setPlaceholderColor:[UIColor lightGrayColor]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}
return self;
}
- (void)textChanged:(NSNotification *)notification
{
if([[self placeholder] length] == 0)
{
return;
}
[UIView animateWithDuration:UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION animations:^{
if([[self text] length] == 0)
{
[[self viewWithTag:999] setAlpha:1];
}
else
{
[[self viewWithTag:999] setAlpha:0];
}
}];
}
- (void)setText:(NSString *)text {
[super setText:text];
[self textChanged:nil];
}
- (void)drawRect:(CGRect)rect
{
if( [[self placeholder] length] > 0 )
{
if (_placeHolderLabel == nil )
{
_placeHolderLabel = [[UILabel alloc] initWithFrame:CGRectMake(8,8,self.bounds.size.width - 16,0)];
_placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping;
_placeHolderLabel.numberOfLines = 0;
_placeHolderLabel.font = self.font;
_placeHolderLabel.backgroundColor = [UIColor clearColor];
_placeHolderLabel.textColor = self.placeholderColor;
_placeHolderLabel.alpha = 0;
_placeHolderLabel.tag = 999;
[self addSubview:_placeHolderLabel];
}
_placeHolderLabel.text = self.placeholder;
[_placeHolderLabel sizeToFit];
[self sendSubviewToBack:_placeHolderLabel];
}
if( [[self text] length] == 0 && [[self placeholder] length] > 0 )
{
[[self viewWithTag:999] setAlpha:1];
}
[super drawRect:rect];
}
@end
Простий спосіб, просто створіть текст заповнення UITextViewза допомогою наступних UITextViewDelegateметодів:
- (void)textViewDidBeginEditing:(UITextView *)textView
{
if ([textView.text isEqualToString:@"placeholder text here..."]) {
textView.text = @"";
textView.textColor = [UIColor blackColor]; //optional
}
[textView becomeFirstResponder];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
if ([textView.text isEqualToString:@""]) {
textView.text = @"placeholder text here...";
textView.textColor = [UIColor lightGrayColor]; //optional
}
[textView resignFirstResponder];
}
просто не забудьте встановити myUITextViewточний текст на створення, наприклад
UITextView *myUITextView = [[UITextView alloc] init];
myUITextView.delegate = self;
myUITextView.text = @"placeholder text here...";
myUITextView.textColor = [UIColor lightGrayColor]; //optional
і зробити батьківський клас a UITextViewDelegateперед тим, як включити ці методи, наприклад
@interface MyClass () <UITextViewDelegate>
@end
Код для Swift 3.1
func textViewDidBeginEditing(_ textView: UITextView)
{
if (textView.text == "placeholder text here..." && textView.textColor == .lightGray)
{
textView.text = ""
textView.textColor = .black
}
textView.becomeFirstResponder() //Optional
}
func textViewDidEndEditing(_ textView: UITextView)
{
if (textView.text == "")
{
textView.text = "placeholder text here..."
textView.textColor = .lightGray
}
textView.resignFirstResponder()
}
просто не забудьте встановити myUITextViewточний текст на створення, наприклад
let myUITextView = UITextView.init()
myUITextView.delegate = self
myUITextView.text = "placeholder text here..."
myUITextView.textColor = .lightGray
і зробити батьківський клас a UITextViewDelegateперед тим, як включити ці методи, наприклад
class MyClass: UITextViewDelegate
{
}
textатрибутом TextView , який є своїм родом nice..whereas цього метод змінює його
Я не був надто задоволений жодним із розміщених рішень, оскільки вони були трохи важкими. Додавання поглядів до перегляду насправді не ідеально (особливо в drawRect:). Вони обоє мали витоки, що теж не прийнятно.
Ось моє рішення: SAMTextView
SAMTextView.h
//
// SAMTextView.h
// SAMTextView
//
// Created by Sam Soffes on 8/18/10.
// Copyright 2010-2013 Sam Soffes. All rights reserved.
//
#import <UIKit/UIKit.h>
/**
UITextView subclass that adds placeholder support like UITextField has.
*/
@interface SAMTextView : UITextView
/**
The string that is displayed when there is no other text in the text view.
The default value is `nil`.
*/
@property (nonatomic, strong) NSString *placeholder;
/**
The color of the placeholder.
The default is `[UIColor lightGrayColor]`.
*/
@property (nonatomic, strong) UIColor *placeholderTextColor;
/**
Returns the drawing rectangle for the text views’s placeholder text.
@param bounds The bounding rectangle of the receiver.
@return The computed drawing rectangle for the placeholder text.
*/
- (CGRect)placeholderRectForBounds:(CGRect)bounds;
@end
SAMTextView.m
//
// SAMTextView.m
// SAMTextView
//
// Created by Sam Soffes on 8/18/10.
// Copyright 2010-2013 Sam Soffes. All rights reserved.
//
#import "SAMTextView.h"
@implementation SAMTextView
#pragma mark - Accessors
@synthesize placeholder = _placeholder;
@synthesize placeholderTextColor = _placeholderTextColor;
- (void)setText:(NSString *)string {
[super setText:string];
[self setNeedsDisplay];
}
- (void)insertText:(NSString *)string {
[super insertText:string];
[self setNeedsDisplay];
}
- (void)setAttributedText:(NSAttributedString *)attributedText {
[super setAttributedText:attributedText];
[self setNeedsDisplay];
}
- (void)setPlaceholder:(NSString *)string {
if ([string isEqual:_placeholder]) {
return;
}
_placeholder = string;
[self setNeedsDisplay];
}
- (void)setContentInset:(UIEdgeInsets)contentInset {
[super setContentInset:contentInset];
[self setNeedsDisplay];
}
- (void)setFont:(UIFont *)font {
[super setFont:font];
[self setNeedsDisplay];
}
- (void)setTextAlignment:(NSTextAlignment)textAlignment {
[super setTextAlignment:textAlignment];
[self setNeedsDisplay];
}
#pragma mark - NSObject
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidChangeNotification object:self];
}
#pragma mark - UIView
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self initialize];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
[self initialize];
}
return self;
}
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
if (self.text.length == 0 && self.placeholder) {
rect = [self placeholderRectForBounds:self.bounds];
UIFont *font = self.font ? self.font : self.typingAttributes[NSFontAttributeName];
// Draw the text
[self.placeholderTextColor set];
[self.placeholder drawInRect:rect withFont:font lineBreakMode:NSLineBreakByTruncatingTail alignment:self.textAlignment];
}
}
#pragma mark - Placeholder
- (CGRect)placeholderRectForBounds:(CGRect)bounds {
// Inset the rect
CGRect rect = UIEdgeInsetsInsetRect(bounds, self.contentInset);
if (self.typingAttributes) {
NSParagraphStyle *style = self.typingAttributes[NSParagraphStyleAttributeName];
if (style) {
rect.origin.x += style.headIndent;
rect.origin.y += style.firstLineHeadIndent;
}
}
return rect;
}
#pragma mark - Private
- (void)initialize {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:self];
self.placeholderTextColor = [UIColor colorWithWhite:0.702f alpha:1.0f];
}
- (void)textChanged:(NSNotification *)notification {
[self setNeedsDisplay];
}
@end
Це набагато простіше, ніж інші, так як він не використовує підгляди (або не має витоків). Сміливо користуйтеся ним.
Оновлення 11/10/11: Тепер це документально підтверджено та підтримує використання в Interface Builder.
Оновлення 24.11.13: Вкажіть на нове репо.
setTextщоб також оновити заповнення заповнення при зміні властивості тексту програмно: - (void) setText: (NSString *) рядок {[super setText: string]; [self _updateShouldDrawPlaceholder]; }
notificationаргумент написано неправильно в останньому методі, і це занадто мала зміна для подання як редагування.
Я знайшов собі дуже простий спосіб наслідувати місця, що займає місце
Редагувати:
Змінено, якщо висловлювання порівнюють теги, а не текст. Якщо користувач видалив їх текст, можна було також випадково видалити частину власника місця @"Foobar placeholder". Це означало, що якщо користувач повторно ввів textView наступний метод делегування -(BOOL) textViewShouldBeginEditing:(UITextView *) textView, він не буде працювати, як очікувалося. Я спробував порівняти за кольором тексту в операторі if, але виявив, що світло-сірий колір, встановлений в програмі інтерфейсу, не такий, як світло-сірий колір, встановлений у коді з[UIColor lightGreyColor]
- (BOOL) textViewShouldBeginEditing:(UITextView *)textView
{
if(textView.tag == 0) {
textView.text = @"";
textView.textColor = [UIColor blackColor];
textView.tag = 1;
}
return YES;
}
Можливо також скинути текст заповнення, коли повертається клавіатура, і [textView length] == 0
Редагувати:
Просто, щоб остання частина була зрозумілішою - ось як можна встановити назад текст заповнення:
- (void)textViewDidChange:(UITextView *)textView
{
if([textView.text length] == 0)
{
textView.text = @"Foobar placeholder";
textView.textColor = [UIColor lightGrayColor];
textView.tag = 0;
}
}
Що ви можете зробити, це налаштувати перегляд тексту з деяким початковим значенням у textвластивості та змінити textColorна [UIColor grayColor]або щось подібне. Потім, коли текст перегляду стане редагованим, очистіть текст і введіть курсор, і якщо текстове поле ще раз буде порожнім, поверніть його назад. Змініть колір на [UIColor blackColor]відповідний варіант.
Це не зовсім те саме, що функціонал заповнення місця в UITextField, але він близький.
Ви можете встановити ярлик на UITextViewпо
[UITextView addSubView:lblPlaceHoldaer];
і приховати його за TextViewdidChangeметодом.
Це простий і простий спосіб.
Якщо комусь потрібне рішення для Swift:
Додайте UITextViewDelegate до свого класу
var placeHolderText = "Placeholder Text..."
override func viewDidLoad() {
super.viewDidLoad()
textView.delegate = self
}
func textViewShouldBeginEditing(textView: UITextView) -> Bool {
self.textView.textColor = .black
if(self.textView.text == placeHolderText) {
self.textView.text = ""
}
return true
}
func textViewDidEndEditing(textView: UITextView) {
if(textView.text == "") {
self.textView.text = placeHolderText
self.textView.textColor = .lightGray
}
}
override func viewWillAppear(animated: Bool) {
if(currentQuestion.answerDisplayValue == "") {
self.textView.text = placeHolderText
self.textView.textColor = .lightGray
} else {
self.textView.text = "xxx" // load default text / or stored
self.textView.textColor = .black
}
}
Просте рішення Swift 3
Додайте UITextViewDelegateдо свого класу
Встановити yourTextView.delegate = self
Створіть placeholderLabelі розташуйте всерединіyourTextView
Тепер просто анімуйте placeholderLabel.alphaна textViewDidChange:
func textViewDidChange(_ textView: UITextView) {
let newAlpha: CGFloat = textView.text.isEmpty ? 1 : 0
if placeholderLabel.alpha != newAlpha {
UIView.animate(withDuration: 0.3) {
self.placeholderLabel.alpha = newAlpha
}
}
}
вам, можливо, доведеться грати з placeholderLabelположенням, щоб правильно його встановити, але це не повинно бути занадто важким
let alpha = CGFloat(textView.text.isEmpty ? 1.0 : 0.0) if alpha != lblPlaceholder.alpha { UIView.animate(withDuration: 0.3) { self.lblPlaceholder.alpha = alpha } }
Я розширив відповідь KmKndy, щоб заповнювач місця залишився видимим, поки користувач не почне редагувати, UITextViewа не просто натискати на нього. Це відображає функціональність у програмах Twitter та Facebook. Моє рішення не вимагає від вас підкласу та працює, якщо користувач вводить безпосередньо або вставляє текст!

- (void)textViewDidChangeSelection:(UITextView *)textView{
if ([textView.text isEqualToString:@"What's happening?"] && [textView.textColor isEqual:[UIColor lightGrayColor]])[textView setSelectedRange:NSMakeRange(0, 0)];
}
- (void)textViewDidBeginEditing:(UITextView *)textView{
[textView setSelectedRange:NSMakeRange(0, 0)];
}
- (void)textViewDidChange:(UITextView *)textView
{
if (textView.text.length != 0 && [[textView.text substringFromIndex:1] isEqualToString:@"What's happening?"] && [textView.textColor isEqual:[UIColor lightGrayColor]]){
textView.text = [textView.text substringToIndex:1];
textView.textColor = [UIColor blackColor]; //optional
}
else if(textView.text.length == 0){
textView.text = @"What's happening?";
textView.textColor = [UIColor lightGrayColor];
[textView setSelectedRange:NSMakeRange(0, 0)];
}
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
if ([textView.text isEqualToString:@""]) {
textView.text = @"What's happening?";
textView.textColor = [UIColor lightGrayColor]; //optional
}
[textView resignFirstResponder];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if (textView.text.length > 1 && [textView.text isEqualToString:@"What's happening?"]) {
textView.text = @"";
textView.textColor = [UIColor blackColor];
}
return YES;
}
просто не забудьте встановити myUITextView з точним текстом при створенні, наприклад
UITextView *myUITextView = [[UITextView alloc] init];
myUITextView.delegate = self;
myUITextView.text = @"What's happening?";
myUITextView.textColor = [UIColor lightGrayColor]; //optional
і зробити батьківський клас делегатом UITextView перед включенням цих методів, наприклад
@interface MyClass () <UITextViewDelegate>
@end
Рекомендую використовувати SZTextView.
https://github.com/glaszig/SZTextView
Додайте за замовчуванням UITextViewз, storyboardа потім змініть його власний клас на SZTextViewтакий, як нижче 👇👇👇👇

Тоді ви побачите дві нові опції у Attribute Inspector👇👇👇👇

Нижче знаходиться порт Swift з кодом ObjC "SAMTextView", який розміщено як одну з перших жмень відповідей на питання. Я перевірив це на iOS 8. Я підробив пару речей, включаючи зміщення меж для розміщення тексту заповнювача, оскільки оригінал був занадто високим і занадто правильним (використовував пропозицію в одному з коментарів до цієї публікації).
Я знаю, що існує багато простих рішень, але мені подобається підхід підкласифікації UITextView, оскільки він багаторазовий, і мені не потрібно захаращувати класи, використовуючи його за допомогою механізмів.
Швидкий 2.2:
import UIKit
class PlaceholderTextView: UITextView {
@IBInspectable var placeholderColor: UIColor = UIColor.lightGrayColor()
@IBInspectable var placeholderText: String = ""
override var font: UIFont? {
didSet {
setNeedsDisplay()
}
}
override var contentInset: UIEdgeInsets {
didSet {
setNeedsDisplay()
}
}
override var textAlignment: NSTextAlignment {
didSet {
setNeedsDisplay()
}
}
override var text: String? {
didSet {
setNeedsDisplay()
}
}
override var attributedText: NSAttributedString? {
didSet {
setNeedsDisplay()
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUp()
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
}
private func setUp() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PlaceholderTextView.textChanged(_:)),
name: UITextViewTextDidChangeNotification, object: self)
}
func textChanged(notification: NSNotification) {
setNeedsDisplay()
}
func placeholderRectForBounds(bounds: CGRect) -> CGRect {
var x = contentInset.left + 4.0
var y = contentInset.top + 9.0
let w = frame.size.width - contentInset.left - contentInset.right - 16.0
let h = frame.size.height - contentInset.top - contentInset.bottom - 16.0
if let style = self.typingAttributes[NSParagraphStyleAttributeName] as? NSParagraphStyle {
x += style.headIndent
y += style.firstLineHeadIndent
}
return CGRect(x: x, y: y, width: w, height: h)
}
override func drawRect(rect: CGRect) {
if text!.isEmpty && !placeholderText.isEmpty {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = textAlignment
let attributes: [ String: AnyObject ] = [
NSFontAttributeName : font!,
NSForegroundColorAttributeName : placeholderColor,
NSParagraphStyleAttributeName : paragraphStyle]
placeholderText.drawInRect(placeholderRectForBounds(bounds), withAttributes: attributes)
}
super.drawRect(rect)
}
}
Швидкий 4.2:
import UIKit
class PlaceholderTextView: UITextView {
@IBInspectable var placeholderColor: UIColor = UIColor.lightGray
@IBInspectable var placeholderText: String = ""
override var font: UIFont? {
didSet {
setNeedsDisplay()
}
}
override var contentInset: UIEdgeInsets {
didSet {
setNeedsDisplay()
}
}
override var textAlignment: NSTextAlignment {
didSet {
setNeedsDisplay()
}
}
override var text: String? {
didSet {
setNeedsDisplay()
}
}
override var attributedText: NSAttributedString? {
didSet {
setNeedsDisplay()
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUp()
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
}
private func setUp() {
NotificationCenter.default.addObserver(self,
selector: #selector(self.textChanged(notification:)),
name: Notification.Name("UITextViewTextDidChangeNotification"),
object: nil)
}
@objc func textChanged(notification: NSNotification) {
setNeedsDisplay()
}
func placeholderRectForBounds(bounds: CGRect) -> CGRect {
var x = contentInset.left + 4.0
var y = contentInset.top + 9.0
let w = frame.size.width - contentInset.left - contentInset.right - 16.0
let h = frame.size.height - contentInset.top - contentInset.bottom - 16.0
if let style = self.typingAttributes[NSAttributedString.Key.paragraphStyle] as? NSParagraphStyle {
x += style.headIndent
y += style.firstLineHeadIndent
}
return CGRect(x: x, y: y, width: w, height: h)
}
override func draw(_ rect: CGRect) {
if text!.isEmpty && !placeholderText.isEmpty {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = textAlignment
let attributes: [NSAttributedString.Key: Any] = [
NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue) : font!,
NSAttributedString.Key(rawValue: NSAttributedString.Key.foregroundColor.rawValue) : placeholderColor,
NSAttributedString.Key(rawValue: NSAttributedString.Key.paragraphStyle.rawValue) : paragraphStyle]
placeholderText.draw(in: placeholderRectForBounds(bounds: bounds), withAttributes: attributes)
}
super.draw(rect)
}
}
ось як я це зробив:
UITextView2.h
#import <UIKit/UIKit.h>
@interface UITextView2 : UITextView <UITextViewDelegate> {
NSString *placeholder;
UIColor *placeholderColor;
}
@property(nonatomic, retain) NSString *placeholder;
@property(nonatomic, retain) UIColor *placeholderColor;
-(void)textChanged:(NSNotification*)notif;
@end
UITextView2.m
@implementation UITextView2
@synthesize placeholder, placeholderColor;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setPlaceholder:@""];
[self setPlaceholderColor:[UIColor lightGrayColor]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}
return self;
}
-(void)textChanged:(NSNotification*)notif {
if ([[self placeholder] length]==0)
return;
if ([[self text] length]==0) {
[[self viewWithTag:999] setAlpha:1];
} else {
[[self viewWithTag:999] setAlpha:0];
}
}
- (void)drawRect:(CGRect)rect {
if ([[self placeholder] length]>0) {
UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(8, 8, 0, 0)];
[l setFont:self.font];
[l setTextColor:self.placeholderColor];
[l setText:self.placeholder];
[l setAlpha:0];
[l setTag:999];
[self addSubview:l];
[l sizeToFit];
[self sendSubviewToBack:l];
[l release];
}
if ([[self text] length]==0 && [[self placeholder] length]>0) {
[[self viewWithTag:999] setAlpha:1];
}
[super drawRect:rect];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
@end
Ось спосіб простішого рішення, яке веде себе точно як заповнювач UITextField, але не вимагає малювання спеціальних представлень чи відставки першого відповіді.
- (void) textViewDidChange:(UITextView *)textView{
if (textView.text.length == 0){
textView.textColor = [UIColor lightGrayColor];
textView.text = placeholderText;
[textView setSelectedRange:NSMakeRange(0, 0)];
isPlaceholder = YES;
} else if (isPlaceholder && ![textView.text isEqualToString:placeholderText]) {
textView.text = [textView.text substringToIndex:1];
textView.textColor = [UIColor blackColor];
isPlaceholder = NO;
}
}
(друга перевірка в іншому, якщо оператор - для випадку, коли нічого не введено, а користувач натискає на зворотну простір)
Просто встановіть свій клас як UITextViewDelegate. У viewDidLoad вам слід ініціалізувати як
- (void) viewDidLoad{
// initialize placeholder text
placeholderText = @"some placeholder";
isPlaceholder = YES;
self.someTextView.text = placeholderText;
self.someTextView.textColor = [UIColor lightGrayColor];
[self.someTextView setSelectedRange:NSMakeRange(0, 0)];
// assign UITextViewDelegate
self.someTextView.delegate = self;
}
Привіт, ви можете використовувати IQTextView, доступний у менеджері IQKeyboard, простий у використанні та інтеграції просто встановлений клас вашого перегляду тексту в IQTextView, і ви можете використовувати його властивість для встановлення ярлика заповнювача з потрібним кольором. Ви можете завантажити бібліотеку з IQKeyboardManager
або ви можете встановити його з какаоподів.
UITextViewDelegateпрацював просто чудово
Вибачте, щоб додати ще одну відповідь, але я просто зняв щось подібне, і це створило найближчий до UITextField вид заповнювача.
Сподіваюся, що це комусь допоможе.
-(void)textViewDidChange:(UITextView *)textView{
if(textView.textColor == [UIColor lightGrayColor]){
textView.textColor = [UIColor blackColor]; // look at the comment section in this answer
textView.text = [textView.text substringToIndex: 0];// look at the comment section in this answer
}else if(textView.text.length == 0){
textView.text = @"This is some placeholder text.";
textView.textColor = [UIColor lightGrayColor];
textView.selectedRange = NSMakeRange(0, 0);
}
}
-(void)textViewDidChangeSelection:(UITextView *)textView{
if(textView.textColor == [UIColor lightGrayColor] && (textView.selectedRange.location != 0 || textView.selectedRange.length != 0)){
textView.selectedRange = NSMakeRange(0, 0);
}
}
if(textView.textColor == [UIColor lightGrayColor]){ textView.textColor = [UIColor blackColor]; textView.text = [textView.text substringToIndex: 1]; Інакше перший символ, що вводиться в перегляд тексту, був розміщений в кінці тексту
Простий спосіб використовувати це в деякому рядку коду:
Візьміть одну мітку до UITextView в .nib, підключивши цю мітку до коду, Після неї.
- (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;
}
Я змінив реалізацію Sam Soffes для роботи з iOS7:
- (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;
}
Не забудьте встановити _placeholderAttribues = nilметоди, які можуть змінити шрифт та інші відтінки, які можуть вплинути на них. Ви також можете пропустити "ліниве" складання словника атрибутів, якщо це не помилка.
Редагувати:
Не забудьте зателефонувати setNeedsDisplay у перекритій версії setBounds, якщо вам подобається, що заповнювач місця розміщення добре виглядає після анімації авторозмітки тощо.
Ви також можете створити новий клас TextViewWithPlaceholder як підклас UITextView.
(Цей код начебто грубий, але я думаю, що він на правильному шляху.)
@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;
}
}
У своєму делегаті додайте це:
- (void)textViewDidChange:(UITextView *)textView
{
if ([textView respondsToSelector: @selector(updateForTextChange)])
{
[textView updateForTextChange];
}
}
Я створив власну версію підкласу 'UITextView'. Мені сподобалася ідея Сема Соффа про використання сповіщень, але мені не сподобалось малюнок drawRect: перезапис. Здається, мені надмірно. Я думаю, що я зробив дуже чисту реалізацію.
Ви можете подивитися на мій підклас тут . Також включений демонстраційний проект.
На цю тему було багато відповідей, але ось таку версію я віддаю перевагу.
Він розширює існуючий UITextViewклас, тому його легко використовувати повторно, і він не перехоплює події типу textViewDidChange(які можуть порушити код користувача, якщо вони вже перехоплювали ці події в іншому місці).
Використовуючи мій код (показаний нижче), ви можете легко додати заповнювач до будь-якого UITextViewsподібного:
self.textViewComments.placeholder = @"(Enter some comments here.)";
Коли ви встановите це нове значення заповнювача, воно спокійно додає додаток у UILabelверхній частині вашого UITextView, а потім приховає / показує, як потрібно:

Гаразд, щоб внести ці зміни, додайте файл "UITextViewHelper.h", що містить цей код:
// 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
... і файл UITextViewHelper.m, що містить це:
// 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
Так, це багато коду, але як тільки ви додали його до свого проекту та включили .h файл ...
#import "UITextViewHelper.h"
... ви можете легко використовувати заповнювачі в UITextViews.
Хоча є одна готча
Якщо ви це зробите:
self.textViewComments.placeholder = @"(Enter some comments here.)";
self.textViewComments.text = @"Ooooh, hello there";
... заповнювач заповнення з’явиться вгорі тексту. Коли ви встановлюєте textзначення, жодне з звичайних сповіщень не викликається, тому я не міг розібратися, як викликати свою функцію, щоб вирішити, показати чи приховати заповнювач.
Рішення полягає у встановленні, textValueа не text:
self.textViewComments.placeholder = @"(Enter some comments here.)";
self.textViewComments.textValue = @"Ooooh, hello there";
Крім того, ви можете встановити textзначення, а потім зателефонувати checkIfNeedToDisplayPlaceholder.
self.textViewComments.text = @"Ooooh, hello there";
[self.textViewComments checkIfNeedToDisplayPlaceholder];
Мені подобаються такі рішення, оскільки вони "заповнюють прогалину" між тим, що нам надає Apple, і тим, що нам (як розробникам) насправді потрібно в наших додатках. Ви пишете цей код один раз, додаєте його у свою бібліотеку файлів "helper" .m / .h, і з часом SDK насправді починає ставати менш розчарувальним.
(Я написав аналогічного помічника для додавання кнопки "ясно" до своїх UITextViews, інша річ, яка прикро існує в, UITextFieldале не в UITextView...)
Спочатку візьміть ярлик у .h файл.
Ось я беру
UILabel * lbl;
Тоді в .m під viewDidLoad заявіть про це
lbl = [[UILabel alloc] initWithFrame:CGRectMake(8.0, 0.0,250, 34.0)];
lbl.font=[UIFont systemFontOfSize:14.0];
[lbl setText:@"Write a message..."];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setTextColor:[UIColor lightGrayColor]];
[textview addSubview:lbl];
textview - це мій TextView.
Тепер задекларуйте
-(void)textViewDidChange:(UITextView *)textView {
if (![textView hasText]){
lbl.hidden = NO;
}
else{
lbl.hidden = YES;
}
}
І ваш заповнювач Textview готовий!
Рекомендую використовувати pod "UITextView + заповнювач"
pod 'UITextView+Placeholder'
на свій код
#import "UITextView+Placeholder.h"
////
UITextView *textView = [[UITextView alloc] init];
textView.placeholder = @"How are you?";
textView.placeholderColor = [UIColor lightGrayColor];
- (void)textViewDidChange:(UITextView *)textView
{
placeholderLabel.hidden = YES;
}
поставте мітку над переглядом тексту.
Неможливо створити заповнювач місця в UITextView, але ви можете створити такий ефект, як власник місця.
- (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];
}
}
АБО ви можете додати мітку в текстовому перегляді так само
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];
і встановити
- (void)textViewDidEndEditing:(UITextView *)theTextView
{
if (![textView hasText]) {
lbl.hidden = NO;
}
}
- (void) textViewDidChange:(UITextView *)textView
{
if(![textView hasText]) {
lbl.hidden = NO;
}
else{
lbl.hidden = YES;
}
}
Це ідеально імітує заповнювач UITextField, де текст власника місця залишається, поки ви фактично щось не введете.
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
}
}
}
Ось ще один спосіб зробити це, який відтворює невеликий відступ UITextFieldзапам'ятовувача:
Перетягніть UITextFieldправоруч під таким UITextViewчином, щоб їхні верхні ліві кути були вирівняні. Додайте текст заповнювача до текстового поля.
У viewDidLoad додайте:
[tView setDelegate:self];
tView.contentInset = UIEdgeInsetsMake(-8,-8,0,0);
tView.backgroundColor = [UIColor clearColor];
Потім додайте:
- (void)textViewDidChange:(UITextView *)textView {
if (textView.text.length == 0) {
textView.backgroundColor = [UIColor clearColor];
} else {
textView.backgroundColor = [UIColor whiteColor];
}
}
Давайте зробимо це легким
Створіть один UILabel і розмістіть його на своєму текстовому вікні (Надайте текст як кольоровий колір, встановлений сірим кольором - ви можете зробити все це у своєму xib) Тепер у вашому заголовковому файлі оголосьте UILabel, а також textviewDelegate Тепер ви можете просто приховати мітку при натисканні на перегляд тексту
повний код нижче
заголовок
@interface ViewController :UIViewController<UITextViewDelegate>{
}
@property (nonatomic,strong) IBOutlet UILabel *PlceHolder_label;
@property (nonatomic,strong) IBOutlet UITextView *TextView;
@end
реалізація
@implementation UploadFoodImageViewController
@synthesize PlceHolder_label,TextView;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
if([textView isEqual:TextView]){
[PlceHolder_label setHidden:YES];
[self.tabScrlVw setContentOffset:CGPointMake(0,150) animated:YES];
}
return YES;
}
@end
Не забудьте підключити textView та UILabel до власника файлів від xib
Погляньте на UTPlaceholderTextView .
Це зручний підклас UITextView, який підтримує заповнювач заповнення, подібний до UITextField. Основні особливості:
Я прочитав усе це, але придумав дуже коротке рішення Swift 3, яке спрацювало у всіх моїх тестах. Це може витримати трохи більше загальності, але процес простий. Ось вся справа, яку я називаю "TextViewWithPlaceholder".
import UIKit
class TextViewWithPlaceholder: UITextView {
public var placeholder: String?
public var placeholderColor = UIColor.lightGray
private var placeholderLabel: UILabel?
// Set up notification listener when created from a XIB or storyboard.
// You can also set up init() functions if you plan on creating
// these programmatically.
override func awakeFromNib() {
super.awakeFromNib()
NotificationCenter.default.addObserver(self,
selector: #selector(TextViewWithPlaceholder.textDidChangeHandler(notification:)),
name: .UITextViewTextDidChange,
object: self)
placeholderLabel = UILabel()
placeholderLabel?.alpha = 0.85
placeholderLabel?.textColor = placeholderColor
}
// By using layoutSubviews, you can size and position the placeholder
// more accurately. I chose to hard-code the size of the placeholder
// but you can combine this with other techniques shown in previous replies.
override func layoutSubviews() {
super.layoutSubviews()
placeholderLabel?.textColor = placeholderColor
placeholderLabel?.text = placeholder
placeholderLabel?.frame = CGRect(x: 6, y: 4, width: self.bounds.size.width-16, height: 24)
if text.isEmpty {
addSubview(placeholderLabel!)
bringSubview(toFront: placeholderLabel!)
} else {
placeholderLabel?.removeFromSuperview()
}
}
// Whenever the text changes, just trigger a new layout pass.
func textDidChangeHandler(notification: Notification) {
layoutSubviews()
}
}
layoutSubviews()безпосередньо. І ви не видалили спостерігача NotificationCenter.
Я швидко написав клас. Ви можете імпортувати цей клас, коли це потрібно.
import UIKit
загальнодоступний клас CustomTextView: UITextView {
private struct Constants {
static let defaultiOSPlaceholderColor = UIColor(red: 0.0, green: 0.0, blue: 0.0980392, alpha: 0.22)
}
private let placeholderLabel: UILabel = UILabel()
private var placeholderLabelConstraints = [NSLayoutConstraint]()
@IBInspectable public var placeholder: String = "" {
didSet {
placeholderLabel.text = placeholder
}
}
@IBInspectable public var placeholderColor: UIColor = CustomTextView.Constants.defaultiOSPlaceholderColor {
didSet {
placeholderLabel.textColor = placeholderColor
}
}
override public var font: UIFont! {
didSet {
placeholderLabel.font = font
}
}
override public var textAlignment: NSTextAlignment {
didSet {
placeholderLabel.textAlignment = textAlignment
}
}
override public var text: String! {
didSet {
textDidChange()
}
}
override public var attributedText: NSAttributedString! {
didSet {
textDidChange()
}
}
override public var textContainerInset: UIEdgeInsets {
didSet {
updateConstraintsForPlaceholderLabel()
}
}
override public init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(textDidChange),
name: UITextViewTextDidChangeNotification,
object: nil)
placeholderLabel.font = font
placeholderLabel.textColor = placeholderColor
placeholderLabel.textAlignment = textAlignment
placeholderLabel.text = placeholder
placeholderLabel.numberOfLines = 0
placeholderLabel.backgroundColor = UIColor.clearColor()
placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(placeholderLabel)
updateConstraintsForPlaceholderLabel()
}
private func updateConstraintsForPlaceholderLabel() {
var newConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-(\(textContainerInset.left + textContainer.lineFragmentPadding))-[placeholder]",
options: [],
metrics: nil,
views: ["placeholder": placeholderLabel])
newConstraints += NSLayoutConstraint.constraintsWithVisualFormat("V:|-(\(textContainerInset.top))-[placeholder]",
options: [],
metrics: nil,
views: ["placeholder": placeholderLabel])
newConstraints.append(NSLayoutConstraint(
item: placeholderLabel,
attribute: .Width,
relatedBy: .Equal,
toItem: self,
attribute: .Width,
multiplier: 1.0,
constant: -(textContainerInset.left + textContainerInset.right + textContainer.lineFragmentPadding * 2.0)
))
removeConstraints(placeholderLabelConstraints)
addConstraints(newConstraints)
placeholderLabelConstraints = newConstraints
}
@objc private func textDidChange() {
placeholderLabel.hidden = !text.isEmpty
}
public override func layoutSubviews() {
super.layoutSubviews()
placeholderLabel.preferredMaxLayoutWidth = textContainer.size.width - textContainer.lineFragmentPadding * 2.0
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self,
name: UITextViewTextDidChangeNotification,
object: nil)
}
}