You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

737 lines
28 KiB

//
// XHMessageInputView.m
// MessageDisplayExample
//
// Created by HUAJIE-1 on 14-4-24.
// Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import "XHMessageInputView.h"
#import "NSString+MessageInputView.h"
#import "XHMacro.h"
#import "XHConfigurationHelper.h"
@interface XHMessageInputView () <UITextViewDelegate>
@property (nonatomic, weak, readwrite) XHMessageTextView *inputTextView;
@property (nonatomic, weak, readwrite) UIButton *voiceChangeButton;
@property (nonatomic, weak, readwrite) UIButton *multiMediaSendButton;
@property (nonatomic, weak, readwrite) UIButton *faceSendButton;
@property (nonatomic, weak, readwrite) UIButton *holdDownButton;
/**
* 是否取消錄音
*/
@property (nonatomic, assign, readwrite) BOOL isCancelled;
/**
* 是否正在錄音
*/
@property (nonatomic, assign, readwrite) BOOL isRecording;
/**
* 在切换语音和文本消息的时候,需要保存原本已经输入的文本,这样达到一个好的UE
*/
@property (nonatomic, copy) NSString *inputedText;
/**
* 输入框内的所有按钮,点击事件所触发的方法
*
* @param sender 被点击的按钮对象
*/
//- (void)messageStyleButtonClicked:(UIButton *)sender;
/**
* 当录音按钮被按下所触发的事件,这时候是开始录音
*/
- (void)holdDownButtonTouchDown;
/**
* 当手指在录音按钮范围之外离开屏幕所触发的事件,这时候是取消录音
*/
- (void)holdDownButtonTouchUpOutside;
/**
* 当手指在录音按钮范围之内离开屏幕所触发的事件,这时候是完成录音
*/
- (void)holdDownButtonTouchUpInside;
/**
* 当手指滑动到录音按钮的范围之外所触发的事件
*/
- (void)holdDownDragOutside;
/**
* 当手指滑动到录音按钮的范围之内所触发的时间
*/
- (void)holdDownDragInside;
#pragma mark - layout subViews UI
/**
* 根据正常显示和高亮状态创建一个按钮对象
*
* @param image 正常显示图
* @param hlImage 高亮显示图
*
* @return 返回按钮对象
*/
- (UIButton *)createButtonWithImage:(UIImage *)image HLImage:(UIImage *)hlImage ;
/**
* 根据输入框的样式类型配置输入框的样式和UI布局
*
* @param style 输入框样式类型
*/
- (void)setupMessageInputViewBarWithStyle:(XHMessageInputViewStyle)style ;
/**
* 配置默认参数
*/
- (void)setup ;
#pragma mark - Message input view
/**
* 动态改变textView的高度
*
* @param changeInHeight 动态的高度
*/
- (void)adjustTextViewHeightBy:(CGFloat)changeInHeight;
@end
@implementation XHMessageInputView
#pragma mark - Action
- (void)messageStyleButtonClicked:(UIButton *)sender {
NSInteger index = sender.tag;
switch (index) {
case 0: {
sender.selected = !sender.selected;
if (sender.selected) {
self.inputedText = self.inputTextView.text;
self.inputTextView.text = @"";
[self.inputTextView resignFirstResponder];
} else {
self.inputTextView.text = self.inputedText;
self.inputedText = nil;
[self.inputTextView becomeFirstResponder];
}
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.holdDownButton.alpha = sender.selected;
self.inputTextView.alpha = !sender.selected;
} completion:^(BOOL finished) {
}];
if ([self.delegate respondsToSelector:@selector(didChangeSendVoiceAction:)]) {
[self.delegate didChangeSendVoiceAction:sender.selected];
}
break;
}
case 1: {
sender.selected = !sender.selected;
self.voiceChangeButton.selected = !sender.selected;
if (!sender.selected) {
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.holdDownButton.alpha = sender.selected;
self.inputTextView.alpha = !sender.selected;
} completion:^(BOOL finished) {
}];
} else {
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.holdDownButton.alpha = !sender.selected;
self.inputTextView.alpha = sender.selected;
} completion:^(BOOL finished) {
}];
}
if ([self.delegate respondsToSelector:@selector(didSendFaceAction:)]) {
[self.delegate didSendFaceAction:sender.selected];
}
break;
}
case 2: {
self.faceSendButton.selected = NO;
if ([self.delegate respondsToSelector:@selector(didSelectedMultipleMediaAction)]) {
[self.delegate didSelectedMultipleMediaAction];
}
break;
}
default:
break;
}
}
- (void)holdDownButtonTouchDown {
self.isCancelled = NO;
self.isRecording = NO;
if ([self.delegate respondsToSelector:@selector(prepareRecordingVoiceActionWithCompletion:)]) {
WEAKSELF
//這邊回調 return 的 YES, 或 NO, 可以讓底層知道該次錄音是否成功, 進而處理無用的 record 對象
[self.delegate prepareRecordingVoiceActionWithCompletion:^BOOL{
STRONGSELF
//這邊要判斷回調回來的時候, 使用者是不是已經早就鬆開手了
if (strongSelf && !strongSelf.isCancelled) {
strongSelf.isRecording = YES;
[strongSelf.delegate didStartRecordingVoiceAction];
return YES;
} else {
return NO;
}
}];
}
}
- (void)holdDownButtonTouchUpOutside {
//如果已經開始錄音了, 才需要做取消的動作, 否則只要切換 isCancelled, 不讓錄音開始.
if (self.isRecording) {
if ([self.delegate respondsToSelector:@selector(didCancelRecordingVoiceAction)]) {
[self.delegate didCancelRecordingVoiceAction];
}
} else {
self.isCancelled = YES;
}
}
- (void)holdDownButtonTouchUpInside {
//如果已經開始錄音了, 才需要做結束的動作, 否則只要切換 isCancelled, 不讓錄音開始.
if (self.isRecording) {
if ([self.delegate respondsToSelector:@selector(didFinishRecoingVoiceAction)]) {
[self.delegate didFinishRecoingVoiceAction];
}
} else {
self.isCancelled = YES;
}
}
- (void)holdDownDragOutside {
//如果已經開始錄音了, 才需要做拖曳出去的動作, 否則只要切換 isCancelled, 不讓錄音開始.
if (self.isRecording) {
if ([self.delegate respondsToSelector:@selector(didDragOutsideAction)]) {
[self.delegate didDragOutsideAction];
}
} else {
self.isCancelled = YES;
}
}
- (void)holdDownDragInside {
//如果已經開始錄音了, 才需要做拖曳回來的動作, 否則只要切換 isCancelled, 不讓錄音開始.
if (self.isRecording) {
if ([self.delegate respondsToSelector:@selector(didDragInsideAction)]) {
[self.delegate didDragInsideAction];
}
} else {
self.isCancelled = YES;
}
}
#pragma mark - layout subViews UI
- (UIButton *)createButtonWithImage:(UIImage *)image HLImage:(UIImage *)hlImage {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, [XHMessageInputView textViewLineHeight], [XHMessageInputView textViewLineHeight])];
if (image)
[button setBackgroundImage:image forState:UIControlStateNormal];
if (hlImage)
[button setBackgroundImage:hlImage forState:UIControlStateHighlighted];
return button;
}
- (void)setupMessageInputViewBarWithStyle:(XHMessageInputViewStyle)style {
// 配置输入工具条的样式和布局
// 需要显示按钮的总宽度,包括间隔在内
CGFloat allButtonWidth = 0.0;
// 水平间隔
CGFloat horizontalPadding = 8;
// 垂直间隔
CGFloat verticalPadding = 5;
// 输入框
CGFloat textViewLeftMargin = ((style == XHMessageInputViewStyleFlat) ? 6.0 : 4.0);
// 每个按钮统一使用的frame变量
CGRect buttonFrame;
// 按钮对象消息
UIButton *button;
// 允许发送语音
if (self.allowsSendVoice) {
NSString *voiceNormalImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewVoiceNormalImageNameKey];
if (!voiceNormalImageName) {
voiceNormalImageName = @"voice";
}
NSString *voiceHLImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewVoiceHLImageNameKey];
if (!voiceHLImageName) {
voiceHLImageName = @"voice_HL";
}
NSString *keyboardNormalImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewKeyboardNormalImageNameKey];
if (!keyboardNormalImageName) {
keyboardNormalImageName = @"keyboard";
}
NSString *keyboardHLImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewKeyboardHLImageNameKey];
if (!keyboardHLImageName) {
keyboardHLImageName = @"keyboard_HL";
}
button = [self createButtonWithImage:[UIImage imageNamed:voiceNormalImageName] HLImage:[UIImage imageNamed:voiceHLImageName]];
[button addTarget:self action:@selector(messageStyleButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 0;
[button setBackgroundImage:[UIImage imageNamed:keyboardNormalImageName] forState:UIControlStateSelected];
buttonFrame = button.frame;
buttonFrame.origin = CGPointMake(horizontalPadding, verticalPadding);
button.frame = buttonFrame;
if (self.allowsSendText && self.allowsSendVoice) {
[self addSubview:button];
}
allButtonWidth += CGRectGetMaxX(buttonFrame) + horizontalPadding;
textViewLeftMargin += CGRectGetMaxX(buttonFrame);
self.voiceChangeButton = button;
}
// 允许发送多媒体消息,为什么不是先放表情按钮呢?因为布局的需要!
if (self.allowsSendMultiMedia) {
NSString *extensionNormalImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewExtensionNormalImageNameKey];
if (!extensionNormalImageName) {
extensionNormalImageName = @"multiMedia";
}
NSString *extensionHLImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewExtensionHLImageNameKey];
if (!extensionHLImageName) {
extensionHLImageName = @"multiMedia_HL";
}
button = [self createButtonWithImage:[UIImage imageNamed:extensionNormalImageName] HLImage:[UIImage imageNamed:extensionHLImageName]];
button.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[button addTarget:self action:@selector(messageStyleButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 2;
buttonFrame = button.frame;
buttonFrame.origin = CGPointMake(CGRectGetWidth(self.bounds) - horizontalPadding - CGRectGetWidth(buttonFrame), verticalPadding);
button.frame = buttonFrame;
[self addSubview:button];
allButtonWidth += CGRectGetWidth(buttonFrame) + horizontalPadding * 1.5;
self.multiMediaSendButton = button;
}
// 允许发送表情
if (self.allowsSendFace) {
NSString *emotionNormalImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewEmotionNormalImageNameKey];
if (!emotionNormalImageName) {
emotionNormalImageName = @"face";
}
NSString *emotionHLImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewEmotionHLImageNameKey];
if (!emotionHLImageName) {
emotionHLImageName = @"face_HL";
}
NSString *keyboardNormalImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewKeyboardNormalImageNameKey];
if (!keyboardNormalImageName) {
keyboardNormalImageName = @"keyboard";
}
NSString *keyboardHLImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewKeyboardHLImageNameKey];
if (!keyboardHLImageName) {
keyboardHLImageName = @"keyboard_HL";
}
button = [self createButtonWithImage:[UIImage imageNamed:emotionNormalImageName] HLImage:[UIImage imageNamed:emotionHLImageName]];
button.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[button setBackgroundImage:[UIImage imageNamed:keyboardNormalImageName] forState:UIControlStateSelected];
[button addTarget:self action:@selector(messageStyleButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 1;
buttonFrame = button.frame;
if (self.allowsSendMultiMedia) {
buttonFrame.origin = CGPointMake(CGRectGetMinX(self.multiMediaSendButton.frame) - CGRectGetWidth(buttonFrame) - horizontalPadding, verticalPadding);
allButtonWidth += CGRectGetWidth(buttonFrame) + horizontalPadding * 0.5;
} else {
buttonFrame.origin = CGPointMake(CGRectGetWidth(self.bounds) - horizontalPadding - CGRectGetWidth(buttonFrame), verticalPadding);
allButtonWidth += CGRectGetWidth(buttonFrame) + horizontalPadding * 1.5;
}
button.frame = buttonFrame;
[self addSubview:button];
self.faceSendButton = button;
}
// 输入框的高度和宽度 update by lsz 2020-12-10 把按钮的长度去掉
CGFloat width = CGRectGetWidth(self.bounds) - (textViewLeftMargin * 2); //- (allButtonWidth ? allButtonWidth : (textViewLeftMargin * 2));
CGFloat height = [XHMessageInputView textViewLineHeight];
if (self.allowsSendText) {
// 初始化输入框
XHMessageTextView *textView = [[XHMessageTextView alloc] initWithFrame:CGRectZero];
// 这个是仿微信的一个细节体验
textView.returnKeyType = UIReturnKeySend;
textView.enablesReturnKeyAutomatically = YES; // UITextView内部判断send按钮是否可以用
UIColor *placeHolderTextColor = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewPlaceHolderTextColorKey];
if (placeHolderTextColor) {
textView.placeHolderTextColor = placeHolderTextColor;
}
UIColor *textColor = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewTextColorKey];
if (textColor) {
textView.textColor = textColor;
}
NSString *placeHolder = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewPlaceHolderKey];
if (!placeHolder) {
placeHolder = NSLocalizedStringFromTable(@"SendAMessage", @"MessageDisplayKitString", nil);
}
textView.placeHolder = placeHolder;
textView.delegate = self;
[self addSubview:textView];
_inputTextView = textView;
}
// 配置不同iOS SDK版本的样式
switch (style) {
case XHMessageInputViewStyleFlat: {
UIColor *inputBackgroundColor = [XHConfigurationHelper appearance].messageInputViewStyle[kXHMessageInputViewBackgroundColorKey];
NSString *inputViewBackgroundImageName = nil;
if (!inputBackgroundColor) {
inputViewBackgroundImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewBackgroundImageNameKey];
if (!inputViewBackgroundImageName) {
inputViewBackgroundImageName = @"input-bar-flat";
}
}
UIColor *borderColor = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewBorderColorKey];
if (!borderColor) {
borderColor = [UIColor colorWithWhite:0.8f alpha:1.0f];
}
CGFloat borderWidth = [[[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewBorderWidthKey] floatValue];
if (borderWidth == 0) {
borderWidth = 0.65f;
}
CGFloat cornerRadius = [[[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewCornerRadiusKey] floatValue];
if (cornerRadius == 0) {
cornerRadius = 6.0f;
}
_inputTextView.frame = CGRectMake(textViewLeftMargin, 4.5f, width, height);
_inputTextView.backgroundColor = [UIColor clearColor];
_inputTextView.layer.borderColor = borderColor.CGColor;
_inputTextView.layer.borderWidth = borderWidth;
_inputTextView.layer.cornerRadius = cornerRadius;
if (inputBackgroundColor) {
self.backgroundColor = inputBackgroundColor;
} else {
self.image = [[UIImage imageNamed:inputViewBackgroundImageName] resizableImageWithCapInsets:UIEdgeInsetsMake(2.0f, 0.0f, 0.0f, 0.0f)
resizingMode:UIImageResizingModeTile];
}
break;
}
default:
break;
}
if (self.allowsSendVoice) {
if (self.allowsSendText) {
NSString *voiceHolderImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewVoiceHolderImageNameKey];
if (!voiceHolderImageName) {
voiceHolderImageName = @"VoiceBtn_Black";
}
NSString *voiceHolderHLImageName = [[XHConfigurationHelper appearance].messageInputViewStyle objectForKey:kXHMessageInputViewVoiceHolderHLImageNameKey];
if (!voiceHolderHLImageName) {
voiceHolderHLImageName = @"VoiceBtn_BlackHL";
}
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(9, 9, 9, 9);
button = [self createButtonWithImage:XH_STRETCH_IMAGE([UIImage imageNamed:voiceHolderImageName], edgeInsets) HLImage:XH_STRETCH_IMAGE([UIImage imageNamed:voiceHolderHLImageName], edgeInsets)];
[button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
if([UIScreen mainScreen].bounds.size.height >= 812){ //是iphoneX
buttonFrame = CGRectMake(textViewLeftMargin-5, 0, width+10, self.frame.size.height-35);
}else{
buttonFrame = CGRectMake(textViewLeftMargin-5, 0, width+10, self.frame.size.height);
}
button.frame = buttonFrame;
button.alpha = self.voiceChangeButton.selected;
}else{
if([UIScreen mainScreen].bounds.size.height >= 812){ //是iphoneX
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)-35)];
}else{
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];
}
// button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];
[button setTitleColor:[UIColor whiteColor]
forState:UIControlStateNormal];
button.backgroundColor = [UIColor colorWithRed:255/255.0
green:126/255.0
blue:0 alpha:1];
}
[button setTitle:NSLocalizedStringFromTable(@"HoldToTalk", @"MessageDisplayKitString", nil) forState:UIControlStateNormal];
[button setTitle:NSLocalizedStringFromTable(@"ReleaseToSend", @"MessageDisplayKitString", nil) forState:UIControlStateHighlighted];
[button addTarget:self action:@selector(holdDownButtonTouchDown) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:@selector(holdDownButtonTouchUpOutside) forControlEvents:UIControlEventTouchUpOutside];
[button addTarget:self action:@selector(holdDownButtonTouchUpInside) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:@selector(holdDownDragOutside) forControlEvents:UIControlEventTouchDragExit];
[button addTarget:self action:@selector(holdDownDragInside) forControlEvents:UIControlEventTouchDragEnter];
[self addSubview:button];
self.holdDownButton = button;
}
}
#pragma mark - Life cycle
- (void)setup {
// 配置自适应
self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin);
self.opaque = YES;
// 由于继承UIImageView,所以需要这个属性设置
self.userInteractionEnabled = YES;
// 默认设置
_allowsSendText = YES;
_allowsSendVoice = YES;
_allowsSendFace = YES;
_allowsSendMultiMedia = YES;
_messageInputViewStyle = XHMessageInputViewStyleFlat;
}
- (void)awakeFromNib {
[self setup];
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setup];
}
return self;
}
- (void)dealloc {
self.inputedText = nil;
_inputTextView.delegate = nil;
_inputTextView = nil;
_voiceChangeButton = nil;
_multiMediaSendButton = nil;
_faceSendButton = nil;
_holdDownButton = nil;
}
- (void)willMoveToSuperview:(UIView *)newSuperview {
// 当别的地方需要add的时候,就会调用这里
if (newSuperview) {
[self setupMessageInputViewBarWithStyle:self.messageInputViewStyle];
}
}
#pragma mark - Message input view
- (void)adjustTextViewHeightBy:(CGFloat)changeInHeight {
// 动态改变自身的高度和输入框的高度
CGRect prevFrame = self.inputTextView.frame;
NSUInteger numLines = MAX([self.inputTextView numberOfLinesOfText],
[self.inputTextView.text numberOfLines]);
self.inputTextView.frame = CGRectMake(prevFrame.origin.x,
prevFrame.origin.y,
prevFrame.size.width,
prevFrame.size.height + changeInHeight);
self.inputTextView.contentInset = UIEdgeInsetsMake((numLines >= 6 ? 4.0f : 0.0f),
0.0f,
(numLines >= 6 ? 4.0f : 0.0f),
0.0f);
// from iOS 7, the content size will be accurate only if the scrolling is enabled.
self.inputTextView.scrollEnabled = YES;
if (numLines >= 6) {
CGPoint bottomOffset = CGPointMake(0.0f, self.inputTextView.contentSize.height - self.inputTextView.bounds.size.height);
[self.inputTextView setContentOffset:bottomOffset animated:YES];
[self.inputTextView scrollRangeToVisible:NSMakeRange(self.inputTextView.text.length - 2, 1)];
}
}
+ (CGFloat)textViewLineHeight {
return 36.0f; // for fontSize 16.0f
}
+ (CGFloat)maxLines {
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? 3.0f : 8.0f;
}
+ (CGFloat)maxHeight {
return ([XHMessageInputView maxLines] + 1.0f) * [XHMessageInputView textViewLineHeight];
}
#pragma mark - Text view delegate
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
if ([self.delegate respondsToSelector:@selector(inputTextViewWillBeginEditing:)]) {
[self.delegate inputTextViewWillBeginEditing:self.inputTextView];
}
self.faceSendButton.selected = NO;
self.voiceChangeButton.selected = NO;
return YES;
}
- (void)textViewDidBeginEditing:(UITextView *)textView {
[textView becomeFirstResponder];
if ([self.delegate respondsToSelector:@selector(inputTextViewDidBeginEditing:)]) {
[self.delegate inputTextViewDidBeginEditing:self.inputTextView];
}
}
- (void)textViewDidEndEditing:(UITextView *)textView {
[textView resignFirstResponder];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
// if ([text isEqualToString:@"\n"]) {
// if ([self.delegate respondsToSelector:@selector(didSendTextAction:)]) {
// [self.delegate didSendTextAction:textView.text];
// }
// return NO;
// }
// return YES;
// 最终的结果
NSString *str = textView.text;
NSString *resultStr = [str stringByReplacingCharactersInRange:range withString:text];
if ([text isEqualToString:@"\n"]) {
if ([self.delegate respondsToSelector:@selector(didSendTextAction:)]) {
[self.delegate didSendTextAction:textView.text];
}
return NO;
}else if ([resultStr getStringLenthOfBytes] > 64) //中文和字符一起检测 中文是两个字符
{
[SVProgressHUD dismiss];
[SVProgressHUD showErrorWithStatus:@"文字不允许超过32个汉字或64个英文字符"];
return NO;
}
if ([textView isFirstResponder]) {
if ([[[textView textInputMode] primaryLanguage] isEqualToString:@"emoji"] || ![[textView textInputMode] primaryLanguage]) {
return NO;
}
//判断键盘是不是九宫格键盘
if ([self isNineKeyBoard:str] ){
return YES;
}else{
if ([self hasEmoji:str] || [self stringContainsEmoji:str]){
return NO;
}
}
}
return YES;
}
/**
判断是不是九宫格
@param string 输入的字符
@return YES(是九宫格拼音键盘)
*/
-(BOOL)isNineKeyBoard:(NSString *)string
{
NSString *other = @"➋➌➍➎➏➐➑➒";
int len = (int)string.length;
for(int i=0;i<len;i++)
{
if(!([other rangeOfString:string].location != NSNotFound))
return NO;
}
return YES;
}
/**
* 判断字符串中是否存在emoji
* @param string 字符串
* @return YES(含有表情)
*/
- (BOOL)hasEmoji:(NSString*)string;
{
NSString *pattern = @"[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern];
BOOL isMatch = [pred evaluateWithObject:string];
return isMatch;
}
/**
* 判断字符串中是否存在emoji
* @param string 字符串
* @return YES(含有表情)
*/
- (BOOL)stringContainsEmoji:(NSString *)string {
__block BOOL returnValue = NO;
[string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:
^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
const unichar hs = [substring characterAtIndex:0];
// surrogate pair
if (0xd800 <= hs && hs <= 0xdbff) {
if (substring.length > 1) {
const unichar ls = [substring characterAtIndex:1];
const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
if (0x1d000 <= uc && uc <= 0x1f77f) {
returnValue = YES;
}
}
} else if (substring.length > 1) {
const unichar ls = [substring characterAtIndex:1];
if (ls == 0x20e3) {
returnValue = YES;
}
} else {
// non surrogate
if (0x2100 <= hs && hs <= 0x27ff) {
returnValue = YES;
} else if (0x2B05 <= hs && hs <= 0x2b07) {
returnValue = YES;
} else if (0x2934 <= hs && hs <= 0x2935) {
returnValue = YES;
} else if (0x3297 <= hs && hs <= 0x3299) {
returnValue = YES;
} else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
returnValue = YES;
}
}
}];
return returnValue;
}
@end