我想从Flutter(或Dart)中的字符串模拟键盘退格键删除事件。像这样:
String str = "hello你们"
myBackspace(str) // will return "hello你们"
myBackspace(str) // will return "hello你们"
myBackspace(str) // will return "hello你们"
myBackspace(str) // will return "hello你"
myBackspace(str) // will return "hello"
myBackspace(str) // will return "hello"
myBackspace(str) // will return "hell"
非常感谢。
注意:该问题的标题和描述与原始帖子相比有很大变化。
答案 0 :(得分:2)
首先,让我们了解一些定义。根据{{3}}页:
使用substring
删除最后一个字符时,实际上是在删除最后一个代码单元。如果您运行print(newStr.codeUnits)
和print(str.codeUnits)
,则会看到128512
符与代码单元55357
和56832
的联合等效,因此{ {1}}实际上是有效的,但是在没有另一个代码单元的“帮助”的情况下不代表任何内容。
实际上,当您的字符串中包含非ASCII字符(例如表情符号或阿拉伯字母)时,您不想使用55357
。它永远都行不通。您要做的是删除最后一个字素簇。这么简单:
substring
但是,Dart尚不支持此功能。关于这一点,存在几个问题。其中一些:
this
https://github.com/dart-lang/language/issues/34
这种缺乏支持的接缝会导致其他一些问题,例如您提到的问题和该问题: https://github.com/dart-lang/language/issues/49
答案 1 :(得分:2)
此答案仍然有问题
由于dart不提供数据类型“ Grapheme Cluster”,因此我尝试使用方法通道使用kotlin进行此操作:
第1步:创建一个新的“ Flutter插件”项目,将其命名为“ gmc01”,将自动创建2个文件,即“ gmc01.dart”和“ main.dart”。
第2步:将gmc01.dart中的代码替换为以下内容:
import 'dart:async';
import 'package:flutter/services.dart';
class Gmc01 {
static const MethodChannel _channel =
const MethodChannel('gmc01');
static Future<String> removeLastGMC(String strOriginal) async {
final String version = await _channel.invokeMethod('removeLastGMC', strOriginal);
return version;
}
}
步骤3:将main.dart中的代码替换为以下内容:
import 'package:gmc01/gmc01.dart';
void main() async {
String strTemp = '12345678我们5你';
strTemp = await Gmc01.removeLastGMC(strTemp);
print(strTemp);
strTemp = await Gmc01.removeLastGMC(strTemp);
print(strTemp);
strTemp = await Gmc01.removeLastGMC(strTemp);
print(strTemp);
strTemp = await Gmc01.removeLastGMC(strTemp);
print(strTemp);
strTemp = await Gmc01.removeLastGMC(strTemp);
print(strTemp);
strTemp = await Gmc01.removeLastGMC(strTemp);
print(strTemp);
strTemp = await Gmc01.removeLastGMC(strTemp);
print(strTemp);
}
第4步:在android / build.gradle中,将minSdkVersion从16更改为24。
步骤5:在example / android / app / build.gradle中,将minSdkVersion从16更改为24。
步骤6:单击文件->打开,选择gmc01-> android,然后单击“确定”,将打开插件的kotlin部分(在另一个窗口中)。
第7步:用以下代码替换Gmc01Plugin.kt中的代码:(用您自己的软件包名称替换第一行)
package com.example.gmc01 // replace the left with your own package name
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
import android.icu.text.BreakIterator
class Gmc01Plugin: MethodCallHandler {
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), gmc01)
channel.setMethodCallHandler(Gmc01Plugin())
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
var strArg: String
strArg = call.arguments.toString()
var boundary = BreakIterator.getWordInstance()
boundary.setText(strArg);
when (call.method) {
removeLastGMC -> {
result.success(removeLastGMC(boundary, strArg))
}
else -> {
result.notImplemented()
}
}
}
fun removeLastGMC(boundary: BreakIterator, source: String):String {
val end = boundary.last()
val start = boundary.previous()
return source.substring(0, start)
}
}
第8步:返回到插件窗口,然后单击“运行”。
这是控制台中的输出:
I/flutter (22855): 12345678我们5你
I/flutter (22855): 12345678我们5你
I/flutter (22855): 12345678我们5
I/flutter (22855): 12345678我们5
I/flutter (22855): 12345678我们
I/flutter (22855): 12345678
I/flutter (22855):
如您所见,正确删除了“家庭表情符号”,“面部表情符号”和“国家国旗”表情符号,但是使用单个removeLastGMC删除了中文2个字符“我们”和数字“ 12345678”,因此仍然需要弄清楚如何区分中文双字节字符/英文字符/表情符号。
顺便说一句,我不知道该怎么做Swift部分,有人可以帮忙吗?
答案 2 :(得分:1)
代码无法正常运行。我只是放在这里供参考。
和
。String myBackspace(String str) {
Runes strRunes = str.runes;
str = String.fromCharCodes(strRunes, 0, strRunes.length - 1);
print(str);
return str;
}
和
。基于link
String myBackspace(String str) {
int i = 0;
while (str.length > 0) {
i++;
int removedCharCode = str.codeUnitAt(str.length - 1);
if (isWellFormattedUTF16(removedCharCode)) break;
str = str.substring(0, str.length - 1);
}
if (i == 1) str = str.substring(0, str.length - 1);
print(str);
return str;
}
bool isWellFormattedUTF16(int charCode) {
int surrogateLeadingStart = 0xD800;
int surrogateLeadingEnd = 0xDBFF;
int surrogateTrailingStart = 0xDC00;
int surrogateTrailingEnd = 0xDFFF;
if (!(charCode >= surrogateLeadingStart && charCode <= surrogateLeadingEnd) &&
!(charCode >= surrogateTrailingStart && charCode <= surrogateTrailingEnd)) return true;
return false;
}
答案 3 :(得分:1)
如果有人需要简单的解决方案从字符串中删除表情符号,请尝试此操作。
String str = "hello??你们?????"İ
final RegExp REGEX_EMOJI = RegExp(r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])');
if(str.contains(REGEX_EMOJI)){
str = str.replaceAll(REGEX_EMOJI,'');
}
答案 4 :(得分:1)
String formatText(String str) {
final RegExp regExp = RegExp(r'(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])');
if(str.contains(regExp)){
str = str.replaceAll(regExp,'');
}
return str; }
例如:转到https://dartpad.dev/进行测试:
String str =“ ThaiKV受け行くけどよね??????” => ThaiKV受け行くけどよね
答案 5 :(得分:1)
With RegExp and replaceAll:
final regex = RegExp(
"(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-
\udfff]|\ud83e[\ud000-\udfff])");
final textReplace = String.replaceAll(regex, '');
答案 6 :(得分:0)
您要检查的内容有点不清楚。我建议您从子字符串中删除-1
,因为它会破坏表情符号的代码片段
void main() {
var str = "abc";
var newStr = str.substring(0, str.length); // i removed it here
print(newStr);
print(newStr.runes);
print(str.runes);
}
这将给出
的输出abc
(97, 98, 99, 128512)
(97, 98, 99, 128512)
的测试
答案 7 :(得分:0)
您可以执行类似这样的方法
bool isValid(String prevString, String newString){
if (prevString == newString)
return true;
else return false;
}
然后在键盘上使用onChange属性进行验证
TextField(
onChanged: (text) {
isValid(varYouHad ,text); //validate
},
);