解决UITextView的Placeholder属性

解决UITextView的placeholder属性,并解决了键盘遮挡问题,代码如下:

第一个类:

#import <UIKit/UIKit.h>

@interface HPTextViewInternal : UITextView {

   NSString *placeholder;

   UIColor *placeholderColor;

@private    

   UILabel *placeHolderLabel;

}

@property(nonatomicretainUILabel *placeHolderLabel;

@property(nonatomicretainNSString *placeholder;

@property(nonatomicretainUIColor *placeholderColor;

-(void)textChanged:(NSNotification*)notification;

@end

 

#import "HPTextViewInternal.h"

@implementation HPTextViewInternal

@synthesize placeHolderLabel;

@synthesize placeholder;

@synthesize placeholderColor;

- (void)dealloc

{

   [[NSNotificationCenterdefaultCenterremoveObserver:self];

   [placeHolderLabelrelease]; placeHolderLabel = nil;

   [placeholderColorrelease]; placeholderColor = nil;

   [placeholderrelease]; placeholder = nil;

   [superdealloc];

}

- (void)awakeFromNib

{

   [superawakeFromNib];

   [selfsetPlaceholder:@""];

   [selfsetPlaceholderColor:[UIColorlightGrayColor]];

   [[NSNotificationCenterdefaultCenteraddObserver:selfselector:@selector(textChanged:)name:UITextViewTextDidChangeNotificationobject:nil];

}

- (id)initWithFrame:(CGRect)frame

{

   if( (self = [superinitWithFrame:frame]) )

   {

       [selfsetPlaceholder:@""];

       [selfsetPlaceholderColor:[UIColorlightGrayColor]];

       [[NSNotificationCenterdefaultCenteraddObserver:selfselector:@selector(textChanged:)name:UITextViewTextDidChangeNotificationobject:nil];

   }

   returnself;

}

- (void)textChanged:(NSNotification *)notification

{

   if([[selfplaceholderlength] == 0)

   {

       return;

   }

   

   if([[selftextlength] == 0)

   {

       [[selfviewWithTag:999setAlpha:1];

   }

   else

   {

       [[selfviewWithTag:999setAlpha:0];

   }

}

- (void)drawRect:(CGRect)rect

{

   if( [[selfplaceholderlength] > 0 )

   {

       if ( placeHolderLabel == nil )

       {

           placeHolderLabel = [[UILabelallocinitWithFrame:CGRectMake(8,8,self.bounds.size.width - 16,0)];

           placeHolderLabel.lineBreakMode = UILineBreakModeWordWrap;

           placeHolderLabel.numberOfLines = 0;

           placeHolderLabel.font = self.font;

           placeHolderLabel.backgroundColor = [UIColorclearColor];

           placeHolderLabel.textColor = self.placeholderColor;

           placeHolderLabel.alpha = 0;

           placeHolderLabel.tag = 999;

           [selfaddSubview:placeHolderLabel];

       }

       

       placeHolderLabel.text = self.placeholder;

       [placeHolderLabelsizeToFit];

       [selfsendSubviewToBack:placeHolderLabel];

   }

   

   if( [[selftextlength] == 0 && [[selfplaceholderlength] > 0 )

   {

       [[selfviewWithTag:999setAlpha:1];

   }

   

   [superdrawRect:rect];

}

-(void)setText:(NSString *)text

{

   [supersetText:text];

   [selftextChanged:nil];

   

   BOOL originalValue = self.scrollEnabled;

   //If one of GrowingTextView's superviews is a scrollView, and self.scrollEnabled == NO,

   //setting the text programatically will cause UIKit to search upwards until it finds a scrollView with scrollEnabled==yes

   //then scroll it erratically. Setting scrollEnabled temporarily to YES prevents this.

   [selfsetScrollEnabled:YES];

   [supersetText:text];

   [selfsetScrollEnabled:originalValue];

}

 

-(void)setContentOffset:(CGPoint)s

{

if(self.tracking || self.decelerating){

//initiated by user...

       

       UIEdgeInsets insets = self.contentInset;

       insets.bottom = 0;

       insets.top = 0;

       self.contentInset = insets;

       

else {

 

float bottomOffset = (self.contentSize.height - self.frame.size.height + self.contentInset.bottom);

if(s.y < bottomOffset && self.scrollEnabled){            

           UIEdgeInsets insets = self.contentInset;

           insets.bottom = 8;

           insets.top = 0;

           self.contentInset = insets;            

       }

}

[supersetContentOffset:s];

}

 

-(void)setContentInset:(UIEdgeInsets)s

{

UIEdgeInsets insets = s;

if(s.bottom>8) insets.bottom = 0;

insets.top = 0;

 

[supersetContentInset:insets];

}

-(void)setContentSize:(CGSize)contentSize

{

   // is this an iOS5 bug? Need testing!

   if(self.contentSize.height > contentSize.height)

   {

       UIEdgeInsets insets = self.contentInset;

       insets.bottom = 0;

       insets.top = 0;

       self.contentInset = insets;

   }

   

   [supersetContentSize:contentSize];

}

@end

 

第二个类:

 

#import <UIKit/UIKit.h>

@classHPGrowingTextView;

@classHPTextViewInternal;

@protocol HPGrowingTextViewDelegate

@optional

- (BOOL)growingTextViewShouldBeginEditing:(HPGrowingTextView *)growingTextView;

- (BOOL)growingTextViewShouldEndEditing:(HPGrowingTextView *)growingTextView;

 

- (void)growingTextViewDidBeginEditing:(HPGrowingTextView *)growingTextView;

- (void)growingTextViewDidEndEditing:(HPGrowingTextView *)growingTextView;

 

- (BOOL)growingTextView:(HPGrowingTextView *)growingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;

- (void)growingTextViewDidChange:(HPGrowingTextView *)growingTextView;

 

- (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(float)height;

- (void)growingTextView:(HPGrowingTextView *)growingTextView didChangeHeight:(float)height;

 

- (void)growingTextViewDidChangeSelection:(HPGrowingTextView *)growingTextView;

- (BOOL)growingTextViewShouldReturn:(HPGrowingTextView *)growingTextView;

 

@end

 

@interface HPGrowingTextView : UIView <UITextViewDelegate> {

HPTextViewInternal *internalTextView;

int minHeight;

int maxHeight;

//class properties

int maxNumberOfLines;

int minNumberOfLines;

BOOL animateHeightChange;

//uitextview properties

NSObject <HPGrowingTextViewDelegate> *__unsafe_unretained delegate;

UITextAlignment textAlignment;

NSRange selectedRange;

BOOL editable;

UIDataDetectorTypes dataDetectorTypes;

UIReturnKeyType returnKeyType;

   

   UIEdgeInsets contentInset;

}

 

//real class properties

@propertyint maxNumberOfLines;

@propertyint minNumberOfLines;

@propertyBOOL animateHeightChange;

@property (nonatomic, strong) UITextView *internalTextView;

 

 

//uitextview properties

@property(unsafe_unretained) NSObject<HPGrowingTextViewDelegate> *delegate;

@property(nonatomic,strong) NSString *text;

@property(nonatomic,strong) UIFont *font;

@property(nonatomic,strong) UIColor *textColor;

@property(nonatomic) UITextAlignment textAlignment;    // default is UITextAlignmentLeft

@property(nonatomic) NSRange selectedRange;            // only ranges of length 0 are supported

@property(nonatomic,getter=isEditable) BOOL editable;

@property(nonatomic) UIDataDetectorTypes dataDetectorTypes __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_3_0);

@property (nonatomic) UIReturnKeyType returnKeyType;

@property (assign) UIEdgeInsets contentInset;

@property(nonatomic) BOOL enablesReturnKeyAutomatically;

 

//uitextview methods

//need others? use .internalTextView

- (BOOL)becomeFirstResponder;

- (BOOL)resignFirstResponder;

- (BOOL)isFirstResponder;

 

- (BOOL)hasText;

- (void)scrollRangeToVisible:(NSRange)range;

//设置Placeholder属性

-(void)settingPlaceholder:(NSString *)string;

@end

#import "HPGrowingTextView.h"

#import "HPTextViewInternal.h"

 

@interface HPGrowingTextView(private)

-(void)commonInitialiser;

-(void)resizeTextView:(NSInteger)newSizeH;

-(void)growDidStop;

@end

 

@implementation HPGrowingTextView

@synthesize internalTextView;

@synthesize delegate;

 

@synthesize font;

@synthesize textColor;

@synthesize textAlignment;

@synthesize selectedRange;

@synthesize editable;

@synthesize dataDetectorTypes;

@synthesize animateHeightChange;

@synthesize returnKeyType;

 

// having initwithcoder allows us to use HPGrowingTextView in a Nib. -- aob, 9/2011

- (id)initWithCoder:(NSCoder *)aDecoder

{

   if ((self = [superinitWithCoder:aDecoder])) {

       [selfcommonInitialiser];

   }

   returnself;

}

 

- (id)initWithFrame:(CGRect)frame {

   if ((self = [superinitWithFrame:frame])) {

       [selfcommonInitialiser];

   }

   returnself;

}

 

-(void)commonInitialiser

{

   // Initialization code

   CGRect r = self.frame;

   r.origin.y = 0;

   r.origin.x = 0;

   internalTextView = [[HPTextViewInternalalloc] initWithFrame:r];

   internalTextView.delegate = self;

   internalTextView.scrollEnabled = NO;

   internalTextView.font = [UIFontfontWithName:@"Helvetica"size:13];

   internalTextView.contentInset = UIEdgeInsetsZero;

   internalTextView.showsHorizontalScrollIndicator = NO;

   internalTextView.text = @"-";

   [selfaddSubview:internalTextView];

   

   minHeight = internalTextView.frame.size.height;

   minNumberOfLines = 1;

   

   animateHeightChange = YES;

   

   internalTextView.text = @"";

  //设置Placeholder属性

   [selfsetMaxNumberOfLines:3];

}

-(void)settingPlaceholder:(NSString *)string

{

   internalTextView.placeholder = string;

}

-(CGSize)sizeThatFits:(CGSize)size

{

   if (self.text.length == 0) {

       size.height = minHeight;

   }

   return size;

}

 

-(void)layoutSubviews

{

   [superlayoutSubviews];

   

CGRect r = self.bounds;

r.origin.y = 0;

r.origin.x = contentInset.left;

   r.size.width -= contentInset.left + contentInset.right;

   

   internalTextView.frame = r;

}

 

-(void)setContentInset:(UIEdgeInsets)inset

{

   contentInset = inset;

   

   CGRect r = self.frame;

   r.origin.y = inset.top - inset.bottom;

   r.origin.x = inset.left;

   r.size.width -= inset.left + inset.right;

   

   internalTextView.frame = r;

   

   [selfsetMaxNumberOfLines:maxNumberOfLines];

   [selfsetMinNumberOfLines:minNumberOfLines];

}

 

-(UIEdgeInsets)contentInset

{

   returncontentInset;

}

 

-(void)setMaxNumberOfLines:(int)n

{

   // Use internalTextView for height calculations, thanks to Gwynne <http://blog.darkrainfall.org/>

   NSString *saveText = internalTextView.text, *newText = @"-";

   

   internalTextView.delegate = nil;

   internalTextView.hidden = YES;

   

   for (int i = 1; i < n; ++i)

       newText = [newText stringByAppendingString:@"\n|W|"];

   

   internalTextView.text = newText;

   

   maxHeight = internalTextView.contentSize.height;

   

   internalTextView.text = saveText;

   internalTextView.hidden = NO;

   internalTextView.delegate = self;

   

   [selfsizeToFit];

   

   maxNumberOfLines = n;

}

 

-(int)maxNumberOfLines

{

   returnmaxNumberOfLines;

}

 

-(void)setMinNumberOfLines:(int)m

{

// Use internalTextView for height calculations, thanks to Gwynne <http://blog.darkrainfall.org/>

   NSString *saveText = internalTextView.text, *newText = @"-";

   

   internalTextView.delegate = nil;

   internalTextView.hidden = YES;

   

   for (int i = 1; i < m; ++i)

       newText = [newText stringByAppendingString:@"\n|W|"];

   

   internalTextView.text = newText;

   

   minHeight = internalTextView.contentSize.height;

   

   internalTextView.text = saveText;

   internalTextView.hidden = NO;

   internalTextView.delegate = self;

   

   [selfsizeToFit];

   

   minNumberOfLines = m;

}

 

-(int)minNumberOfLines

{

   returnminNumberOfLines;

}

 

 

- (void)textViewDidChange:(UITextView *)textView

{

//size of content, so we can set the frame of self

NSInteger newSizeH = internalTextView.contentSize.height;

if(newSizeH < minHeight || !internalTextView.hasText) newSizeH = minHeight; //not smalles than minHeight

 if (internalTextView.frame.size.height > maxHeight) newSizeH = maxHeight; // not taller than maxHeight

 

if (internalTextView.frame.size.height != newSizeH)

{

       // [fixed] Pasting too much text into the view failed to fire the height change,

       // thanks to Gwynne <http://blog.darkrainfall.org/>

       

       if (newSizeH > maxHeight && internalTextView.frame.size.height <= maxHeight)

       {

           newSizeH = maxHeight;

       }

       

if (newSizeH <= maxHeight)

{

           if(animateHeightChange) {

               

               if ([UIViewresolveClassMethod:@selector(animateWithDuration:animations:)]) {

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000

                   [UIViewanimateWithDuration:0.1f

                                         delay:0

                                       options:(UIViewAnimationOptionAllowUserInteraction|

                                                UIViewAnimationOptionBeginFromCurrentState)                                 

                                    animations:^(void) {

                                        [selfresizeTextView:newSizeH];

                                    }

                                    completion:^(BOOL finished) {

                                        if ([delegaterespondsToSelector:@selector(growingTextView:didChangeHeight:)]) {

                                            [delegategrowingTextView:selfdidChangeHeight:newSizeH];

                                        }

                                    }];

#endif

               } else {

                   [UIViewbeginAnimations:@""context:nil];

                   [UIViewsetAnimationDuration:0.1f];

                   [UIViewsetAnimationDelegate:self];

                   [UIViewsetAnimationDidStopSelector:@selector(growDidStop)];

                   [UIViewsetAnimationBeginsFromCurrentState:YES];

                   [selfresizeTextView:newSizeH];

                   [UIViewcommitAnimations];

               }

           } else {

               [selfresizeTextView:newSizeH];                

               // [fixed] The growingTextView:didChangeHeight: delegate method was not called at all when not animating height changes.

               // thanks to Gwynne <http://blog.darkrainfall.org/>

               

               if ([delegaterespondsToSelector:@selector(growingTextView:didChangeHeight:)]) {

                   [delegategrowingTextView:selfdidChangeHeight:newSizeH];

               }

           }

}

       

       // if our new height is greater than the maxHeight

       // sets not set the height or move things

       // around and enable scrolling

if (newSizeH >= maxHeight)

{

if(!internalTextView.scrollEnabled){

internalTextView.scrollEnabled = YES;

[internalTextViewflashScrollIndicators];

}

} else {

internalTextView.scrollEnabled = NO;

}

}

if ([delegaterespondsToSelector:@selector(growingTextViewDidChange:)]) {

[delegategrowingTextViewDidChange:self];

}

}

 

-(void)resizeTextView:(NSInteger)newSizeH

{

   if ([delegaterespondsToSelector:@selector(growingTextView:willChangeHeight:)]) {

       [delegategrowingTextView:selfwillChangeHeight:newSizeH];

   }

   

   CGRect internalTextViewFrame = self.frame;

   internalTextViewFrame.size.height = newSizeH; // + padding

   self.frame = internalTextViewFrame;

   

   internalTextViewFrame.origin.y = contentInset.top - contentInset.bottom;

   internalTextViewFrame.origin.x = contentInset.left;

   internalTextViewFrame.size.width = internalTextView.contentSize.width;

   

   internalTextView.frame = internalTextViewFrame;

}

 

-(void)growDidStop

{

if ([delegaterespondsToSelector:@selector(growingTextView:didChangeHeight:)]) {

[delegategrowingTextView:selfdidChangeHeight:self.frame.size.height];

}

}

 

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

   [internalTextViewbecomeFirstResponder];

}

 

- (BOOL)becomeFirstResponder

{

   [superbecomeFirstResponder];

   return [self.internalTextViewbecomeFirstResponder];

}

 

-(BOOL)resignFirstResponder

{

[superresignFirstResponder];

return [internalTextViewresignFirstResponder];

}

 

-(BOOL)isFirstResponder

{

 return [self.internalTextViewisFirstResponder];

}

 

 

 

///

#pragma mark UITextView properties

///

 

-(void)setText:(NSString *)newText

{

   internalTextView.text = newText;

   

   // include this line to analyze the height of the textview.

   // fix from Ankit Thakur

   [selfperformSelector:@selector(textViewDidChange:) withObject:internalTextView];

}

 

-(NSString*) text

{

   returninternalTextView.text;

}

 

///

 

-(void)setFont:(UIFont *)afont

{

internalTextView.font= afont;

[selfsetMaxNumberOfLines:maxNumberOfLines];

[selfsetMinNumberOfLines:minNumberOfLines];

}

 

-(UIFont *)font

{

returninternalTextView.font;

}

 

///

 

-(void)setTextColor:(UIColor *)color

{

internalTextView.textColor = color;

}

 

-(UIColor*)textColor{

returninternalTextView.textColor;

}

 

///

 

-(void)setBackgroundColor:(UIColor *)backgroundColor

{

 [supersetBackgroundColor:backgroundColor];

internalTextView.backgroundColor = backgroundColor;

}

 

-(UIColor*)backgroundColor

{

 returninternalTextView.backgroundColor;

}

 

///

 

-(void)setTextAlignment:(UITextAlignment)aligment

{

internalTextView.textAlignment = aligment;

}

 

-(UITextAlignment)textAlignment

{

returninternalTextView.textAlignment;

}

 

///

 

-(void)setSelectedRange:(NSRange)range

{

internalTextView.selectedRange = range;

}

 

-(NSRange)selectedRange

{

returninternalTextView.selectedRange;

}

 

///

 

-(void)setEditable:(BOOL)beditable

{

internalTextView.editable = beditable;

}

 

-(BOOL)isEditable

{

returninternalTextView.editable;

}

 

///

 

-(void)setReturnKeyType:(UIReturnKeyType)keyType

{

internalTextView.returnKeyType = keyType;

}

 

-(UIReturnKeyType)returnKeyType

{

returninternalTextView.returnKeyType;

}

 

///

 

- (void)setEnablesReturnKeyAutomatically:(BOOL)enablesReturnKeyAutomatically

{

 internalTextView.enablesReturnKeyAutomatically = enablesReturnKeyAutomatically;

}

 

- (BOOL)enablesReturnKeyAutomatically

{

 returninternalTextView.enablesReturnKeyAutomatically;

}

 

///

 

-(void)setDataDetectorTypes:(UIDataDetectorTypes)datadetector

{

internalTextView.dataDetectorTypes = datadetector;

}

 

-(UIDataDetectorTypes)dataDetectorTypes

{

returninternalTextView.dataDetectorTypes;

}

 

///

 

- (BOOL)hasText{

return [internalTextViewhasText];

}

 

- (void)scrollRangeToVisible:(NSRange)range

{

[internalTextViewscrollRangeToVisible:range];

}

 

/

/

#pragma mark -

#pragma mark UITextViewDelegate

 

 

///

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {

if ([delegaterespondsToSelector:@selector(growingTextViewShouldBeginEditing:)]) {

return [delegategrowingTextViewShouldBeginEditing:self];

} else {

returnYES;

}

}

 

 

///

- (BOOL)textViewShouldEndEditing:(UITextView *)textView {

if ([delegaterespondsToSelector:@selector(growingTextViewShouldEndEditing:)]) {

return [delegategrowingTextViewShouldEndEditing:self];

} else {

returnYES;

}

}

 

 

///

- (void)textViewDidBeginEditing:(UITextView *)textView {

if ([delegaterespondsToSelector:@selector(growingTextViewDidBeginEditing:)]) {

[delegategrowingTextViewDidBeginEditing:self];

}

}

 

 

///

- (void)textViewDidEndEditing:(UITextView *)textView {

if ([delegaterespondsToSelector:@selector(growingTextViewDidEndEditing:)]) {

[delegategrowingTextViewDidEndEditing:self];

}

}

 

 

///

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range

replacementText:(NSString *)atext {

//weird 1 pixel bug when clicking backspace when textView is empty

if(![textView hasText] && [atext isEqualToString:@""]) returnNO;

//Added by bretdabaker: sometimes we want to handle this ourselves

   if ([delegaterespondsToSelector:@selector(growingTextView:shouldChangeTextInRange:replacementText:)])

       return [delegategrowingTextView:selfshouldChangeTextInRange:range replacementText:atext];

if ([atext isEqualToString:@"\n"]) {

if ([delegaterespondsToSelector:@selector(growingTextViewShouldReturn:)]) {

if (![delegateperformSelector:@selector(growingTextViewShouldReturn:) withObject:self]) {

returnYES;

} else {

[textView resignFirstResponder];

returnNO;

}

}

}

returnYES;

   

}

 

///

- (void)textViewDidChangeSelection:(UITextView *)textView {

if ([delegaterespondsToSelector:@selector(growingTextViewDidChangeSelection:)]) {

[delegategrowingTextViewDidChangeSelection:self];

}

}

@end

感谢开源的朋友。

转载于:https://www.cnblogs.com/sany007/archive/2013/02/22/2922536.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值