处理文本输入框的输入事件,单击文本输入框后要弹出键盘。
弹出键盘有两种实现方式:一种代理,一种通知。也就是对应的(观察者模式和代理模式)。
实现过程:先注册消息 postNotificationName ,然后在响应的方法的接收消息 addObserver, 最后实现接收消息的方法
因为在系统中又定义好的键盘处理通知, 所以直接进行监听就行了。
UIKIT_EXTERN NSString * const UIKeyboardWillShowNotification; // 即将弹出
UIKIT_EXTERN NSString * const UIKeyboardDidShowNotification; // 显示
UIKIT_EXTERN NSString * const UIKeyboardWillHideNotification; //即将隐藏
UIKIT_EXTERN NSString * const UIKeyboardDidHideNotification; // 隐藏
// 1、 通过通知监听键盘出现消息
// 添加监听器,监听键盘弹出
[[ NSNotificationCenter defaultCenter ] addObserver : self selector : @selector (keyboardComeout:) name : UIKeyboardWillShowNotification object : nil ];
// 添加监听器 , 监听键盘退出
[[ NSNotificationCenter defaultCenter ] addObserver : self selector : @selector (keyboardGoaway:) name : UIKeyboardWillHideNotification object : nil ];
// 2、 响应通知的方法,显示键盘
- ( void )keyboardComeout:( NSNotification *)note
{
NSLog ( @"keyboardComeout--/n%@" ,note);
// 取出消息中键盘出现后的最终位置 , 要将字典对象转换成 CGRect
CGRect rect = [note. userInfo [ UIKeyboardFrameEndUserInfoKey ] CGRectValue ];
self . viewBotom . constant = rect. size . height ;
// 取出键盘弹出所需要的时间
double animateTime = [note. userInfo [ UIKeyboardAnimationDurationUserInfoKey ] doubleValue ];
[ UIView animateWithDuration :animateTime animations :^{
[ self . view layoutIfNeeded ];
}];
/**
* NSNotification 内部信息
NSConcreteNotification 0x7f896bebf4d0 {name = UIKeyboardWillShowNotification; userInfo = {
UIKeyboardAnimationCurveUserInfoKey = 7;
UIKeyboardAnimationDurationUserInfoKey = "0.25";
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 225}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 779.5}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 554.5}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 225}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 442}, {375, 225}}";
}}
*/
}
/**
* 3、 开始滚动界面后隐藏键盘
*/
- ( void )scrollViewWillBeginDragging:( UIScrollView *)scrollView
{
// 退出键盘
// NSLog ( @"scrollViewWillBeginDragging--" );
//[self.view endEditing:YES];//方法1
[ self . textField resignFirstResponder ]; // 方法2: 谁响应的键盘,谁就可以调用这个方法退出键盘 (resignFirstResponder)
}
// 隐藏键盘
- ( void )keyboardGoaway:( NSNotification *)note
{
NSLog ( @"keyboardGoaway--/n%@" ,note);
self . viewBotom . constant = 0 ;
// 取出键盘弹出所需要的时间
double animateTime = [note. userInfo [ UIKeyboardAnimationDurationUserInfoKey ] doubleValue ];
[ UIView animateWithDuration :animateTime animations :^{
[ self . view layoutIfNeeded ];
}];
}
看 弹出 效果,实际效果是有动画的,过渡更好。
这里使用更新控件的约束来实现view的移动 。
如下属性:
@property ( weak , nonatomic ) IBOutlet NSLayoutConstraint *viewBotom;
然后控制约束的constant值,就可以实现view的移动。
设置方法方法:
// 取出消息中键盘出现后的最终位置 , 要将字典对象转换成 CGRect
CGRect rect = [note. userInfo [ UIKeyboardFrameEndUserInfoKey ] CGRectValue ];
self . viewBotom . constant = rect. size . height ;
直接使用其自带的功能即可
// 设置文本框左边的内容
UIView *leftView = [[ UIView alloc ] init ];
leftView. frame = CGRectMake ( 0 , 0 , 10 , 0 );
self . messageField . leftView = leftView;
self . messageField . leftViewMode = UITextFieldViewModeAlways ;
// 右边间距
self . messageField . rightView = leftView;
self . messageField . rightViewMode = UITextFieldViewModeAlways ;
- ( void )dealloc
{
// 使用完毕后要手动移除监听对象
[[ NSNotificationCenter defaultCenter ] removeObserver : self ];
}
1、在头文件中实现代理,定义协议
2、使用方法:1 设置代理,2 遵守协议,3 实现方法
3、规范:参考苹果官方的协议实现方式
4、作用:
1、监听事件:A是监听B的一些行为,则A成为B的代理
2、消息传递:A想告诉B一些事情,则B成为A的代理
5、总结:
1、如果想监听别人的一些行为,那么就要成为别人的代理
2、如果你想告诉别人一些事情,那么就让别人成为你得代理
6、开发步骤
1、拟一份协议(格式:控件名 + Delegate),在协议里声明一些代理方法(一般代理方法都是@optional)
2、声明一个代理属性(弱引用) @property (weak,nonatomic) id delegate;
3、在内部发生某些行为时,调用代理对应的代理方法,通知代理内部发生了什么事情
4、设置代理: xxx.delegate = self;
5、 yyy对象遵守协议,实现代理方法
然后实现文件也比较简单,在点击过加载按钮后,由此对象给代理发送加载数据通知。
@class SLQLoadData ;
@protocol SLQLoadDataDelegate < NSObject >
@optional
/**
* 代理方法:点击按钮操作
*/
- ( void )LoadDataDidCilckButton:( SLQLoadData *)loadData;
@interface SLQLoadData : UIView
// 代理属性
@property ( weak , nonatomic ) id < SLQLoadDataDelegate > delegate;
+ ( instancetype )loadData; // 返回加载对象
- ( void )endingloadData; // 结束加载
@end
#import "SLQLoadData.h"
@interface SLQLoadData ()
- ( IBAction )loadMoreData:( id )sender;
@property ( weak , nonatomic ) IBOutlet UIView *loadView; // 正在加载界面
@property ( weak , nonatomic ) IBOutlet UIButton *loadBtn; // 加载按钮
@end
@implementation SLQLoadData
+ ( instancetype )loadData
{
// NSStringFromClass 将类名转换成字符串 ,xib 文件名和类名一样
return [[[ NSBundle mainBundle ] loadNibNamed : NSStringFromClass ( self ) owner : nil options : nil ] lastObject ];
}
- ( IBAction )loadMoreData:( id )sender
{
// 模拟从网络加载数据
// NSLog ( @“loadMoreData” );
self . loadView . hidden = NO ;
self . loadBtn . hidden = YES ;
// 发送消息到代理对象 , 首先判断代理方法是否存在
if ([ self . delegate respondsToSelector : @selector (LoadDataDidCilckButton:)])
{
[ self . delegate LoadDataDidCilckButton : self ];
}
}
// 隐藏正在加载界面
- ( void )endingloadData
{
self . loadView . hidden = YES ;
self . loadBtn . hidden = NO ;
}
@end
#import "SLQLoadData.h"
@interface ViewController () < SLQLoadDataDelegate > // 遵守代理协议
SLQLoadData *loadData = [ SLQLoadData loadData ];
// 指定控制器为代理对象
loadData. delegate = self ;
self . tableView . tableFooterView = loadData;
// 实现代理方法
- ( void )LoadDataDidCilckButton:( SLQLoadData *)loadData
{
NSLog ( @"LoadDataDidCilckButton" );
// 模拟从网络加载数据 , 加一个定时器
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 2.0 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
SLQFengNews *news = [[ SLQFengNews alloc ] init ];
news. title = @" 高考往事 " ;
news. topic = NO ;
news. image = @"ad_02" ;
news. comment = @"13489" ;
// 添加至模型对象
[ self . news addObject :news];
// 刷新表格
[ self . tableView reloadData ];
// 隐藏 loadView
SLQLoadData *load = ( SLQLoadData *) self . tableView . tableFooterView ;
[load endingloadData ];
});
}