表情键盘基本布局

  表情键盘基本的完成逻辑想必大多数人都有所了解,在支撑输入的原生控件(UITextView、UITextFieeld)中都会有两个属性inputView、inputAccessoryView,便是替换原生键盘中的inputView来完成自定义的键盘view,用inputAccessoryView来完成键盘顶部的最近运用等,基本都逃不出这个逻辑。

@property (nullable, readwrite, strong) UIView *inputView;      
@property (nullable, readwrite, strong) UIView *inputAccessoryView;

  如下图左面为抖音的文字键盘,右图为微信的表情键盘,抖音的文字键盘中的绿色框部分即为自定义的inputAccessoryView也便是所谓的最近运用的表情,微信的表情键盘中的赤色框部分即为自定义的inputView

iOS表情键盘总结
  如下图所示在表情键盘中,也便是自定义的inputView中通常会有这种能够支撑左右滑动切换表情包类型,上下滑动展现同一表情包中的表情的逻辑,其实便是在UIScrollView中包裹三个CollectionView来完成。
iOS表情键盘总结

// LFTEmotionInputView为自定义的inputView
- (LFTEmotionInputView *)inputView {
  if (!_inputView) {
        // [EmotionManger getEmoteModel]为获取表情键盘数据
    _inputView = [[LFTEmotionInputView alloc] initWithEmoModel:[EmotionManger getEmoteModel] frame:CGRectMake(0, 0, UI_SCREEN_WIDTH, 324)];
    @weakify(self)
    _inputView.emoteClick = (EmoteVO * model) {
      @strongify(self)
      // 这儿能够处理表情点击事情
    };
    _inputView.deleteClick = (UIButton * deleBtn) {
      @strongify(self)
      // 这儿能够处理表情键盘中的删去事情
    };
  }
  return _inputView;
}
******************************************************************************
// LFTEmotionAccessoryView为自定义的inputAccessoryView
- (LFTEmotionAccessoryView *)recentView {
  if (!_recentView) {
        //[EmotionManger getOftenModel]为获取最近运用的表情数据
    _recentView = [[LFTEmotionAccessoryView alloc] initWithFrame:CGRectMake(0, 0, UI_SCREEN_WIDTH, 44) recentModels:[EmotionManger getOftenModel]];
    @weakify(self)
    _recentView.recentEmoteClick = (EmoteVO *model) {
      @strongify(self)
      // 这儿能够处理最近运用中的表情点击事情
    };
  }
  return _recentView
}

表情键盘与文字键盘的切换

  目前看到的app中的表情键盘与文字键盘的切换分为两种,一种是微信抖音那样的点击切换按钮后,有一个表情键盘(文字键盘)向下渐隐到文字键盘(表情键盘)向上渐显的动画转场作用,这种作用也便是先让输入框resignFirstResponder,可是输入框的方位不会下落,然后再为其重新设置inputView和inputAccessoryView,最后becomeFirstResponder,就能够到达相似的这种作用,当然也有那种输入框下面便是表情键盘view的布局逻辑这种和替换键盘的inputView就有本质的区别了。

 // 点击切换按钮调用的办法(省掉大部分的数据赋值逻辑和监听键盘弹出和隐藏对输入框方位的处理逻辑,仅保留了简单的切换逻辑)
 - (void)keyBoardChange {
     if (self.emotionChangeBtn.tag == 0) { // 通过记tag判断tag == 0切换到表情键盘
         self.emotionChangeBtn.tag = 1;
         [self.textView resignFirstResponder];
         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.textView.inputView = self.inputView; // 自定义的表情view
            self.textView.inputAccessoryView = nil;
            [self.textView becomeFirstResponder];
        });
     } else { // 切换到文字键盘
         self.emotionChangeBtn.tag = 0;
         self.emotionChangeBtn.svg_ImageName = @"toolbar_icon_emoji.svg";
         [self.textView resignFirstResponder];
         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.textView.inputView = nil;
            self.textView.inputAccessoryView = self.recentView; // 自定义的最近运用view
            }
            [self.textView becomeFirstResponder];
            self.isEmoteBtnClick = NO;
        });
     }
 }

另一种便是相似微博的那种的切换作用,没有相关的专场动画过渡,大约逻辑如下:

- (void)keyBoardChange {
  self.isEmoteBtnClick = YES;
  if (self.emotionChangeBtn.tag == 0) { //表情键盘
    self.emotionChangeBtn.tag = 1; // emotionChangeBtn为输入框右边的切换图标按钮
    self.emotionChangeBtn.svg_ImageName = @"toolbar_icon_keyboard.svg";
    self.textView.inputView = self.inputView;
        self.textView.inputAccessoryView = nil;
    [self.textView reloadInputViews];
  } else { // 一般键盘
    self.emotionChangeBtn.tag = 0;
    self.emotionChangeBtn.svg_ImageName = @"toolbar_icon_emoji.svg";
    self.textView.inputView = nil;
    self.textView.inputAccessoryView = self.recentView;
    [self.textView reloadInputViews];
  }
  [self.textView becomeFirstResponder];
}

特殊注意点

可是微博的表情键盘有一个功能便是在点击输入框而且不失掉焦点的情况下(输入框中一向显示光标)能够切换inputView,使其从表情键盘切换到一般的文字键盘,这是怎么做到的呢?知乎上也有人提出了相同的疑问www.zhihu.com/question/51… 其实仔细研讨下咱们不难发现,咱们能够给TextView添加一个点击手势,可是textView本来就能够响应点击事情,所以要在点击署理中做一下处理,然后在点击手势中做一些文章就能够到达微博的这种作用了,主要的逻辑如下:

// 添加点击手势
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(TextViewClick)];
tapGesture.delegate = self;
[self.textView addGestureRecognizer:tapGesture];
// 支撑多手势,让textView的点击事情能够被识别,默认为no,假如这儿不处理就不会出发TextViewClick办法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
  if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
    return YES;
  }
  return NO;
}
//输入框点击切换
- (void)TextViewClick {
  if (self.emotionChangeBtn.tag == 1) {
    [self keyBoardChange];
  } else {
    [self.textView becomeFirstResponder];
  }
}