从而知道工具条该上下移动的高度值,最近整理

2019-10-01 13:16 来源:未知

最近整理了一些在项目中常用的工具类,整理到了这个感觉在项目里面挺常用的,于是就在这里分享出来。

场景一


在iOS开发中,我们经常处理这样的情况:

当键盘出现或者消失的时候,我们需要做一些相应的操作。比如键盘上面的工具条的位置变化等。

这里我们就假设有一个工具条在键盘的上面,我们要求当键盘出现的时候,工具条的位置向上移动始终在键盘的上面,当键盘消失的时候,工具条向下移动到屏幕的下面。

这时候,我们应该怎么处理呢?

先上效果图

键盘.gif

先看一下demo 效果:

思路

为了让工具条上下移动,我们就要求出键盘上下移动的高度值,从而知道工具条该上下移动的高度值

想获取键盘的移动值,就要对键盘的显示和隐藏进行监听,我们这里可以使用通知

是不是觉得思路很清晰了,那么开始吧。

消息中心(NSNotificationCenter)

实现视图对键盘弹出的响应主要利用的是通知机制。这里我们来了解下通知机制。

不同于代理用于一对一的传递消息,通知机制用于多对多的传递消息。这个信息的传递是通过消息中心(NSNotificationCenter),每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信。任何一个对象都可以向通知中心发布通知(NSNotification),描述自己在做什么。其他感兴趣的对象(Observer)可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知。这样便能实现消息的传递。

消息中心(NSNotificationCenter)是唯一的(即单例),在创建时使用类方法 [NSNotificationCenter defaultCenter] 即可。
通知(NSNotification)
而发送的消息叫做通知(NSNotification),一个完整的通知一般包含3个属性:
(NSString *)name; // 通知的名称
(id)object; // 通知发布者(是谁要发布通知)
(NSDictionary *)userInfo; // 一些额外的信息(通知发布者传递给通知接收者的信息内容)

图片 1

处理步骤

1、给键盘设一个通知

/**

*  给键盘的frame改变添加监听

*  @param keyBoardWillChangeFrame: 监听方法

*/

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyBoardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];

2、在键盘的通知监听方法里面做需要的操作

- (void)keyboardWillChangeFrame:(NSNotification *)notification

{

// 键盘显示隐藏完毕的frame

CGRect frame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];

// 修改底部约束

self.bottomSapce.constant = XMGScreenH - frame.origin.y;

// 动画时间

CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

// 动画

[UIView animateWithDuration:duration animations:^{

[self.view layoutIfNeeded];

}];

}

上一段代码解释:

notification.userInfo:

 notification是指传递过来的通知

 userInfo是一个字典,存储任何和通知相关联的可能用到的信息。当一个通知的值发生改变的时候,就会将值存储到userInfo的字典中。例如这里的userInfo包含通知执行的时间,和通知结束时候键盘的frame等信息。

也可以改变工具条的transform实现:

self.toolbar.transform = CGAffineTransformMakeTranslation(0, -keyboardF.size.height);

初始化一个通知(NSNotification)对象有这些方法

+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject;

+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)UserInfo;

- (instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;

接下来看是怎么实现的吧!!!

自定义键盘,只需要设置下面的属性即可

@property (readwrite, retain) UIView *inputView;

最后,一定要记得在dealoc方法里释放监听

- (void)dealloc

{

[[NSNotificationCenter defaultCenter] removeObserver:self];

}

发布通知

通知中心提供了相应的方法来帮助发布通知

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

//发布一个notification通知,可在notification对象中设置通知的名称、通知发布者、额外信息等

- (void)postNotificationName:(NSString *)aName object:(id)anObject;
//发布一个名称为aName的通知,anObject为这个通知的发布者

- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
//发布一个名称为aName的通知,anObject为这个通知的发布者,aUserInfo为额外信息

我在demo实现了一个viewcontroller的扩展 在这个扩展里面实现了几个方法。

场景二

有时候在同一个界面里面,可能有多个TextField输入框,而点击不同额输入框,我们可能希望弹出的键盘拥有不同的工具条,这时候我们怎么办呢?

监听通知

通知中心(NSNotificationCenter)提供了方法来注册一个监听通知的监听器(Observer)

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;

其中:

observer:监听器,即谁要接收这个通知
aSelector:收到通知后,回调监听器的这个方法,并且把通知对象当做参数传入
aName:通知的名称。如果为nil,那么无论通知的名称是什么,监听器都能收到这个通知
anObject:通知发布者。如果为anObject和aName都为nil,监听器都收到所有的通知
值得注意的是,aSelector 指示的方法传入的参数即是通知对象本身,我们可以通过通知对象的 userInfo; // 一些额外的信息(通知发布者传递给通知接收者的信息内容)

图片 2

思路

首先我们要有那么几种工具条,可以使用xib方式(简单,不讲解了了,不知道可以发邮件给我)

然后设置不同输入框的配件视图(textField.inputAccessoryView = xxxTool)

设置输入框成为第一响应者,这样弹出的时候就能有不同的toolBar了。

代码实现

//这里不贴图了,比较简单

UIView *tool1 = [[[NSBundle mainBundle] loadNibNamed:@"ToolBar1" owner:nil options:nil] lastObject];

UIView *tool2 = [[[NSBundle mainBundle] loadNibNamed:@"ToolBar2" owner:nil options:nil] lastObject];

self.textField1.inputAccessoryView = tool1;

self.textField2.inputAccessoryView = tool2;

初始化一个通知(NSNotification)对象有这些方法

+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject;

+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)UserInfo;

