Skip to content

Commit

Permalink
1、略微修改UI,提高textView高度 。2、重命名inputView。3、修复表情重复imageName问题。4、发送逻辑代码略微修…
Browse files Browse the repository at this point in the history
…改,更符合实际IM
  • Loading branch information
QDong415 committed Jun 28, 2022
1 parent 44b6631 commit ea970bd
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 121 deletions.
4 changes: 2 additions & 2 deletions Example/QKeyboardEmotionView.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = com.dq.qkeyboard;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "dq-deve-profile20220323";
PROVISIONING_PROFILE_SPECIFIER = "dq-develop-profile20220328";
SWIFT_OBJC_BRIDGING_HEADER = "QKeyboardEmotionView/QKeyboardEmotionView-Bridging-Header.h";
SWIFT_VERSION = 5.0;
WRAPPER_EXTENSION = app;
Expand All @@ -686,7 +686,7 @@
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = com.dq.qkeyboard;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "dq-deve-profile20220323";
PROVISIONING_PROFILE_SPECIFIER = "dq-develop-profile20220328";
SWIFT_OBJC_BRIDGING_HEADER = "QKeyboardEmotionView/QKeyboardEmotionView-Bridging-Header.h";
SWIFT_VERSION = 5.0;
WRAPPER_EXTENSION = app;
Expand Down
65 changes: 42 additions & 23 deletions Example/QKeyboardEmotionView/Chat/ChatViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,60 @@ - (void)keyboardManager:(QKeyboardManager *)keyboardManager onWholeInputViewHeig
*/
- (void)sendTextMessage:(NSString *)inputText {

[_messageArray addObject:inputText];
//第1步:本地创建MessageModel,每个app的MessageModel格式都不一样,我这里demo就不演示了,用string代替

//第2步:添加到array中 + reload和滚到底部
[self insertAndScrollToBottom:inputText needClearInputText:YES];

//第3步,发送给服务器,我这里demo就不演示了
// [self updateToRemote: inputText];
}

#pragma mark - Private

//添加到array中 + reload和滚到底部。 needClearInputText: 是否需要清空文本框输入的内容
- (void)insertAndScrollToBottom:(NSString *)contentModel needClearInputText:(BOOL)needClearInputText {

//添加到array中
[self.messageArray addObject:contentModel];

//请不要用inputTextView.text = nil来清空文本,具体原因看方法注释
//@return 0:当前inputText只有一行;非0:动画时长
NSTimeInterval animationDuration = [self.inputView clearInputTextBySend];
NSTimeInterval animationDuration = needClearInputText ? [self.inputBarView clearInputTextBySend] : 0;

//reloadData并滚到底部
[self reloadDataAndScrollToBottomAnimated:YES animationDelay:animationDuration];
}

