Je voudrais simuler un événement de suppression de retour arrière du clavier à partir d'une chaîne dans Flutter (ou Dart). Quelque chose comme:
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"
7 Réponses :
Ce que vous voulez vérifier n'est pas clair. Je vous suggère de supprimer le -1
de la sous-chaîne car cela cassera la capture de code de l'emoji
abcð (97, 98, 99, 128512) (97, 98, 99, 128512)
Cela donnera la sortie de
void main() { var str = "abcð"; var newStr = str.substring(0, str.length); // i removed it here print(newStr); print(newStr.runes); print(str.runes); }
Testé sur https://dartpad.dartlang.org/
Je pensais que ma question était claire. que dois-je changer pour clarifier ma question? Je veux trouver la plage de codes non valide. J'ajoute -1 dans le but. Je veux détecter si une chaîne contient un caractère invalide ou non. En d'autres termes, 55357 est un code char invalide. et je veux savoir quels sont tous les autres codes de caractères invalides. Merci.
Il n'est pas logique d'utiliser une sous-chaîne pour vérifier si la chaîne contient un caractère non valide. Qu'en est-il de cette chaîne alors var str = "abc😀 xx";
il donnera la sortie suivante abc😀 x (97, 98, 99, 128512, 32, 120) (97, 98, 99, 128512, 32, 120, 120)
Merci beaucoup pour votre réponse. Je viens de modifier la question. Vous pouvez mieux comprendre ce que je veux réaliser maintenant. Désolé pour la confusion.
Je comprends ce que sgon00 veut faire: (1) par exemple, pour toute application qui a un widget `` Entrée de texte '', allez dans ce widget, saisissez n'importe quel emoji et cliquez sur le retour arrière de votre clavier virtuel, vous pourrez voir seulement «LA MOITIÉ DES EMOJI EST SUPPRIMÉE» (Essayez-vous d'abord!). Sa première question est donc de savoir comment supprimer tout l'emoji en cliquant sur le retour arrière.
Question 2, si (1) ne peut pas être fait, pouvons-nous vérifier si une chaîne contient HALF EMOJI afin de pouvoir supprimer ce demi-emoji par programme?
@KennethLi vous avez absolument raison. Je mettrai à jour ma question avec vos mots. :) Merci.
Si nous pouvons résoudre son problème (1), alors oubliez simplement (2), c'est-à-dire oubliez le str.length - 1, ce 'MINUS ONE', est pour créer un 'HALF EMOJI' par programme.
L'équipe Dart a publié un package d' aide qui aide à atteindre cet objectif. String.characters.skipLast(1)
devrait être capable de faire ce que vous attendez.
Tout d'abord, passons à quelques définitions. Selon cette page:
Lorsque vous supprimez le dernier caractère à l'aide d'une substring
- substring
, vous supprimez en fait la dernière unité de code. Si vous exécutez print(newStr.codeUnits)
et print(str.codeUnits)
, vous verrez que la rune 128512
est équivalente à la jointure des unités de code 55357
et 56832
, donc 55357
est en fait valide, mais ne représente rien sans "l'aide" d'une autre unité de code.
En fait, vous ne voulez pas utiliser substring()
quand il y a des caractères non ASCII dans votre chaîne (comme des émojis ou des lettres arabes). Ça ne marchera jamais. Ce que vous devez faire est de supprimer le dernier cluster de graphèmes. Quelque chose d'aussi simple que ça:
str.graphemeClusters.removeLast()
Cependant, Dart ne le prend pas encore en charge. Il y a plusieurs problèmes autour de ce point. Certains d'entre eux: https://github.com/dart-lang/language/issues/34
https://github.com/dart-lang/language/issues/49
Ce manque de support peut entraîner d'autres problèmes, comme celui que vous avez mentionné et celui-ci: https://github.com/flutter/flutter/issues/31818
Merci beaucoup pour la réponse. Le problème est que je dois implémenter cette fonctionnalité maintenant. Comment puis-je contourner ce problème? J'ai une chaîne qui est un mélange de caractères anglais, de caractères asiatiques, de grappes de graphèmes, etc. Je dois implémenter une action de retour arrière. Il devrait supprimer correctement un par un. Par exemple, hello你🇵🇬
devrait devenir `à la première action backspace` `bonjour你puis hello
à la deuxième fois et l' hell
à la troisième fois. Merci beaucoup.
Vous ne pouvez pas. Du moins pas de manière simple. J'ai une idée pour contourner cela, mais ce sera un package et je prendrai jusqu'à 1 semaine pour le créer. Il faudrait attendre un peu.
OK cool. Je peux attendre. actuellement, je désactive les gens pour saisir tous les caractères dont la longueur de chaîne est supérieure à 2. puis j'utilise quelque chose comme String.fromCharCodes(sRunes, 0, sRunes.length-1)
comme solution de contournement.
Sgon00 vient-il de Chine? Les étrangers peuvent ne pas comprendre à quel point il est douloureux d'ajouter des emoji en chinois et en anglais!
@KennethLi Oui, je suis en Chine maintenant. Ouais, je viens de Chine. ^ _ ^
Bonjour, j'ai vérifié le problème arc-en-ciel (31818) que vous avez déposé. Je n'ai pas ce problème ici. Voulez-vous dire les emoji 🌈
? J'utilise le flutter master v1.5.9-pre.205.
Salut, juste pour info. J'ai résolu le problème et posté comme réponse. Il devrait être capable de gérer toutes sortes d'emojis. stackoverflow.com/a/56135774/348719
@ sgon00 On dirait que le problème TextField
vous avez mentionné vient d'être corrigé: github.com/flutter/flutter/issues/23496
@HugoPassos merci pour l'info. Je n'ai pas terminé la mise à niveau du flutter donc je ne peux pas encore la tester. La vitesse de téléchargement est trop lente et je ne veux pas utiliser le miroir cn, donc je dois souffrir de la lenteur.
Vous pouvez faire une méthode comme celle-ci
TextField( onChanged: (text) { isValid(varYouHad ,text); //validate }, );
puis dans votre clavier vous validez avec une propriété onChange
bool isValid(String prevString, String newString){ if (prevString == newString) return true; else return false; }
Désolé pour mon anglais (pas ma langue maternelle). Je pense que vous pouvez toujours mal comprendre ma question. Le code ci-dessus vérifie simplement si deux chaînes sont identiques ou non. Je ne sais pas comment cela aide à répondre à ma question. J'ai ajouté le lien de bogue dans la question. J'ai besoin de détecter si le texte est valide ou non et sinon, de supprimer le caractère inattendu. Veuillez me faire savoir si ma description n'est toujours pas claire. J'essaierai plus de mots pour expliquer.
Non mais c'est très bien, car si le charcode change, la chaîne change également et vous donne false. Je l'ai testé.
Mais ma question n'est pas de tester si la chaîne change ou non. Ma question essaie de supprimer le caractère inattendu par programme lorsqu'il existe. Je mettrai à jour à nouveau la description de ma question.
Je pensais que vous vouliez cela parce que vous avez écrit.Je I am wondering if there is a invalid char code range exists, so that I can write a function to check if the character is invalid or not, for example, isValid(55357) will return false.
hahaha pas de soucis
Merci beaucoup pour votre temps et votre aide. Mon objectif principal est que isValid(55357)
doit renvoyer false. Pour que je sache que 55357 est invalide et doit être supprimé par programme. J'ai de nouveau mis à jour la question. Espérons que cette fois, cela a plus de sens.
Cette réponse pose toujours problème
Puisque dart ne fournit pas le type de données 'Grapheme Cluster', j'essaie d'utiliser le canal de méthode pour le faire en utilisant kotlin:
Étape 1: Créez un nouveau projet 'Flutter Plugin', nommez le projet 'gmc01', 2 fichiers seront créés automatiquement, à savoir 'gmc01.dart' et 'main.dart'.
Étape 2: remplacez les codes dans gmc01.dart par ce qui suit:
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):
Étape 3: remplacez les codes dans main.dart par ce qui suit:
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) } }
Étape 4: Dans android / build.gradle, modifiez minSdkVersion de 16 à 24.
Étape 5: Dans example / android / app / build.gradle, changez la minSdkVersion de 16 à 24.
Étape 6: Cliquez sur Fichier-> Ouvrir, sélectionnez gmc01-> Android, puis cliquez sur 'OK', la partie kotlin du plugin sera ouverte (dans une autre fenêtre).
Étape 7: remplacez les codes dans Gmc01Plugin.kt par ce qui suit: (Remplacez la première ligne par votre propre nom de package)
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); }
Étape 8: Revenez à la fenêtre du plugin, et cliquez sur 'Exécuter'.
Voici la sortie dans la console:
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; } }
Comme vous pouvez le voir, les emoji 'Famille Emoji', 'Visage Emoji' et 'Drapeau du pays' sont supprimés correctement, mais les 2 caractères chinois 'æˆ'ä »¬' et les chiffres '12345678' sont supprimés en utilisant un seul removeLastGMC , il faut donc encore déterminer comment distinguer les caractères chinois à deux octets / caractères anglais / émojis.
BTW, je ne sais pas comment faire la partie Swift, quelqu'un peut-il aider?
Salut, merci pour le code. Mais cela ne fonctionnera pas lorsque l'emoji a besoin de deux codes de caractères pour représenter (longueur de chaîne> 2). Par exemple, 🇵🇬
. Pour les emoji avec une longueur de chaîne de 2, j'utilise String.fromCharCodes(sRunes, 0, sRunes.length-1)
, qui a une idée similaire à la vôtre. Je vérifie le commentaire de Tom qui m'indique la plage de codes de caractères correcte.
Salut, FYI. J'ai résolu le problème qui devrait être capable de gérer n'importe quel type d'émojis. Veuillez vérifier ma propre réponse, stackoverflow.com/a/56135774/348719
Le code ne fonctionne pas correctement. Je viens de mettre ici pour référence.
🇵🇬
et ðŸ'¨â€ ðŸ'©â€ ðŸ'¦
.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; }
😀😀
séquence emoji connectée 😀😀
et ðŸ'¨â€ ðŸ'©â€ ðŸ'¦
.Basé sur le lien
String myBackspace(String str) { Runes strRunes = str.runes; str = String.fromCharCodes(strRunes, 0, strRunes.length - 1); print(str); return str; }
comme le mien, le vôtre ne fonctionne pas avec les emojis complexes tels que les 'familles emojis', par exemple celui-ci '👨👩👦'. Cet emoji, affiché comme 'Un seul Emoji avec 3 personnes', lorsque vous utilisez vos codes, les 3 personnes seront supprimées un par un.
il y a d'autres 'emoji simples' qui peuvent prendre jusqu'à 8 'caractères', c'est-à-dire str.length = 8
C'est vrai. Malheureusement, la seule façon de bien faire les choses est de supprimer le cluster de graphèmes, comme je l'ai dit dans ma réponse.
@KennethLi Mon code a même un autre problème, supprimera les emojis de séquence tels que 😀😀
à la fois. J'essaye de comprendre comment les contourner. Si cela ne peut pas être fait dans les 30 minutes, je devrai d'abord dormir et vérifier demain. :)
Je suis d'accord avec Hugo Passos
si quelqu'un a besoin d'une solution simple pour supprimer les emojies de la chaîne, essayez ceci.
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,''); }
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; } Ex: Go to https://dartpad.dev/ to test:String str = "ThaiKVåãè¡ããã©ããðððð°ðð" => ThaiKVåãè¡ããã©ãã
Pourriez-vous reformuler la question s'il vous plaît?
@Jalil que puis-je faire pour reformater la question? Je suis d'accord pour le reformater, mais je ne sais pas ce que vous voulez que je fasse?
@ sgon00 Votre question n'est pas claire. Que veux-tu accomplir?
Comme poser explicitement une question
@Jalil, j'ai édité ma question. Vous pouvez jeter un œil maintenant. J'essaierai de l'améliorer à nouveau après cette réponse. Merci beaucoup pour votre commentaire.
Qu'essayez-vous de faire? en général? Juste pour voir s'il y a une autre approche du problème
@Jalil Je viens d'ajouter une section "PS" dans la description de ma question. Vous pouvez jeter un oeil. Fondamentalement, je souhaite supprimer tous les caractères non valides d'une chaîne. (1) un bug de scintillement fait que les emojis ne peuvent pas être supprimés correctement par un retour arrière et un point d'interrogation gauche à la fin de chaque emoji. (2) J'ai également besoin d'implémenter un bouton pour supprimer les entrées utilisateur (char par char) qui contiennent aussi des emojis.
@HugoPassos merci beaucoup de m'avoir dit ça. J'ai modifié la question et le titre. Vous pouvez jeter un œil maintenant. À votre santé.
Si vous commencez avec une chaîne valide, le problème est que vous vous retrouvez avec un substitut élevé sans un substitut bas immédiatement après. Ce sont des plages d'unités de code UTF-16 bien définies . @HugoPassos explique la terminologie. (Je ne connais pas Dart mais je suppose que vous pouvez coder un chèque.)
@TomBlodget merci beaucoup pour le lien. Je suis heureux d'apprendre qu'il existe des fourchettes bien définies. J'essaierai de l'ajouter à mon code. Et va coller le résultat ici.
@TomBlodget merci beaucoup pour le lien. Sur la base de la gamme, j'ai publié une réponse . Cela fonctionne enfin. 😀
@TomBlodget salut, je viens de trouver un problème avec mon code. Je ne peux pas distinguer
😀😀
et🇵🇬
. Donc, il supprimera tous les emojis connectés à la fois. Puisque🇵🇬
se🇵🇬
en deux emojis, avez-vous des idées pour vérifier si🇵🇬
est un emoji au lieu de deux? Merci beaucoup.