UITextView -- 文本视图
UITextView继承自UIScrollView,是一个可滚动的多行文本区域。UITextView支持使用自定义的样式信息来显示文本,也支持对文本编辑,通常使用UITextView来显示多行文本,例如在显示大型文本文档的正文时。
UITextView可以通过设置attributedText属性来支持富文本(iOS 6之前的版本不支持富文本),设置attributedText属性的值将导致UITextView使用富文本字符串中提供的样式信息来显示文本,但需要注意UITextView的font、textColor和textAlignment等这些适用于UITextView中所有文本的样式属性,这些属性会与attributedText属性设置的富文本样式冲突。例如textColor,如果如果在为attributedText属性设置富文本之前设置此属性,不会影响富文本的颜色,如果在为attributedText属性设置富文本之后设置此属性,则该属性设置的颜色值会应用于attributedText属性中的整个字符串。
常用属性
@property(nullable,nonatomic,weak) id<UITextViewDelegate> delegate;
属性描述 :设置UITextView的代理,UITextView代理对象会响应与UITextView编辑相关的消息,可以使用代理跟踪UITextView中文本内容的更改和文本选中状态的更改。
@property(null_resettable,nonatomic,copy) NSString *text;
属性描述 : UITextView显示的文本。在iOS 6及更高版本中,如果为该属性重新分配新文本之前设置过attributedText属性,那么会以没有任何样式的富文本来显示重新分配的新文本;如果没有设置过attributedText属性,则UITextView使用font、textColor和textAlignment等与样式相关的属性设置重新分配的新文本样式。
@property(nullable,nonatomic,strong) UIFont *font;
属性描述 :UITextView显示文本的字体,此属性应用于UITextView中的整个文本字符串,此属性的默认值是系统字体的主体样式,可以使用UIFont类的方法获取有关系统上可用字体的信息。在iOS 6及更高版本中,如果只想将字体应用于文本的一部分,则必须使用所需的样式信息创建一个新的富文本字符串,并将其分配给attributedText属性,如果在设置过attributedText属性之后为该属性分配新字体,将导致新字体应用于attributedText属性设置的整个富文本内容。
@property(nullable,nonatomic,strong) UIColor *textColor;
属性描述 : UITextView显示文本的颜色。此属性应用于UITextView中的整个文本字符串,默认文本颜色为黑色。在iOS 6及更高版本中,如果只想将文本颜色应用于文本的一部分,则必须使用所需的样式信息创建一个新的富文本字符串,并将其分配给attributedText属性,如果在设置过attributedText属性之后为该属性分配新文本颜色,将导致新文本颜色应用于attributedText属性设置的整个富文本内容。
@property(nonatomic) NSTextAlignment textAlignment;
属性描述 :UITextView显示文本的对齐方式,此属性应用于UITextView中的整个文本字符串,该属性的默认值是NSTextAlignmentNatural。在iOS 6及更高版本中,如果只想将文本的对其方式应用于文本的一部分,则必须使用所需的样式信息创建一个新的富文本字符串,并将其分配给attributedText属性,如果在设置过attributedText属性之后为该属性分配新的对齐方式,将导致新的对齐方式应用于attributedText属性设置的整个富文本内容。
@property(nonatomic,getter=isSelectable) BOOL selectable API_AVAILABLE(ios(7.0));
属性描述 :一个布尔值,指示UITextView是否可选,它控制用户选择内容以及与url和附件交互的能力,默认值为YES,可以选择。
@property(nonatomic,getter=isEditable) BOOL editable API_UNAVAILABLE(tvOS);
属性描述 : 一个布尔值,指示UITextView是否可编辑,此属性的默认值为“YES”,可以编辑。
@property(nonatomic) UIDataDetectorTypes dataDetectorTypes API_AVAILABLE(ios(3.0)) API_UNAVAILABLE(tvOS);
属性描述 :在UITextView中检测该属性指定的数据类型(电话号码、http链接等)并转换为可点击的URL,点击时由UITextView打开负责处理URL类型的应用程序,并将URL传递给它。需要注意的是如果UITextView的editable属性设置为“YES”时不会进行数据检测。
//UIDataDetectorTypes枚举值如下:
typedef NS_OPTIONS(NSUInteger, UIDataDetectorTypes) {
UIDataDetectorTypePhoneNumber = 1 << 0, // 电话号码检测
UIDataDetectorTypeLink = 1 << 1, // URL 检测
UIDataDetectorTypeAddress API_AVAILABLE(ios(4.0)) = 1 << 2, // 街道地址检测
UIDataDetectorTypeCalendarEvent API_AVAILABLE(ios(4.0)) = 1 << 3, // 事件检测
UIDataDetectorTypeShipmentTrackingNumber API_AVAILABLE(ios(10.0)) = 1 << 4, // 发货运单号检测
UIDataDetectorTypeFlightNumber API_AVAILABLE(ios(10.0)) = 1 << 5, // 班机号码检测
UIDataDetectorTypeLookupSuggestion API_AVAILABLE(ios(10.0)) = 1 << 6, // 用户可能需要查找信息
UIDataDetectorTypeNone = 0, // 禁用检测
UIDataDetectorTypeAll = NSUIntegerMax // 启用所有类型,包括以后可能添加的类型
} API_UNAVAILABLE(tvOS);
例如检测一条Url链接时 :
@property(nonatomic) BOOL allowsEditingTextAttributes API_AVAILABLE(ios(6.0));
属性描述 : 一个布尔值,指示UITextView是否允许用户编辑文本样式信息。当设置为YES时,UITextView允许用户更改当前选中文本的基本样式,UITextView提供编辑菜单中列出了可用的文本样式选项,并且仅适用于当前选中的文本。此属性的默认值为NO。
设置为YES时会在编辑菜单中提供该选项:
@property(null_resettable,copy) NSAttributedString *attributedText API_AVAILABLE(ios(6.0));
属性描述 :UITextView显示的富文本。如果在将新值赋给该属性之前设置过text属性,那么该属性也会用相同的字符串数据替换text属性的值,但是没有任何样式信息,并且会将设置该属性之前设置的font、textColor和textAlignment等与UITextView显示文本样式相关的属性进行更新。
@property(nonatomic,copy) NSDictionary<NSAttributedStringKey, id> *typingAttributes API_AVAILABLE(ios(6.0));
属性描述 :应用于用户新输入的文本的样式属性,此字典包含要应用于用户新输入的文本的属性key(和相应的值),当UITextView的选择改变时(将第一次输入的内容完全删除、更改光标位置等),字典的内容将自动清除,此属性设置的样式将变得无效。
@property (nullable, readwrite, strong) UIView *inputView;
属性描述 :当UITextView成为第一个响应者时显示的自定义输入视图,如果此属性中的值为nil,则文本视图在成为第一个响应者时显示标准系统键盘,此属性的默认值为nil。
效果如下 :
@property (nullable, readwrite, strong) UIView *inputAccessoryView;
属性描述 :当UITextView成为第一个响应者时,将分配给此属性的视图显示在标准系统键盘之上(如果提供自定义输入视图,则显示在自定义输入视图之上), 此属性的默认值为nil。
例如,可以使用此属性将自定义工具栏附加到键盘上:
@property(nonatomic) BOOL clearsOnInsertion API_AVAILABLE(ios(6.0));
属性描述 : 一个布尔值,指示UITextView是否成为第一个响应者并选中UITextView现有的所有文本,如果设置此属性为YES时,UITextView默认成为第一响应者后会选中UITextView现有的所有文本,并显示一个编辑UI,此时输入内容会插入新文本以替换UITextView中已经选中的文本,之后的操作会忽略该属性。切换光标位置或使UITextView失去第一响应者等操作之后,再次操作UITextView也会忽略该属性。
会产生这种选中状态 :
@property(nonatomic, assign) UIEdgeInsets textContainerInset API_AVAILABLE(ios(7.0));
属性描述 :UITextView中文本容器布局文本的的内边距,此属性默认值为(8,0,8,0),有时会因为文字换行而使内边距看起来比设置的值要大。
@property(nonatomic,readonly) NSLayoutManager *layoutManager API_AVAILABLE(ios(7.0));
属性描述 :通过此属性可以比较方便的访问UITextView的文本容器布局管理对象。
@property(null_resettable, nonatomic, copy) NSDictionary<NSAttributedStringKey,id> *linkTextAttributes API_AVAILABLE(ios(7.0));
属性描述 :应用于UITextView显示的内容中被检测为网址URL链接(UIDataDetectorTypeLink)的文本样式属性,默认属性指定蓝色文本。
@property (nonatomic) BOOL usesStandardTextScaling API_AVAILABLE(ios(13.0));
属性描述 : 一个布尔值,用于确定文本的呈现比例。当此属性的值为 YES 时,UIKit 会自动调整UITextView中文本的渲染以匹配标准文本缩放。例如在iOS 中使用 13 磅字体的文本看起来就像 macOS 中使用 13 磅字体的文本。
UITextViewDelegate代理函数
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;
函数描述 :询问代理是否应在指定的UITextView中开始编辑。通常情况下,当用户执行会启动编辑会话的操作时,UITextView首先调用此方法,以查看是否应该继续进行编辑。在大多数情况下,只需从这个方法返回YES就可以继续编辑。
由代理实现的此方法是可选的。如果代理没有实现它,编辑过程就像这个方法已经返回YES一样。
参数 :
textView :即将开始编辑的UITextView文本视图对象。
返回值 :
如果应启动编辑会话,则为“YES”;否则,为“NO”,则不允许编辑。
- (BOOL)textViewShouldEndEditing:(UITextView *)textView;
函数描述 :询问代理是否应在指定的UITextView中停止编辑。当要求UITextView放弃第一响应程序状态时(当用户试图将编辑焦点更改为其他控件时可能会发生这种情况)调用此方法,但是在焦点实际更改之前,UITextView调用此方法以使代理有机会决定是否应该放弃第一响应程序状态。
通常,将从该方法返回YES以允许UITextView放弃第一响应者状态。但是如果代理要验证UITextView的内容是否合理时则可能返回NO,通过返回NO可以防止用户在UITextView包含有效值之前切换到其他控件。
注意,此方法仅提供有关编辑是否应结束的建议,即使从该方法返回NO,编辑仍有可能结束。例如当UITextView被从其父视图或窗口中删除而被迫放弃第一响应程序状态时,可能会发生这种情况。
代理对此方法的实现是可选的,如果代理没有实现它,则第一响应程序状态将被放弃,如同此方法返回了YES一样。
参数 :
textView :编辑即将结束的文本视图。
返回值 :
如果应停止编辑,则为“YES”;否则,如果应继续编辑会话,则为“NO”
- (void)textViewDidBeginEditing:(UITextView *)textView;
函数描述 :通知代理已开始编辑指定的UITextView。此方法的实现是可选的,UITextView在用户开始在UITextView中进行编辑之后,在实际进行任何更改之前,立即将此消息发送给其代理。可以使用此方法设置任何与编辑相关的数据结构,并通常为代理准备接收将来的编辑消息。
参数 :
textView : 开始编辑的UITextView。
- (void)textViewDidEndEditing:(UITextView *)textView;
函数描述 :通知代理指定的UITextView的编辑已结束。此方法的实现是可选的,UITextView在关闭任何未完成的编辑并放弃其第一响应状态后将此消息发送给其代理。可以使用此方法来销毁开始编辑时设置的任何数据结构或更改任何状态信息。
参数 :
textView : 结束编辑的UITextView。
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
属性描述 :询问代理是否应在UITextView中替换指定的文本。每当用户键入新字符或删除现有字符时,UITextView调用此方法。此方法的实现是可选的,在文本提交到UITextView存储之前,可以使用此方法替换文本。例如,拼写检查器可以使用此方法将拼写错误的单词替换为正确的拼写。
参数 :
textView : 包含更改的UITextView。
range : 当前选择范围。如果范围长度为0,则范围反映当前插入点。如果用户按下Delete键,则范围的长度为1,空字符串对象将替换该字符。
text :要插入的文本。
返回值 :
如果旧文本应替换为新文本,则为“YES”;如果应中止替换操作,则为“NO”。
- (void)textViewDidChange:(UITextView *)textView;
函数描述 :通知代理指定UITextView中的文本或属性已被用户更改。UITextView调用此方法以响应用户对文本发起的更改,此方法不会响应以编程方式启动的更改而调用。
参数 :
textView :包含更改的UITextView。
(void)textViewDidChangeSelection:(UITextView *)textView;
函数描述 :通知代理在指定的UITextView中更改了对文本选择状态。此方法的实现是可选的,可以使用文本视图的selectedRange属性来获取新选择的文本所在的范围。
参数 :
textView : 选中内容已更改的UITextView。
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction API_AVAILABLE(ios(10.0));
函数描述 :询问代理指定的UITextView是否允许在指定的文本范围内与指定的URL进行指定类型的用户交互。仅在与URL链接的第一次交互时调用此方法。
此方法在点击UITextView中被检测为链接数据类型(电话号码、http链接等)的文本时,在与URL链接的第一次交互时调用。例如,当用户希望第一次与URL交互时,调用此方法以显示一个他们可以执行的操作列表,然后用户从列表中选择打开操作,则不调用此方法,因为“打开”表示与同一URL的第二次交互。注:用户长按被检测为链接数据类型(电话号码、http链接等)的文本时,会显示系统的可以执行的操作列表。
UITextView中的链接只有在UITextView可选择但不可编辑时才是交互式的,也就是说需要UITextView的selectable属性的值为YES并且editable属性的值为NO。
参数 :
textView :包含文本附件的UITextView。
URL :要处理的URL。
characterRange : 包含URL的字符范围。
interaction : 正在发生的交互类型(有关可能的值,请参阅UITextItemInteraction)。
返回值 :
如果允许与URL交互,则为YES;如果不允许交互,则为NO。
- UITextItemInteraction的枚举值如下:
typedef NS_ENUM(NSInteger, UITextItemInteraction) {
UITextItemInteractionInvokeDefaultAction,//用户希望对文本项执行默认操作;例如,打开URL。
UITextItemInteractionPresentActions,//用户希望看到可以对文本项执行的操作列表,例如以其他方式打开链接或从链接下载内容。
UITextItemInteractionPreview,//用户希望获得文本项表示的内容的预览,例如通过启动链接上的peek和pop。
} API_AVAILABLE(ios(10.0));
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction API_AVAILABLE(ios(10.0));
函数描述 :询问委托指定的UITextView是否应允许在给定文本范围内与提供的文本附件进行指定类型的用户交互。如果用户轻击或长按文本附件且其image属性不是nil,则文本视图将调用此方法,除了将文本附件内联显示外,还可以使用此方法触发操作。
参数 :
textView : 包含文本附件的UITextView。
textAttachment : 文本附件。
characterRange : 包含文本附件的字符范围。
interaction : 正在发生的交互类型(有关可能的值,请参阅UITextItemInteraction)。
返回值 :
如果允许与文本附件交互,则为“YES”;如果不允许交互,则为“NO”。
UITextView相关通知
UIKIT_EXTERN NSNotificationName const UITextViewTextDidBeginEditingNotification;
通知描述 :通知观察者一个编辑会话在一个UITextView中开始,受影响的UITextView存储在通知对象(NSNotification)的对象(object)参数中,而非使用userInfo字典。
UIKIT_EXTERN NSNotificationName const UITextViewTextDidChangeNotification;
通知描述 :通知观察者UITextView中的文本已更改。受影响的UITextView存储在通知对象(NSNotification)的对象(object)参数中,而非使用userInfo字典。
UIKIT_EXTERN NSNotificationName const UITextViewTextDidEndEditingNotification;
通知描述 :通知观察者UITextView的编辑会话已结束。受影响的UITextView存储在通知对象(NSNotification)的对象(object)参数中,而非使用userInfo字典。
// UIPlaceHolderTextView.h
#import <UIKit/UIKit.h>
@interface UIPlaceHolderTextView : UITextView<UITextViewDelegate>
//提示标签
@property(nonatomic, retain) UILabel *placeHolderLabel;
//提示文本
@property(nonatomic, retain) NSString *placeholder;
//提示文本颜色
@property(nonatomic, retain) UIColor *placeholderColor;
@end
// UIPlaceHolderTextView.m
#import "UIPlaceHolderTextView.h"
@implementation UIPlaceHolderTextView
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
/// 初始化
-(void)awakeFromNib{
[super awakeFromNib];
//设置提示文本
[self setPlaceholder:@""];
//设置提示文本颜色
[self setPlaceholderColor:[UIColor grayColor]];
//监听文本改变事件
[[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]];
//设置键盘return键样式
self.returnKeyType = UIReturnKeyDefault;
//设置代理
[super setDelegate:self];
//监听文本改变事件
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}
return self;
}
/// 文本改变事件
- (void)textChanged:(nullable NSNotification *)notification{
//文本改变时判断文本视图是否设置了提示文本
if([[self placeholder] length] == 0){
//没有设置提示文本不做任何操作
return;
}
//如果没有输入文本
if([[self text] length] == 0){
//显示文本视图中的提示文本
[[self viewWithTag:999] setAlpha:1];
}else{
//有输入的文本内容,隐藏文本视图中的提示文本
[[self viewWithTag:999] setAlpha:0];
}
}
/// 重写UITextView的设置文本的函数
/// @param text 文本
- (void)setText:(NSString *)text {
[super setText:text];
[self textChanged:nil];
}
/// 绘制视图
/// @param rect 视图矩形
- (void)drawRect:(CGRect)rect{
//判断是否设置了提示文本
if( [[self placeholder] length] > 0 ){
//设置了提示文本,判断是否初始化提示文本标签
if (self.placeHolderLabel == nil ){
self.placeHolderLabel = [[UILabel alloc] initWithFrame:CGRectMake(8,5,self.bounds.size.width - 16,0)];
self.placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping ;
self.placeHolderLabel.numberOfLines = 0;
self.placeHolderLabel.font = self.font;
self.placeHolderLabel.backgroundColor = [UIColor clearColor];
self.placeHolderLabel.textColor = self.placeholderColor;
self.placeHolderLabel.alpha = 0;
self.placeHolderLabel.tag = 999;
[self addSubview:self.placeHolderLabel];
}
self.placeHolderLabel.text = self.placeholder;
[self.placeHolderLabel sizeToFit];
[self sendSubviewToBack:self.placeHolderLabel];
}
//如果文本视图没有填入文本,并且设置了提示文本,显示提示文本
if( [[self text] length] == 0 && [[self placeholder] length] > 0 ){
[[self viewWithTag:999] setAlpha:1];
}
[super drawRect:rect];
}
#pragma mark - UITextViewDelegate
///隐藏键盘,实现UITextViewDelegate
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text{
//判断是否点击了键盘return键,点击会输入\n
if ([text isEqualToString:@"\n"]) {
//文本视图放弃第一响应者,收起键盘
[textView resignFirstResponder];
return NO;
}
return YES;
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
UIPlaceHolderTextView *placeHolderTextView = [[UIPlaceHolderTextView alloc]initWithFrame:CGRectZero];
placeHolderTextView.backgroundColor = [UIColor greenColor];
placeHolderTextView.placeholder = @"粘贴文本,可自动识别姓名、电话和地址。\r如:李明 139****8888 北京市朝阳区xx街道xx大厦xx楼xx室。";
placeHolderTextView.placeholderColor = [UIColor redColor];
placeHolderTextView.font = [UIFont systemFontOfSize:12];
[self.view addSubview:placeHolderTextView];
[placeHolderTextView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.size.mas_equalTo(CGSizeMake(200, 70));
}];
}
效果如下:
关于键盘的监听
UIKIT_EXTERN NSNotificationName const UIKeyboardWillShowNotification API_UNAVAILABLE(tvOS);
通知描述 :键盘将要显示的通知,通知对象(NSNotification)的对象(object)参数为nil,userInfo字典包含关于键盘的信息,可以使用描述键盘相关信息的key在userInfo字典中获取键盘的位置和大小。
UIKIT_EXTERN NSNotificationName const UIKeyboardDidShowNotification API_UNAVAILABLE(tvOS);
通知描述 :键盘已经显示的通知,通知对象(NSNotification)的对象(object)参数为nil,userInfo字典包含关于键盘的信息,可以使用描述键盘相关信息的key在userInfo字典中获取键盘的位置和大小。
UIKIT_EXTERN NSNotificationName const UIKeyboardWillHideNotification API_UNAVAILABLE(tvOS);
通知描述 :键盘将要隐藏的通知,通知对象(NSNotification)的对象(object)参数为nil,userInfo字典包含关于键盘的信息,可以使用描述键盘相关信息的key在userInfo字典中获取键盘的位置和大小。
UIKIT_EXTERN NSNotificationName const UIKeyboardDidHideNotification API_UNAVAILABLE(tvOS);
通知描述 :键盘隐藏后的通知,通知对象(NSNotification)的对象(object)参数为nil,userInfo字典包含关于键盘的信息。可以使用描述键盘相关信息的key在userInfo字典中获取键盘的位置和大小。
@interface TestCodeController ()<UITextViewDelegate>
@property (nonatomic, strong) UITextView *textView;
@end
@implementation TestCodeController
- (void)viewDidLoad {
[super viewDidLoad];
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectZero];
textView.backgroundColor = [UIColor grayColor];
textView.font = [UIFont systemFontOfSize:15];
textView.textColor = [UIColor whiteColor];
textView.delegate = self;
self.textView = textView;
[self.view addSubview:self.textView];
[textView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.size.mas_equalTo(CGSizeMake(150, 100));
}];
//监听键盘将要出现
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
//监听键盘已经出现
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
//监听键盘将要隐藏
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
//监听键盘已经隐藏
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification{
NSLog(@"键盘将要出现");
}
- (void)keyboardDidShow:(NSNotification *)notification{
NSLog(@"键盘已经出现");
}
- (void)keyboardWillHide:(NSNotification *)notification{
NSLog(@"键盘将要隐藏");
}
- (void)keyboardDidHide:(NSNotification *)notification{
NSLog(@"键盘已经隐藏");
}
///隐藏键盘,实现UITextViewDelegate
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text{
if ([text isEqualToString:@"\n"]) {
[textView resignFirstResponder];
NSLog(@"放弃第一响应对象,隐藏键盘");
return NO;
}
return YES;
}
- (void)keyboardWillShow:(NSNotification *)notification{
NSLog(@"键盘将要出现");
//获取高度
NSDictionary *userInfo = [notification userInfo];
NSValue *value = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [value CGRectValue];
int height = keyboardRect.size.height;
NSLog(@"%d",height);
}