聊天页面预置的消息输入控件——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
的接口自行实现