textviwe限制字数,包含,联想,中文高亮,emoji表情,粘贴截断的限制

分三个步骤

1.shouldChangeTextInRange处理

- (BOOL)textView:(YYTextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
//开始计算总字数,一个字符length为1,但是表情可能为多个所以此处每多一个表情,总个数自加1
    __block NSInteger count = 0;
    @weakify(self)
    [textView.text enumerateSubstringsInRange:NSMakeRange(0, textView.text.length)
                                      options:NSStringEnumerationByComposedCharacterSequences
                                   usingBlock:^(NSString *substring,NSRange substringRange,NSRange enclosingRange,BOOL *stop){
                                       @strongify(self)
//判断是emoji表情就++,有些emoji为1有些为2有些为4,具体数字可以在此处算出length自己加,demo只是简单的把每个表情当作了1
                                       if ([self stringContainsEmoji:substring]) {
                                           count++;
                                       }
                                   }];
//maxCount就是算上表情之后的总字数了
    NSInteger maxCount = maxLength + count;
//如果是删除就允许编辑
    if ([text isEqualToString:@""]) {
        return YES;
    }
//处理高亮部分,用于中文
    UITextRange *selectedRange = [textView markedTextRange];
    UITextPosition *position = [textView positionFromPosition:selectedRange.start offset:0];
    if (selectedRange && position) {
        NSInteger startOffset = [textView offsetFromPosition:textView.beginningOfDocument toPosition:selectedRange.start];
        NSInteger endOffset = [textView offsetFromPosition:textView.beginningOfDocument toPosition:selectedRange.end];
        NSRange offsetRange = NSMakeRange(startOffset, endOffset - startOffset);
        
        if (offsetRange.location < maxCount) {
            return YES;
        }else{
//已超出字数限制的提示
            return NO;
        }
    }
//开始计算,如果textview的length已经满了,直接NO
    if (range.location >= maxCount) {
//已超出字数限制的提示
        return NO;
    }
//此处防止粘贴直接满的情况
    if (textView.text.length >= maxCount) {
//已超出字数限制的提示
        return YES;
    }
    return YES;
}

2.textViewDidChange

- (void)textViewDidChange:(YYTextView *)textView {
    __block NSInteger count = 0;
    @weakify(self)
    [textView.text enumerateSubstringsInRange:NSMakeRange(0, textView.text.length)
                                      options:NSStringEnumerationByComposedCharacterSequences
                                   usingBlock:^(NSString *substring,NSRange substringRange,NSRange enclosingRange,BOOL *stop){
                                       @strongify(self)
                                       if ([self stringContainsEmoji:substring]) {
                                           count++;
                                       }
                                   }];
    NSInteger maxCount = maxLength + count;
    
    if (textView.text.length >= maxCount) {
        textView.text = [textView.text substringToIndex:maxCount];
        return;
    }
    UITextRange *selectedRange = [textView markedTextRange];
    //获取高亮部分
    UITextPosition *position = [textView positionFromPosition:selectedRange.start offset:0];
    //如果在变化中是高亮部分在变,就不要计算字符了
    if (selectedRange && position) {
        return;
    }
    NSString  *nsTextContent = textView.text;
    NSInteger existTextNum = nsTextContent.length;
    
    if (existTextNum > maxCount){
        //截取到最大位置的字符,达到最大字数限制
        NSString *s = [nsTextContent substringToIndex:maxCount];
        [textView setText:s];
    }
}

 

### 实现 Flutter 中限制用户输入 Emoji 表情 在 Flutter 应用程序中,可以通过 `TextField` 或 `TextFormField` 的控制器 (` TextEditingController`) 来监听用户的输入并实时验证其合法性。为了限制用户输入 Emoji 表情,可以利用正则表达式匹配非标准字符范围。 以下是具体的实现方式: #### 使用正则表达式过滤 Emoji 输入 根据提供的参考资料[^1],可以构建一个用于检测和移除 Emoji 字符的正则表达式 `[^\u0000-\uFFFF]`。此正则表达式的含义是匹配任何不在基本多语言平面 (BMP) 范围内的 Unicode 字符,这些字符通常包括大多数 Emoji 表情。 以下是一个完整的代码示例,展示如何在 Flutter 中实现这一功能: ```dart import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: NoEmojiInputScreen(), ); } } class NoEmojiInputScreen extends StatefulWidget { @override _NoEmojiInputScreenState createState() => _NoEmojiInputScreenState(); } class _NoEmojiInputScreenState extends State<NoEmojiInputScreen> { final TextEditingController _controller = TextEditingController(); void _filterEmoji(String value) { String filteredValue = value.replaceAll(RegExp(r'[^\u0000-\uFFFF]'), ''); // 移除所有 Emoji [^1] setState(() { if (_controller.text != filteredValue) { // 防止无限循环调用 onChanged _controller.value = TextEditingValue( text: filteredValue, selection: TextSelection.collapsed(offset: filteredValue.length), ); } }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('禁止输入 Emoji')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _controller, onChanged: _filterEmoji, // 实时过滤 Emoji 输入 decoration: InputDecoration( labelText: '请输入文本', border: OutlineInputBorder(), ), ), SizedBox(height: 20), ElevatedButton( onPressed: () { print(_controller.text); // 打印最终结果 }, child: Text('提交'), ) ], ), ), ); } @override void dispose() { _controller.dispose(); // 清理资源 super.dispose(); } } ``` #### 关键点解析 1. **正则表达式的作用** 正则表达式 `r'[^\u0000-\uFFFF]'` 是用来识别超出 BMP 平面的字符,即大部分 Emoji 和特殊符号。通过将其替换为空字符串即可达到去除的目的。 2. **动态更新输入框内容** 利用 `_controller.value` 更新 `TextField` 的显示内容,并同步调整光标位置以提供更好的用户体验。 3. **防止死循环触发** 在设置新的 `TextEditingController` 值之前,先比较当前值与目标值是否相同,从而避免因重复调用 `onChanged` 导致的性能问题。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值