if (animationDuration == 0){
//reloadData并滚到底部
- (void)reloadDataAndScrollToBottomAnimated:(BOOL)animated animationDelay:(NSTimeInterval)animationDelay {

BOOL resultAnimated = animated;
if (@available(iOS 13.0, *)) {
// ios 13、15都是ok的
} else {
//在ios12中,滚到底部再animal总是会出现最后一个Cell滚动异常,所以我干脆禁止了ios12的动画
resultAnimated = NO;
}

if (animationDelay == 0){
//如果textView的文本只有一行,那么清空输入框的时候,不会走onWholeInputViewHeightDidChange回调,也不会重新设置tableView的contentInset。所以就无需延时reloadData
[self reloadDataAndScrollToBottomAnimated:YES];

[self.tableView reloadData];

[self scrollToBottomAnimated:resultAnimated];
} else {

//textView的文本大于一行,那么清空输入框的时候,会重设tableView的contentInset(并且我还是在0.2秒的动画里重设的),如果这时候reloadData,在低性能设备上会出现tableView来回上下移动的问题
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(animationDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(animationDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

[self reloadDataAndScrollToBottomAnimated:YES];
[self.tableView reloadData];

[self scrollToBottomAnimated:resultAnimated];
});
}

}

#pragma mark - Private
//滚到底部
- (void)scrollToBottomAnimated:(BOOL)animated {
NSInteger rows = [self.tableView numberOfRowsInSection:0];
Expand All @@ -157,21 +191,6 @@ - (void)scrollToBottomAnimated:(BOOL)animated {
}
}

//reloadData并滚到底部
- (void)reloadDataAndScrollToBottomAnimated:(BOOL)animated {

[self.tableView reloadData];

BOOL resultAnimated = animated;
if (@available(iOS 13.0, *)) {
} else {
//在ios12中,滚到底部再animal总是会出现最后一个Cell滚动异常,所以我干脆禁止了ios12的动画
resultAnimated = NO;
}
// ios 13、15都是ok的
[self scrollToBottomAnimated:resultAnimated];
}

- (BOOL)alreadyAtBottom {
if (((NSInteger)self.tableView.contentOffset.y) == ((NSInteger)self.tableView.contentSize.height + self.scrollviewContentInset.bottom - CGRectGetHeight(self.tableView.bounds))) {
return YES;
Expand Down
2 changes: 1 addition & 1 deletion Example/QKeyboardEmotionView/Chat/ChatXibViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *
NSString *str = [NSString stringWithFormat:@"%f😄[微笑][呲牙]翁绕所😄多付所多啊打发斯蒂芬[再见][微笑2]的打法撒😄旦法[微笑毒贩夫妇][大小][捂👨🏻❤️脸][微笑]阿斯顿发斯👨🏻❤️n蒂芬[微笑]http://连哭都是打开分类[微笑]哭都\n是打开分类到😄到哭都是打开分类哭都是<dd>✔️😄打开分类[旺柴][社会社会][6👨🏻❤️66][]是打发斯FFF的蒂芬[阿萨大师👨🏻❤️傅恩我\n若翁绕%f😄[微笑][呲牙]翁绕所😄多付所多啊打发斯蒂芬[再见][微笑2]的打法撒😄旦法[微笑毒贩夫妇][大小][捂👨🏻❤️脸][微笑]阿斯顿发斯👨🏻❤️n蒂芬[微笑]http://连哭都是打开分类[微笑]哭都\n是打开分类到😄到哭都是打开分类哭都是<dd>✔️😄打开分类[旺柴][社会社会][6👨🏻❤️66][]是打发斯FFF的蒂芬[阿萨大师👨🏻❤️傅恩我\n若翁绕[Emm][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑👨🏻❤️][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][Emm][Emm][憨笑]所👨🏻❤️多\n付所多啊😄打发斯蒂芬对的[立刻就阿杀了的减肥;垃圾收代理费即时看到发文日唉短FFF发水立方;as;的李开复;了as人][jjiidi]asdfjksajdlfk 大是大非 答[微笑]复阿斯蒂芬 FFF 阿士大夫的是👨🏻❤️n垃圾收代理费。👨🏻❤️的减肥;垃圾收代理费即[偷看]时看到发文日唉短发,的减肥;垃圾收代理费即时看到发文日唉短发。的减肥;垃圾收代理费即时看到发文日唉短发[吃鸭][汪星人]🐶[沙发斯蒂芬][大笑][]]]][[[[[]as!@#!@¥#%¥#……¥%&%……&[偷笑]【】[👋🏻][你好][再见][Emm][Emm][Emm][Emm][Emm][Emm][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][Emm][Emm][憨笑][大笑][大笑]隊_(:з」∠)_👩🏻👨🏻[Emm][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑👨🏻❤️][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][Emm][Emm][憨笑]所👨🏻❤️多\n付所多啊😄打发斯蒂芬对的[立刻就阿杀了的减肥;垃圾收代理费即时看到发文日唉短FFF发水立方;as;的李开复;了as人][jjiidi]asdfjksajdlfk 大是大非 答[微笑]复阿斯蒂芬 FFF 阿士大夫的是👨🏻❤️n垃圾收代理费。👨🏻❤️的减肥;垃圾收代理费即[偷看]时看到发文日唉短发,的减肥;垃圾收代理费即时看到发文日唉短发。的减肥;垃圾收代理费即时看到发文日唉短发[吃鸭][汪星人]🐶[沙发斯蒂芬][大笑][]]]][[[[[]][Emm][Emm][Emm][Emm][Emm][Emm][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][Emm][Emm][憨笑][大笑][大笑]隊_(:з」∠)_👩🏻👨🏻[Emm][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑👨🏻❤️][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][Emm][Emm][憨笑]所👨🏻❤️多\n付所多啊😄打发斯蒂芬对的[立刻就阿杀了的减肥;垃圾收代理费即时看到发文日唉短FFF发水立方;as;的李开复;了as人][jjiidi]asdfjksajdlfk 大是大非 答[微笑]复阿斯蒂芬 FFF 阿士大夫的是👨🏻❤️n垃圾收代理费。👨🏻❤️的减肥;垃圾收代理费即[偷看]时看到发文日唉短发,的减肥;垃圾收代理费即时看到发文日唉短发。的减肥;垃圾收代理费即时看到发文日唉短发[吃鸭][汪星人]🐶[沙发斯蒂芬][大笑][]]]][[[[[]as!@#!@¥#%¥#……¥%&%……&[偷笑]【】[👋🏻][你好][再见][Emm][Emm][Emm][Emm][Emm][Emm][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][Emm][Emm][憨笑][大笑][大笑]隊_(:з」∠)_👩🏻👨🏻❤️[Emm][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑👨🏻❤️][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][Emm][Emm][憨笑]所👨🏻❤️多\n付所多啊😄打发斯蒂芬对的[立刻就阿杀了的减肥;垃圾收代理费即时看到发文日唉短FFF发水立方;as;的李开复;了as人][jjiidi]asdfjksajdlfk 大是大非 答[微笑]复阿斯蒂芬 FFF 阿士大夫的是👨🏻❤️n垃圾收代理费。👨🏻❤️的减肥;垃圾收代理费即[偷看]时看到发文日唉短发,的减肥;垃圾收代理费即时看到发文日唉短发。的减肥;垃圾收代理费即时看到发文日唉短发[吃鸭][汪星人]🐶[沙发斯蒂芬][大笑][]]]][[[[[]as!@#!@¥#%¥#……¥%&%……&[偷笑]【】[👋🏻][你好][再见][Emm][Emm][Emm][Emm][Emm][Emm][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][憨笑][Emm][Emm][憨笑][大笑][大笑]隊_(:з」∠)_👩🏻👨🏻❤️❤️[偷看][偷看]", [[NSDate date] timeIntervalSince1970],[[NSDate date] timeIntervalSince1970]];

NSLog(@"1");
//1次遍历,只是setAttributedString 不转表情: 内存占24.2,0.0005s; 转表情0.006;转译表情 = 0.
//1次遍历,只是setAttributedString 不转表情: 内存占24.2,0.0005s; 转表情0.006;
for (int i = 0; i < 1; i++){
str = [NSString stringWithFormat:@"%@%d",str,i];
label.attributedText = [[QEmotionHelper sharedEmotionHelper] attributedStringByText:str font:label.font];
Expand Down
24 changes: 12 additions & 12 deletions Example/QKeyboardEmotionView/Common/CommonCustomViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ @interface CommonCustomViewController ()<InputBoardDataSource ,InputBoardDelegat

@property(nonatomic,strong)QKeyboardManager *keyboardManager;

@property(nonatomic,strong)QInputBarView *inputView;
@property(nonatomic,strong)QInputBarView *inputBarView;

@end

Expand All @@ -36,21 +36,21 @@ - (void)viewDidLoad {

// 初始化输入工具条,frame可以先这样临时设置,下面的addBottomInputBarView方法会重置输入条frame
// 如果你想要自定义输入条View,请参考TextFieldViewController代码
_inputView = [[QInputBarView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,UIInputBarViewMinHeight)];
[_inputView setupWithConfiguration:[self inputBarViewConfiguration]];
_inputView.dataSource = self;
_inputView.delegate = self;
_inputBarView = [[QInputBarView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,UIInputBarViewMinHeight)];
[_inputBarView setupWithConfiguration:[self inputBarViewConfiguration]];
_inputBarView.dataSource = self;
_inputBarView.delegate = self;

//keyboard管理类,用来管理键盘,各大面板的切换
_keyboardManager = [[QKeyboardManager alloc] initWithViewController:self];
_keyboardManager.dataSource = self;
//因为addBottomInputBarView方法会立刻触发delegate,所以这里需要先设置delegate
_keyboardManager.delegate = self;
//将输入条View添加到ViewController;YES表示输入条平时不显示(比如朋友圈);NO表示平时也显示(比如聊天)
[_keyboardManager addBottomInputBarView:_inputView belowViewController:NO];
[_keyboardManager addBottomInputBarView:_inputBarView belowViewController:NO];

//把输入框(如果有的话)绑定给管理类
[_keyboardManager bindTextView:_inputView.inputTextView];
[_keyboardManager bindTextView:_inputBarView.inputTextView];
}

#pragma mark - NeedOverride
Expand Down Expand Up @@ -108,20 +108,20 @@ - (void)keyboardManager:(QKeyboardManager *)keyboardManager onWholeInputViewHeig
* @param emotion 被选中的表情对应的`QMUIEmotion`对象
*/
- (void)emotionView:(QEmotionBoardView *)emotionView didSelectEmotion:(QEmotion *)emotion atIndex:(NSInteger)index {
[_inputView insertEmotion:emotion.displayName];
[_inputBarView insertEmotion:emotion.displayName];
}

// 删除按钮的点击事件回调
- (void)emotionViewDidSelectDeleteButton:(QEmotionBoardView *)emotionView {
if (![_inputView deleteEmotion]){
if (![_inputBarView deleteEmotion]){
//根据当前的光标,这次点击删除按钮并没有删除表情,那么就删除文字
[_inputView.inputTextView deleteBackward];
[_inputBarView.inputTextView deleteBackward];
}
}

// 发送按钮的点击事件回调
- (void)emotionViewDidSelectSendButton:(QEmotionBoardView *)emotionView {
[self sendTextMessage:[_inputView textViewInputNormalText]];
[self sendTextMessage:[_inputBarView textViewInputNormalText]];
}

#pragma mark - QExtendBoardViewDelegate
Expand Down Expand Up @@ -168,7 +168,7 @@ - (void)inputBarView:(QInputBarView *)inputBarView onEmotionButtonClick:(UIButto
if (emotionSwitchButton.isSelected) {
[_keyboardManager switchToEmotionBoardKeyboard];
} else {
[_inputView textViewBecomeFirstResponder];
[_inputBarView textViewBecomeFirstResponder];
}
}

Expand Down
2 changes: 1 addition & 1 deletion Example/QKeyboardEmotionView/Common/CommonViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//我是为了封装demo才把这两个变量设置为public,实际开发中, 无需对外开放
@property(nonatomic,strong)QKeyboardManager *keyboardManager;

@property(nonatomic,strong)QInputBarView *inputView;
@property(nonatomic,strong)QInputBarView *inputBarView;

@end

20 changes: 10 additions & 10 deletions Example/QKeyboardEmotionView/Common/CommonViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,20 @@ - (void)viewDidLoad {

// 初始化输入工具条,frame可以先这样临时设置,下面的addBottomInputBarView方法会重置输入条frame
// 如果你想要自定义输入条View,请参考TextFieldViewController代码
_inputView = [[QInputBarView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,UIInputBarViewMinHeight)];
[_inputView setupWithConfiguration:[self inputBarViewConfiguration]];
_inputView.delegate = self;
_inputBarView = [[QInputBarView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,UIInputBarViewMinHeight)];
[_inputBarView setupWithConfiguration:[self inputBarViewConfiguration]];
_inputBarView.delegate = self;

//keyboard管理类,用来管理键盘,各大面板的切换
_keyboardManager = [[QKeyboardManager alloc] initWithViewController:self];
_keyboardManager.dataSource = self;
//因为addBottomInputBarView方法会立刻触发delegate,所以这里需要先设置delegate
_keyboardManager.delegate = self;
//将输入条View添加到ViewController;YES表示输入条平时不显示(比如朋友圈);NO表示平时也显示(比如聊天)
[_keyboardManager addBottomInputBarView:_inputView belowViewController:[self belowViewController]];
[_keyboardManager addBottomInputBarView:_inputBarView belowViewController:[self belowViewController]];

//把输入框(如果有的话)绑定给管理类
[_keyboardManager bindTextView:_inputView.inputTextView];
[_keyboardManager bindTextView:_inputBarView.inputTextView];
}

#pragma mark - IBAction
Expand Down Expand Up @@ -139,20 +139,20 @@ - (void)emotionView:(QEmotionBoardView *)emotionView didSelectEmotion:(QEmotion

QEmotionHelper *faceManager = [QEmotionHelper sharedEmotionHelper];
//把😊插入到输入栏
[_inputView insertEmotionAttributedString:[faceManager obtainAttributedStringByImageKey:emotion.displayName font:_inputView.inputTextView.font useCache:NO]];
[_inputBarView insertEmotionAttributedString:[faceManager obtainAttributedStringByImageKey:emotion.displayName font:_inputBarView.inputTextView.font useCache:NO]];
}

// 删除按钮的点击事件回调
- (void)emotionViewDidSelectDeleteButton:(QEmotionBoardView *)emotionView {
if (![_inputView deleteEmotion]){
if (![_inputBarView deleteEmotion]){
//根据当前的光标,这次点击删除按钮并没有删除表情,那么就删除文字
[_inputView.inputTextView deleteBackward];
[_inputBarView.inputTextView deleteBackward];
}
}

// 发送按钮的点击事件回调
- (void)emotionViewDidSelectSendButton:(QEmotionBoardView *)emotionView {
[self sendTextMessage:[_inputView textViewInputNormalText]];
[self sendTextMessage:[_inputBarView textViewInputNormalText]];
}

#pragma mark - QExtendBoardViewDelegate
Expand Down Expand Up @@ -191,7 +191,7 @@ - (void)inputBarView:(QInputBarView *)inputBarView onEmotionButtonClick:(UIButto
if (emotionSwitchButton.isSelected) {
[_keyboardManager switchToEmotionBoardKeyboard];
} else {
[_inputView textViewBecomeFirstResponder];
[_inputBarView textViewBecomeFirstResponder];
}
}

Expand Down
8 changes: 4 additions & 4 deletions Example/QKeyboardEmotionView/Discuss/DiscussViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ - (void)sendTextMessage:(NSString *)inputText {
[_messageArray addObject:inputText];

//清空输入框,如果是聊天界面就不要用这句
self.inputView.inputTextView.text = nil;
self.inputBarView.inputTextView.text = nil;

//隐藏键盘
[self.keyboardManager hideAllBoardView];
Expand All @@ -93,11 +93,11 @@ - (void)scrollToRowAtIndexPathByOffset:(NSIndexPath *)indexPath{
CGRect rectInTableview = [self.tableView rectForRowAtIndexPath:indexPath];

CGFloat kTopNavHeight = UIApplication.sharedApplication.statusBarFrame.size.height + 44;
if (CGRectGetMaxY(rectInTableview) < CGRectGetMinY(self.inputView.frame) - kTopNavHeight){
if (CGRectGetMaxY(rectInTableview) < CGRectGetMinY(self.inputBarView.frame) - kTopNavHeight){
return;
}

float resultY = rectInTableview.origin.y-self.tableView.contentOffset.y - kTopNavHeight + self.tableView.contentOffset.y - (CGRectGetMinY(self.inputView.frame) - rectInTableview.size.height - kTopNavHeight);
float resultY = rectInTableview.origin.y-self.tableView.contentOffset.y - kTopNavHeight + self.tableView.contentOffset.y - (CGRectGetMinY(self.inputBarView.frame) - rectInTableview.size.height - kTopNavHeight);
[self.tableView setContentOffset:CGPointMake(self.tableView.contentOffset.x, resultY) animated:YES];

//无脑把indexPath这个cell滚到导航栏下的第一个
Expand Down Expand Up @@ -141,7 +141,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.lastSelectedIndexPath = indexPath;
[self.inputView.inputTextView becomeFirstResponder];
[self.inputBarView.inputTextView becomeFirstResponder];
}

//设置cell的高度
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//我是为了封装demo才把这两个变量设置为public,实际开发中, 无需对外开放
@property(nonatomic,strong)QKeyboardManager *keyboardManager;

@property(nonatomic,strong)QInputBarView *inputView;
@property(nonatomic,strong)QInputBarView *inputBarView;

@end

Loading

0 comments on commit ea970bd

Please sign in to comment.