zoukankan      html  css  js  c++  java
  • iOS开发中UITextView使用小结

      最近项目开发中用到了多行文本框限制文字输入个数限制,之前的话在textViewDidChange方法中截取超出字数就可以。测试人员发现在拼音转汉字的过程中,YYTextView不会二次确认textViewDidChange方法,输入字数只能最后确认结束弹框的时候计算,影响体验效果,后转用自己封装的继承UITextView替换。另外拼音转汉字的情况下,在输入文本中间一直输入,依然会出现输入字数计算不准确的问题。下面列出解决问题实现的代码。

      

    #pragma mark- UITextViewDelegate

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

    {

        [self.activityTextView resignFirstResponder];

    }

     

    -(void)updateSpeechButtonStatus{

        if (self.activityTextView.text.length >= MAX_NUM) {

            self.btnSpeech.enabled = NO;

        }else{

            self.btnSpeech.enabled = YES;

        }

    }

    //动态显示可输入文本字数

    -(void)changeTextNumber:(UITextView *)textView{

        if (textView.text.length <= MAX_NUM) {

            self.numLabel.text = [NSString stringWithFormat:@"%lu/%lu",(unsigned long)textView.text.length,(MAX_NUM - textView.text.length)];

        }else{

            self.numLabel.text = [NSString stringWithFormat:@"%@/%@",[NSString stringWithFormat:@"%d",MAX_NUM],@"0"];

        }

    }

    -(void)textViewDidChange:(UITextView *)textView{

        

        UITextRange *selectedRange = [textView markedTextRange];

        //获取高亮部分

        UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0];

        

        //如果是拼音转汉语状态不统计字数,确认输入后统计

        if (selectedRange && pos) {

            return;

        }

        

        [self changeTextNumber:textView];

        [self updateSpeechButtonStatus];

        

    }

    -(void)textViewDidEndEditing:(UITextView *)textView{

        textView.text = [EaseEmoji stringReplaceEmoji:textView.text];

        [self changeTextNumber:textView];

        [self updateSpeechButtonStatus];

    }

     

    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text

    {

        BOOL isLimit = [CCCommonAPI textViewTextCountLimit:textView range:range text:text maxCount:[NSString stringWithFormat:@"%d",MAX_NUM] isAllowEmoji:YES completeBlock:^{

            //执行这里block的时候不执行textViewDidChange,block里面的内容就是textViewDidChange里面的操作

            [self changeTextNumber:textView];

            [self updateSpeechButtonStatus];

        }];

        return isLimit;

        

    }

    //textview字数限制处理

    + (BOOL)textViewTextCountLimit:(UITextView *)textView range:(NSRange)range text:(NSString *)text maxCount:(NSString *)maxCountStr isAllowEmoji:(BOOL)isAllowEmoji completeBlock:(nonnull CommonTextLimitCompletion)completeBlock{

        

        if (!isAllowEmoji) {

            //不允许输入表情的时候返回NO

            if ([[[UITextInputMode currentInputMode] primaryLanguage] isEqualToString:@"emoji"]) {

                return NO;

            }

        }

        

        //对于退格删除键开放限制

        if (text.length == 0) {return YES;}

            

        NSString *comcatstr = [textView.text stringByReplacingCharactersInRange:range withString:text];

        

        NSInteger caninputlen = [maxCountStr intValue] - comcatstr.length;

        

        if (caninputlen >= 0){

            return YES;

        }else{

            NSInteger len = text.length + caninputlen;

            //防止当text.length + caninputlen < 0时,使得rg.length为一个非法最大正数出错

            NSRange rg = {0,MAX(len,0)};

            

            if (rg.length > 0){

                NSString *s = @"";

                //判断是否只普通的字符或asc码(对于中文和表情返回NO)

                BOOL asc = [text canBeConvertedToEncoding:NSASCIIStringEncoding];

                if (asc) {

                    s = [text substringWithRange:rg];//因为是ascii码直接取就可以了不会错

                }else{

                    __block NSInteger idx = 0;

                    __block NSString  *trimString = @"";//截取出的字串

                    //使用字符串遍历,这个方法能准确知道每个emoji是占一个unicode还是两个

                    [text enumerateSubstringsInRange:NSMakeRange(0, [text length])

                                                  options:NSStringEnumerationByComposedCharacterSequences

                                               usingBlock: ^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop) {

                                                   

                                                   if (idx >= rg.length) {

                                                       *stop = YES; //取出所需要就break,提高效率

                                                       return ;

                                                   }

                                                   

                                                   trimString = [trimString stringByAppendingString:substring];

                                                   

                                                   idx++;

                                               }];

                    

                    s = trimString;

                }

                //rang是指从当前光标处进行替换处理(注意如果执行此句后面返回的是YES会触发didchange事件)

                [textView setText:[textView.text stringByReplacingCharactersInRange:range withString:s]];

                

                completeBlock();

                

                //手动截取更改,不再调用didchange

                return NO;

            }else{

                UITextRange *selectedRange = [textView markedTextRange];

                //获取高亮部分

                UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0];

                

                if (selectedRange && pos) {

                    //如果拼音转汉语状态继续输入

                    return YES;

                }else{

                    return NO;

                }

            }

        }

    }

  • 相关阅读:
    SpringMVC从Request域中获取数据
    SpringMVC重定向
    SpringMVC的请求转发的三种方法
    SpringMVC文件上传
    SpringMVC处理请求释放静态资源的三种方式
    jackson实现json转换
    SpringMVC之请求部分
    SpringMVC的执行流程
    Java [Leetcode 39]Combination Sum
    深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
  • 原文地址:https://www.cnblogs.com/bigant9527/p/15155578.html
Copyright © 2011-2022 走看看