العنصر النائب في 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
UIPLACHORALDEXTVIEVIEN.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
{
}
لم أكن سعيدا جدا بأي من الحلول المنشورة لأنها كانت ثقيلة بعض الشيء. إضافة طرق عرض إلى العرض ليست مثالية حقا (خاصة في 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: أشر إلى ريبو الجديد.
ما يمكنك القيام به هو إعداد عرض النص مع بعض القيمة الأولية في text
الممتلكات، وتغيير textColor
ل [UIColor grayColor]
أو شيئا من هذا القبيل. ثم، كلما أصبحت وجهة نظر النص قابلة للتحرير، قم بإلغاء تحديد النص وتقديم مؤشر، وإذا كان حقل النص فارغ من أي وقت مضى مرة أخرى، ضع نص العنصر النائب الخاص بك مرة أخرى. تغيير اللون إلى [UIColor blackColor]
حسب الاقتضاء.
ليس بالضبط نفس وظيفة العنصر النائب في uitextfield، لكنه قريب.
لقد وجدت نفسي طريقة سهلة للغاية لتقليد صاحب المكان
- في NIB أو التعليمات البرمجية قم بتعيين TextColor TextColor الخاص بك إلى LightGrayColor (معظم الوقت)
- تأكد من ارتباط مندوب نصي النص بمالك الملف وتطبيق UITEXTViewDelegate في ملف رأسك
- اضبط النص الافتراضي لعرض النص الخاص بك إلى (مثال: "Foobar Holoryholder")
- تنفيذ: (BOOL) TextViewShouldBegediting: (UITEXTVIEV *) نص النص
يحرر:
تغيرت إذا كانت البيانات لمقارنة العلامات بدلا من النص. إذا حذف المستخدم نصها، كان من الممكن أيضا حذف جزء عن طريق الخطأ عن طريق الخطأ @"Foobar placeholder"
هذا يعني إذا أعيد إدخال المستخدم طريقة التفويض التالية، -(BOOL) textViewShouldBeginEditing:(UITextView *) textView
, ، لن تعمل كما هو متوقع. حاولت مقارنة بلون النص في بيان إذا وجدت أن اللون الرمادي الفاتح المصمم في منشئ واجهة ليس هو نفسه لون رمادي فاتح مجموعة في الكود مع [UIColor lightGreyColor]
- (BOOL) textViewShouldBeginEditing:(UITextView *)textView
{
if(textView.tag == 0) {
textView.text = @"";
textView.textColor = [UIColor blackColor];
textView.tag = 1;
}
return YES;
}
من الممكن أيضا إعادة تعيين نص العنصر النائب عند إرجاع لوحة المفاتيح و "طول النص إلى" == 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
وضع لإعداده الصحيح، لكن هذا لا ينبغي أن يكون صعبا جدا
قمت بإعادة إجابة 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
👇👇👇👇
فيما يلي ميناء سريع من "SamtextView" رمز OBJC المنشور كواحد من المركبات الأولى من الردود على السؤال. لقد اختبرتها على نظام التشغيل iOS 8. اخترت بضعة أشياء، بما في ذلك إزاحة الحدود لوضع نص العنصر النائب، حيث كان الأصلي مرتفعا للغاية وغير صحيح للغاية (اقتراح مستعمل في إحدى التعليقات على هذا المنصب).
أعلم أن هناك الكثير من الحلول البسيطة، لكني أحب نهج UITEXTVIVIVEPVIEW لأنه قابل لإعادة الاستخدام وليس لدي فئات فوضى باستخدام الآليات.
SWIFT 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)
}
}
SWIFT 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. في viewdididload يجب عليك تهيئة مثل
- (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;
}
آسف لإضافة إجابة أخرى، لكنني سحبت شيئا مثل هذا قبالة وهذا خلق أقرب نوع من العنصر النائب الأقرب إلى UITEX
أمل أن هذا يساعد شخصاما.
-(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 متوفر في Iqkeyboard Manager، من السهل استخدام ودمج فئة تعيين فقط من النصوص الخاصة بك إلى iqtextview ويمكنك استخدام خاصيةها لإعداد تسمية العنصر النائب مع اللون الذي تريده. يمكنك تنزيل المكتبة من iqkeyboardmanager.
أو يمكنك تثبيته من Cocoapods.
طريقة بسيطة لاستخدام هذا في حدود بعض الرمز:
خذ تسمية واحدة تصل إلى 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 إذا كنت تحب العنصر النائب لتبدو جيدة بعد الرسوم المتحركة Autolayout وما شابه ذلك.
يمكنك أيضا إنشاء فئة TextViewwithplaceholdhdholdhdhdhdhder كقسم فرعية من 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". أحببت سام soffes.فكرة استخدام الإخطارات، لكنني لم أحب الرحلة: الكتابة فوق. يبدو مبالغة بالنسبة لي. أعتقد أنني قدمت تنفيذا نظيفا للغاية.
يمكنك أن تنظر إلى الفئة الفرعية الخاصة بي هنا. وبعد يتم تضمين مشروع تجريبي أيضا.
يحتوي هذا الموضوع على الكثير من الإجابات، ولكن إليك الإصدار الذي أفضله.
هو - هي يمتد الموجود 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، وما نقدمه نحن (كمطورين) تحتاج فعلا في تطبيقاتنا.تكتب هذا الرمز مرة واحدة، وتضيفه إلى مكتبتك الخاصة بملفات .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 هو نصفي النصي.
أعلن الآن
-(void)textViewDidChange:(UITextView *)textView {
if (![textView hasText]){
lbl.hidden = NO;
}
else{
lbl.hidden = YES;
}
}
ونظامك النائب الخاص بك جاهز!
أوصي باستخدام 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];
}
}
أو يمكنك إضافة تسمية في 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
بحيث يتم محاذاة زوايا اليسار العليا. أضف نص العنصر النائب الخاص بك إلى حقل النص.
في viewdididload، أضف:
[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;
}
@نهاية
لا تنس توصيل TextView و Uilabel إلى FilesOcker من XIB
إلقاء نظرة على utplaceholdertextview..
هذه هي الفئة الفئة الفرعية المريحة من uitextview التي تدعم العنصر النائب التافئ إلى ذلك من uitextfield. الخصائص الرئيسية:
- لا يستخدم فرعيون
- لا يتجاوز الرحلة:
- قد يكون العنصر النائب ذو طول تعسفيا، وأصبح بنفس الطريقة مثل النص المعتاد
قرأت من خلال كل هذه، لكن جاء مع حل قصير جدا، سويفت 3، الذي عمل في جميع اختباراتي. يمكن أن يقف عمومية أكثر قليلا، لكن العملية بسيطة. إليك الأمر بأكمله الذي أسميه "TextViewWathropholdhder".
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)
}
}