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
และทำให้ชั้นผู้ปกครอง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
และทำให้ชั้นผู้ปกครองUITextViewDelegate
ก่อนรวมถึงวิธีการเหล่านี้เช่น
class MyClass: UITextViewDelegate
{
}
text
คุณลักษณะของ textview ซึ่งค่อนข้างดี .. ทุกที่ที่วิธีนี้แก้ไขมัน
ฉันไม่พอใจกับวิธีแก้ปัญหาใด ๆ ที่โพสต์เนื่องจากหนักมาก การเพิ่มมุมมองไปยังมุมมองนั้นไม่เหมาะอย่างยิ่ง (โดยเฉพาะใน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:ตอนนี้เป็นเอกสารและรองรับการใช้งานในเครื่องมือสร้างส่วนต่อประสาน
อัปเดต 11/24/13:ชี้ไปที่ repo ใหม่
setText
เพื่ออัปเดตตัวยึดตำแหน่งเมื่อเปลี่ยนคุณสมบัติข้อความแบบเป็นโปรแกรม: - (เป็นโมฆะ) setText: (NSString *) สตริง {[super setText: string]; [ตนเอง _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
}
}
Simple Swift 3 solution
เพิ่ม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 โซลูชันของฉันไม่ต้องการให้คุณ subclass และทำงานถ้าผู้ใช้พิมพ์โดยตรงหรือวางข้อความ!
- (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
และทำให้คลาส parent เป็นตัวแทน UITextView ก่อนรวมวิธีการเหล่านี้เช่น
@interface MyClass () <UITextViewDelegate>
@end
SZTextView
ผมแนะนำให้ใช้
https://github.com/glaszig/SZTextView
เพิ่มค่าเริ่มต้นของคุณUITextView
จากstoryboard
นั้นเปลี่ยนคลาสที่กำหนดเองเป็นSZTextView
ชอบด้านล่าง👇👇👇👇
จากนั้นคุณจะเห็นตัวเลือกใหม่สองตัวในAttribute Inspector
👇👇👇👇
ด้านล่างนี้เป็นพอร์ต Swift ของรหัส "Objc" SAMTextView "ที่โพสต์เป็นหนึ่งในการตอบคำถามจำนวนหนึ่ง ฉันทดสอบบน iOS 8 ฉันปรับแต่งสิ่งต่าง ๆ สองสามอย่างรวมถึงขอบเขตชดเชยตำแหน่งข้อความตัวยึดเนื่องจากต้นฉบับสูงเกินไปและถูกเกินไป (ใช้คำแนะนำจากหนึ่งในความคิดเห็นต่อโพสต์นั้น)
ฉันรู้ว่ามีวิธีแก้ปัญหาง่าย ๆ มากมาย แต่ฉันชอบวิธีการของ subclassing 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;
}
}
(การตรวจสอบครั้งที่สองในอื่นถ้าคำสั่งสำหรับกรณีที่ไม่มีอะไรถูกป้อนและผู้ใช้กด backspace)
เพียงตั้งค่าคลาสของคุณเป็น 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 Manager มันใช้งานง่ายและบูรณาการเพียงแค่ตั้งค่าคลาสของมุมมองข้อความของคุณเป็น IQTextView และคุณสามารถใช้คุณสมบัติของมันเพื่อตั้งค่าป้ายบอกตำแหน่งด้วยสีที่คุณต้องการ คุณสามารถดาวน์โหลดห้องสมุดจากIQKeyboardManager
หรือคุณสามารถติดตั้งได้จาก cocoapods
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];
มิฉะนั้นตัวละครตัวแรกที่ถูกป้อนใน textview ถูกวางไว้ที่ส่วนท้ายของข้อความ
วิธีง่ายๆในการใช้สิ่งนี้ภายในโค้ดบางบรรทัด:
ใช้หนึ่งป้ายกำกับจนถึง UITextView ใน. เชื่อมต่อป้ายกำกับนี้กับรหัสของคุณหลังจากนั้น
- (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
วิธีการที่อาจเปลี่ยนแบบอักษรและ thigns อื่น ๆ ที่อาจส่งผลกระทบต่อพวกเขา คุณอาจต้องการข้ามการทำพจนานุกรม "ขี้เกียจ" ของพจนานุกรมคุณลักษณะหากนั่นไม่ทำให้เกิดปัญหา
แก้ไข:
อย่าลืมเรียก 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' ฉันชอบความคิดของSam Soffes ที่ใช้การแจ้งเตือน แต่ฉันไม่ชอบ drawRect: overwrite ดูเหมือน overkill กับฉัน ฉันคิดว่าฉันใช้งานได้ดีมาก
กระทู้นี้มีคำตอบมากมาย แต่นี่เป็นรุ่นที่ฉันชอบ
มันขยาย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
คุณสามารถใช้ตัวยึดตำแหน่งใน
มีหนึ่ง gotcha ว่า
หากคุณทำสิ่งนี้:
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 ของคุณก็พร้อมแล้ว!
ฉันแนะนำให้ใช้พ็อด '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];
}
}
หรือคุณสามารถเพิ่มป้ายกำกับใน textview เช่นเดียวกับ
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 ตอนนี้คุณสามารถซ่อนป้ายกำกับได้ เมื่อคุณคลิกที่ 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
อย่าลืมเชื่อมต่อ textView และ UILabel กับ filesowner จาก xib
นี่คือคลาสย่อยที่สะดวกของ 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)
}
}