聊天页面预置的消息输入控件——YWMessageInputView 提供颜色、图片素材配置以及插件扩展的定制能力,当定制能力不足以满足需求时,则可以使用完全自定义的输入控件。
要实现消息输入控件分为3部分工作:
1. 创建 UIView 子类并遵守 IYWMessageInputView 协议使之作为消息输入控件,控件内部可添加如 UITextView 类型的子视图作为文本输入控件,同时将协议中规定的 text 和 selectedRange 属性关联至文本输入控件
2. 实现 IYWMessageInputView 协议中规定的 id<YWMessageInputViewDelegate> messageInputViewDelegate 属性用于引用委托对象,同时负责在适当时机回调委托对象。
3. 替换 YWConversationViewController 的消息输入控件
以下的内容中,将创建一个简单的消息输入控件 ,内部以 UITextView 子视图作为文本输入控件。
同时 Demo 的工程中附带了一个示例实现 SPMessageInputView 可作为辅助参考
只要遵守 IYWMessageInputView 协议,输入控件本身可以从 UIView 本身或其任何子类中派生而来:
@interface SPMessageInputView : UIView <IYWMessageInputView> @property (nonatomic, weak, readonly) UITextView *inputTextView; @end
IYWMessageInputView 协议协议中定义了3个必须实现的接口:
/** * 文本输入控件中的文本内容 */ @property (nonatomic, copy) NSString *text; /** * 文本输入控件中的文本选中范围 */ @property (nonatomic, assign) NSRange selectedRange; /** * 委托对象 */ @property (nonatomic, weak) id<YWMessageInputViewDelegate> messageInputViewDelegate;
其中 text 和 selectedRange 这两个属性的 getter 和 setter 都要关联文本输入控件:
- (NSString *)text {
return self.inputTextView.text;
}
- (void)setText:(NSString *)text {
self.inputTextView.text = text;
}
// selectedRange 同理省略 messageInputViewDelegate 属性是对委托对象的弱引用,首先需要实现该属性,之后需负责在适当时机调用 YWMessageInputViewDelegate 中定义的方法:
@synthesize messageInputViewDelegate = _messageInputViewDelegate;
协议中定义了两个可选接口,通知应该开始或结束监听系统的键盘事件:
- (void)beginListeningForKeyboard; - (void)endListeningForKeyboard;
消息输入控件委托协议 YWMessageInputViewDelegate 中定义了两类接口:
一类是类似 UITextViewDelegate 的文本输入控件相关的接口,当 UITextViewDelegate 的方法被调用时,则需要转发调用 YWMessageInputViewDelegate中对应的方法:
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
BOOL shouldBeginEditing = YES;
id<YWMessageInputViewDelegate> delegate = self.messageInputViewDelegate;
if( [delegate respondsToSelector:@selector(messageInputViewShouldBeginEditing:) ] ) {
shouldBeginEditing = [delegate messageInputViewShouldBeginEditing:self];
}
return shouldBeginEditing;
} 另一类为通知控件高度变化的接口:
/** * 输入栏高度发生变更 */ - (void)messageInputView:(UIView<IYWMessageInputView> *)inputView heightOfBarDidChange:(CGFloat)height; /** * 输入栏底部区域高度发生变更,如键盘高度或插件面板高度发生变更 */ - (void)messageInputView:(UIView<IYWMessageInputView> *)inputView heightOfKeyboardDidChange:(CGFloat)height;
例如键盘出现时则需要更新控件的 frame 同时通知委托对象:
- (void)keyboardWillShow:(NSNotification *)notification
{
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardEndRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 根据键盘高度更新控件本身的 frame
if ([self.messageInputViewDelegate respondsToSelector:@selector(messageInputView:heightOfKeyboardDidChange:)]) {
// 通知委托对象
[self.messageInputViewDelegate messageInputView:self heightOfKeyboardDidChange:height];
}
} 创建控件实例后赋值给 YWConversationViewController 的 UIView<IYWMessageInputView> *messageInputView 属性即可使之生效, messageInputViewDelegate 属性同时会被自动设置:
SPMessageInputView *messageInputView = [[SPMessageInputView alloc] init]; conversationViewController.messageInputView = messageInputView;
YWConversationViewController 的接口自行实现