- (instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;

-registerViewForKeyboardNotifications;

场景三

上面适用的情况是在屏幕底部只有一个输入框的时候。有朋友问到当一个界面有很多个输入框,上面的输入框点击不需要向上移动,只有下面的点击才需要界面上移的时候怎么办?

取消注册通知监听器

由于通知中心不会保留(retain)监听器对象,在通知中心注册过的对象,必须在该对象释放前取消注册。否则,当相应的通知再次出现时,通知中心仍然会向该监听器发送消息。因为相应的监听器对象已经被释放了,所以可能会导致应用崩溃!!

-resignViewForKeyboardNotifications;

解决方法

我这里就给出一个解决方案,可能不是最优,希望看到的朋友有更好的方法能够分享给我。- 首先让你的xxxController继承代理

@interface xxxController()@end

 让你希望能够上移的输入框XXXTextField的代理称为控制器本身

self.XXXTextField.delegate = self;

 让控制器监听键盘消失的通知,为的是让键盘消失的时候也能在需要时调整界面的位置

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyBoardWillHideFrame:) name:UIKeyboardWillHideNotification object:nil];

实现UITextField的代理方法和键盘的监听方法

- (void)textFieldDidBeginEditing:(UITextField *)textField{

CGRect frame = self.view.frame;

//这里的50是随便设置的

frame.origin.y -=50;

frame.size.height +=50;

self.view.frame = frame;

}

-(BOOL)textFieldShouldReturn:(UITextField *)textField{

CGRect frame = self.view.frame;

frame.origin.y +=50;

frame.size.height -=50;

self.view.frame = frame;

[textField resignFirstResponder];

return YES;

}

-(void)keyBoardWillHideFrame:(NSNotification *)notification{

if (self.view.frame.origin.y == -50) {

CGRect frame = self.view.frame;

frame.origin.y +=50;

frame.size.height -=50;

self.view.frame = frame;

}}

通知中心提供了相应的方法来取消注册监听器
- (void)removeObserver:(id)observer;

- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;

一般我们用第一种方法就可以了,可以(也需要)移除所有监听器对象注册的监听。

一般在监听器销毁之前取消注册(如在监听器中加入下列代码):

- (void)dealloc {
    //[super dealloc];  非ARC中需要调用此句
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

注意我们现在一般都是使用的 ARC 模式,所以不需要调用 [super dealloc] 以及 release 了。 delloc 方法在 ARC 依然保留的原因就是为了方便我们做取消监听注册等情况。

这两个方法分别注册注销系统键盘弹出和消失的通知

常用知识点:

成为第一响应者(可以调出键盘)

- (BOOL)becomeFirstResponder;

取消第一响应者

- (BOOL)resignFirstResponder;

全部取消第一响应者

- (BOOL)endEditing:(BOOL)force;    //使用这个使得view或者其所有的子视图都取消第一响应者 (optionally force)

常见的通知名称

UIDevice 通知

UIDevice类提供了一个单例对象,它代表着设备,通过它可以获得一些设备相关的信息,比如电池电量值(batteryLevel)、电池状态(batteryState)、设备的类型(model,比如iPod、iPhone等)、设备的系统(systemVersion)
,通过[UIDevice currentDevice]可以获取这个单例对象。

UIDevice对象会不间断地发布一些通知,下列是UIDevice对象所发布通知的名称常量:

UIDeviceOrientationDidChangeNotification // 设备旋转
UIDeviceBatteryStateDidChangeNotification // 电池状态改变
UIDeviceBatteryLevelDidChangeNotification // 电池电量改变
UIDeviceProximityStateDidChangeNotification // 近距离传感器(比如设备贴近了使用者的脸部)

键盘通知

键盘状态改变的时候,系统会发出一些特定的通知

UIKeyboardWillShowNotification // 键盘即将显示
UIKeyboardDidShowNotification // 键盘显示完毕
UIKeyboardWillHideNotification // 键盘即将隐藏
UIKeyboardDidHideNotification // 键盘隐藏完毕
UIKeyboardWillChangeFrameNotification // 键盘的位置尺寸即将发生改变
UIKeyboardDidChangeFrameNotification // 键盘的位置尺寸改变完毕
TAG标签:
版权声明:本文由www.129028.com-澳门金沙唯一官网www129028com发布于编程新闻,转载请注明出处:从而知道工具条该上下移动的高度值,最近整理