UITextView のプレースホルダー
-
19-09-2019 - |
質問
私のアプリケーションは UITextView
. 。今私が欲しいのは、 UITextView
に設定できるものと同様のプレースホルダーを用意するには、 UITextField
.
これを行う方法?
解決
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
これらの方法例えば含む前に、親クラスにUITextViewDelegate
を行います。
@interface MyClass () <UITextViewDelegate>
@end
スウィフト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
これらの方法例えば含む前に、親クラスにUITextViewDelegate
を行います。
class MyClass: UITextViewDelegate
{
}
掲載されている解決策はどれも少し重かったので、あまり満足できませんでした。ビューにビューを追加することはあまり理想的ではありません (特に 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
サブビューを使用しない (またはリークがない) ため、他のものよりもはるかに単純です。ご自由にお使いください。
2011 年 11 月 10 日更新: 現在は文書化されており、Interface Builder での使用がサポートされています。
2013 年 11 月 24 日の更新: 新しいリポジトリをポイントします。
何ができることはtext
プロパティ内のいくつかの初期値を持つテキストビューを設定し、textColor
または類似した何かに[UIColor grayColor]
に変更されます。その後、いつでもテキストビューは、テキストをクリアし、カーソルを提示し、編集可能になり、テキストフィールドが再びかつて空の場合は、お使いのプレースホルダーテキストは、元に戻します。適宜[UIColor blackColor]
する色を変更します。
これは、UITextFieldの内のプレースホルダの機能と全く同じではないのですが、それは近いです。
プレースホルダーを模倣する非常に簡単な方法を見つけました
- NIB またはコードで、textView の textColor を lightGrayColor に設定します(ほとんどの場合)
- textView のデリゲートがファイルの所有者にリンクされていることを確認し、ヘッダー ファイルに UITextViewDelegate を実装してください。
- テキスト ビューのデフォルトのテキストを次のように設定します (例:「Foobar プレースホルダー」)
- 埋め込む:(BOOL) textViewShouldBeginEditing:(UITextView *)textView
編集:
テキストではなくタグを比較するように if ステートメントを変更しました。ユーザーがテキストを削除した場合、プレースホルダーの一部も誤って削除してしまう可能性がありました。 @"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;
}
}
は、
によりUITextView
にラベルを設定することができます
[UITextView addSubView:lblPlaceHoldaer];
とTextViewdidChange
方法でそれを隠しています。
これはシンプル&簡単な方法です。
誰かがスウィフトのためのソリューションを必要とする場合:
あなたのクラスに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
}
}
簡単のスイフト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
位置でプレーする必要があるかもしれませんが、それはあまりにも難しいことではありません。
UITextView
の編集を開始だけではなく、それをタップするまで、プレースホルダが表示されたままとなるよう私は、KmKndyの答えを拡張しました。これは、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
するために、そのカスタムクラスを変更
以下は、質問に対する最初の数少ない返信の 1 つとして投稿された「SAMTextView」ObjC コードの Swift ポートです。iOS 8でテストしてみました。元のテキストが高すぎて右端すぎたため、プレースホルダー テキストの配置の境界オフセットなど、いくつかの点を微調整しました (その投稿へのコメントの 1 つで提案を使用しました)。
単純な解決策がたくさんあることは承知していますが、私は UITextView をサブクラス化するアプローチが好きです。なぜなら、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;
}
}
(それ以外では第2チェックステートメントは、何も入力されない場合のためのものであり、ユーザーがバックスペースを押した場合)
ちょうど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;
}
別の答えを追加する申し訳ありませんが、しかし、私はちょうどこのオフのようなものを引っ張り、これはプレースホルダの最も近いツー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);
}
}
こんにちは、あなたはそれがIQTextViewにあなたのTextViewのちょうどセットクラスを使用して統合するのは簡単だし、あなたが欲しい色でプレースホルダのラベルを設定するためのプロパティを使用することができますIQKeyboardマネージャで使用可能なIQTextViewを使用することができます。 あなたは IQKeyboardManagerする
からライブラリをダウンロードすることができますかcocoapodsからそれをインストールすることができます。
簡単な方法は、コードのいくつかの行の中にこれを使用するには
.nibにUITextViewに1つのラベルを取ります あなたのコードにこのラベルを接続し、 それの後ます。
- (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;
}
iOS7 で動作するように Sam Soffes の実装を変更しました。
- (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
フォントやその他の影響を与える可能性のあるメソッドを変更する可能性があります。問題がなければ、属性ディクショナリの「怠惰な」作成をスキップすることもできます。
編集:
自動レイアウト アニメーションなどの後にプレースホルダーの見栄えを良くしたい場合は、setBounds のオーバーライドされたバージョンで setNeedsDisplay を忘れずに呼び出してください。
また、UITextViewのサブクラスとして新しいクラスTextViewWithPlaceholderを作成することができます。
(このコードは、一種のラフです - 。しかし、私はそれが正しい軌道に乗ってだと思います)。
@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」のサブクラスの自分自身のバージョンを作りました。私は、通知を使用するの のサムSoffesのアイデアを気に入って、私はのdrawRectを言っていませんでした:上書きします。やり過ぎ私には思えます。私は、私は非常にきれいな実装をしたと考えています。
あなたは私のサブクラスをhref="https://github.com/gcamp/GCPlaceholderTextView">で見ることができます。デモプロジェクトも含まれています。
このスレッドは、答えの多くを持っていたが、ここで私が好むのバージョンがあります。
これは に拡張し、既存の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
でプレースホルダを使用することができます。
1つの落とし穴は、しかしあります。
あなたがこれを行う場合:
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がで私たちを提供するものとの間に、そして私たち(開発者など)「ギャップを埋める」と私は、このようなソリューションが好きの、実際に我々のアプリでの必要があります。あなたは時間をかけて、SDKが実際より少なくなってきてイライラを開始し、一度このコードを書き、「ヘルパー」の.m / .hファイルのライブラリに追加し、かつます。
(私は...、私のUITextViewsに「クリア」ボタンを追加するためうるさく
UITextField
ではなくUITextView
に存在する別のものを同様のヘルパーを書きました) まず.hファイルにラベルを取ります。
ここで私が取る。
UILabel * lbl;
その後のviewDidLoadの下.Mでそれを宣言する。
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プレースホルダの準備ができている!
私はポッドを使用することをお勧め '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;
}
のTextViewの上にラベルを置きます。
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
のプレースホルダのわずかなインデントを再現する1です
その左上の角が揃うように
右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];
}
}
それが簡単にできます
1 UILabelを作成し、テキストビューの上に置きます(プレースホルダセットカラーグレー、あなたのXIBですべてこれを行うことができ、テキストを与えます) 今、あなたはファイルをヘッダにUILabelともtextviewDelegateを宣言 あなたはTextViewの上でクリックしたときに今、あなたは、単にラベルを非表示にすることができます。
以下の完全なコード
ヘッダ
@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
タグXIBからfilesownerするのTextViewとUILabelを接続することを忘れてはいけません
を見てみましょう UTPlaceholderTextView.
これは、UITextField と同様のプレースホルダーをサポートする UITextView の便利なサブクラスです。主な特徴:
- サブビューを使用しません
- drawRect をオーバーライドしません:
- プレースホルダーは任意の長さにすることができ、通常のテキストと同じようにレンダリングされます。
私はこれらのすべてを読み、私のすべてのテストで働いている非常に短い、スウィフト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()
}
}
私は、迅速でクラスを書いています。必要な時はいつでもあなたは、このクラスをインポートすることができます。
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)
}
}