J'ai besoin de détecter des modifications de texte dans un editext. J'ai essayé Textwatcher, mais cela ne fonctionne pas d'une manière à laquelle je m'attendrais. Prenez la méthode OntextChanged:
Dites que j'ai déjà le texte "Jean" dans le Éditer le texte. Si vous appuyez sur une autre touche, "E", Donc, donc je m'attendrais à: Public Void OntextChanged (Chaluquerence S, INT START, INT avant, int compte) CODE> P>
s code> sera "johne",
Démarrer code> sera 0,
avant code> sera 4, et
Compte Code> sera 5. La façon dont je m'attendrais à ce que cette méthode fonctionne serait la différence entre ce que l'EditText était précédemment, et ce qu'il est sur le point de devenir. P>
s = "Johne"
start = 4 // inserting character at index = 4
before = 0 // adding a character, so there was nothing there before
count = 1 // inserting one character
4 Réponses :
Utilisez un Textwatcher et faites-le vous-même. Stockez le texte précédent à l'intérieur de l'observateur, puis comparez le texte précédent à la séquence que vous obtiendrez obtentit d'anéulvement. Étant donné que l'OntextChanged est tiré après chaque personnage, vous connaissez votre texte précédent et que le texte donné diffère au plus d'une lettre, ce qui devrait rendre simple à comprendre quelle lettre a été ajoutée ou supprimée où. IE:
new TextWatcher(){ String previousText = theEditText.getText(); @Override onTextChanged(CharSequence s, int start, int before, int count){ compare(s, previousText); //compare and do whatever you need to do previousText = s; } ... }
C'est une suggestion que j'ai pensée, et certainement viable, mais j'espérais un "voici toi facile!" méthode, qui peut n'exurer peut-être pas. Le seul problème avec votre approche est que le texte peut différer de plus de 1 lettre (plage de sélection, collant du presse-papiers).
Vrai mais à cet endroit, les indices ont peu de signification (que se passe-t-il si vous collez un mot avant le texte actuel par exemple?) Et même alors vous pouvez toujours faire le DIFF vous-même. Je ne pense pas qu'il y ait des solutions intégrées pour ce que vous essayez de faire.
Assez juste. J'ai fini par faire ce que vous avez dit et essentiellement mis en œuvre mon propre Textwatcher et transmis de valeurs que j'attendais. Ce n'est pas une preuve poisson à 100% mais c'est assez proche.
Vous devez stocker et mettre à jour le charcuternence précédent chaque fois que le texte est modifié. Vous pouvez le faire en implémentant le Textwatcher .
Exemple: p>
La meilleure approche que vous puissiez suivre pour identifier les modifications de texte.
var previousText = "" override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { previousText = s.toString() } override fun onTextChanged(newText: CharSequence?, start: Int, before: Int, count: Int) { val position = start + before ; if(newText!!.length > previousText.length){ //Character Added Log.i("Added Character", " ${newText[position]} ") Log.i("At Position", " $position ") } else { //Character Removed Log.i("Removed Character", " ${previousText[position-1]} ") Log.i("From Position", " ${position-1} ") } } override fun afterTextChanged(finalText: Editable?) { }
Je fait face au même problème récemment et je l'ai écrit mon propre algorithme personnalisé pour détecter la diff de la sortie TextWatcher
Algorithme -. P>
Nous stockons 4 choses - p>
Au-dessus de 4 choses sont mises à jour au cours de la au cours du cas suivants sont possibles - p> Cas 1 strong> p> Ceci est une suppression cas avant. Le nombre de caractères supprimés peut être calculé par la longueur ancien_texte moins la longueur newText p> Exemple - p> Ancien texte = Bonjour wo |. DNR ( séquence de texte Ancien avant le curseur / sélection = séquence de texte Ancien après le curseur / sélection = ancienne taille de la sélection = le nouveau texte = Bonjour wo | ld ( Nouvelle séquence de texte avant le curseur / sélection = Nouvelle séquence de texte après le curseur / sélection = Il est clair que cela est un cas de suppression vers l'avant par 1 caractère. p> cas n ° 2 strong> p> est un cas de suppression vers l'arrière. Le nombre de caractères supprimés peut être calculé par la longueur ancien_texte moins la longueur newText p> Exemple - p> Ancien texte = Bonjour wo |. DNR ( séquence de texte Ancien avant le curseur / sélection = séquence de texte Ancien après le curseur / sélection = ancienne taille de la sélection = le nouveau texte = Bonjour w | DNR ( Nouvelle séquence de texte avant le curseur / sélection = Nouvelle séquence de texte après le curseur / sélection = Il est clair que cela est un cas de suppression dans le sens vers l'arrière par 1 caractère. p> cas n ° 3 strong> p> est un boîtier d'insert. La chaîne d'insertion exacte peut être calculée en supprimant le Exemple -. P> Old text = Bonjour wo | DNR ( séquence de texte ancien avant le curseur / sélection = ancienne taille de la sélection = le nouveau texte = Bonjour wo123 | DNR ( Nouvelle séquence de texte avant le curseur / sélection = Nouvelle séquence de texte après le curseur / sélection = Il est clair que ceci est un cas d'insert et la chaîne inséré est cas 4 strong> p> Si aucun des cas ci-dessus sont remplies, alors nous pouvons dire qu'il est un cas remplacer. Et le remplacement des données déjà fournies par TextWatcher dans le Voici le code pour l'algorithme ci-dessus -. P> beforeTextChanged () code> rappel. P>
OnTextChanged () code> rappel, on calcule après deux choses - p>
Nouvelle séquence de texte avant le curseur / sélection == Vieux séquence de texte avant le curseur / sélection code>
Nouvelle séquence de texte après le curseur / sélection isASuffixOf séquence de texte Ancien après le curseur / sélection code> p>
| code> représente le curseur) p>
Bonjour wo code> p>
RLD code> p>
0 code> p>
| code> représente le curseur) p>
Bonjour wo code> p>
ld code> p >
Nouvelle séquence de texte après la curseur / sélection == séquence de texte Ancien après le curseur / sélection code>
Nouvelle séquence de texte avant le curseur / sélection isAPrefixOf séquence de texte Ancien avant le curseur / sélection code> p>
| code> représente le curseur) p>
Bonjour wo code> p>
RLD code> p>
0 code> p>
| code> représente le curseur) p>
Bonjour w code> p>
RLD code> p >
Nouvelle séquence de texte après la curseur / sélection == séquence de texte Ancien après le curseur / sélection code>
séquence de texte Ancien avant le curseur / sélection isAPrefixOf Nouvelle séquence de texte avant le curseur / sélection code> p>
ancienne séquence de texte à partir du curseur + ancienne séquence de texte après le curseur code> de la nouvelle chaîne de texte p>
| code> représente le curseur) p>
Bonjour wo code> p> séquence de texte Ancien après le curseur / sélection =
RLD code> p>
0 code> p>
| code> représente le curseur) p>
Bonjour wo123 code> p>
RLD code> p>
123 code>. p>
OnTextChanged code> rappel p>
class MyTextWatcher : android.text.TextWatcher {
var oldSelectionSize = 0
var oldText: String = ""
var oldSequenceBeforeCursor: String = ""
var oldSequenceAfterCursor: String = ""
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
oldSelectionSize = editText.selectionEnd - editText.selectionStart
oldText = s.toString()
oldSequenceBeforeCursor = s?.subSequence(0, editText.selectionStart).toString()
oldSequenceAfterCursor = s?.subSequence(editText.selectionEnd, s.length).toString()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
s?.toString()?.let { newText ->
val newSequenceBeforeCursor = newText.subSequence(0, selectionStart).toString()
val newSequenceAfterCursor = newText.subSequence(selectionEnd, newText.length)
.toString()
if (newSequenceBeforeCursor == oldSequenceBeforeCursor &&
oldSequenceAfterCursor.endsWith(newSequenceAfterCursor))
// handle delete forward
// number of characters to delete ==>
// if(oldSelectionSize > 0) then deleted number of characters = oldSelectionSize
// else number of characters to delete = oldText.length - newText.length
else if (newSequenceAfterCursor == oldSequenceAfterCursor &&
oldSequenceBeforeCursor.startsWith(newSequenceBeforeCursor))
// handle delete backward
// number of characters to delete ==>
// if(oldSelectionSize > 0) then deleted number of characters = oldSelectionSize
// else number of characters to delete = oldText.length - newText.length
else if (newSequenceAfterCursor == oldSequenceAfterCursor &&
newSequenceBeforeCursor.startsWith(oldSequenceBeforeCursor))
// handle insert
// inserted string = (newText - oldSequenceBeforeCursor) - oldSequenceAfterCursor
else
// handle replace
// replace info already provided in `onTextChanged()` arguments.
}
}
override fun afterTextChanged(s: Editable?) {
}
}
Essayez Onkeylistener pour EditText
Qu'en est-il du collage du presse-papier?
Un autre problème que j'ai, c'est que dire que j'ai une plage de texte sélectionnée. Dans l'une quelconque des méthodes de TextWatcher, le getSelectionStart et la fin sont toujours le même index, peu importe si je dispose de texte sélectionné ou non.
@jason Vous avez raison: lorsque vous entrez dans le nombre de caractères unique, vous devez être 1, comment avez-vous configuré votre TextWatcher? Et quel niveau de l'API utilisez-vous?
@pskink C'était pour un ancien projet que je n'ai malheureusement plus accès à. Je ne me souviens pas de savoir comment je suis allé installer le Textwatcher. Pardon.