7
votes

Détecter les modifications dans editext (Textwatcher inefficace)

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:

Public Void OntextChanged (Chaluquerence S, INT START, INT avant, int compte) CODE> P>

Dites que j'ai déjà le texte "Jean" dans le Éditer le texte. Si vous appuyez sur une autre touche, "E", 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>

Donc, donc je m'attendrais à:

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


5 commentaires

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.


4 Réponses :


12
votes

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;
    }

    ...
}


3 commentaires

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.



0
votes

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: xxx


0 commentaires

1
votes

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?) { }


0 commentaires

0
votes

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>

  1. Old taille de la sélection li>
  2. Ancien texte li>
  3. Séquence de texte Ancien avant le curseur / sélection. Li>
  4. Séquence de texte Ancien après le curseur / sélection. Li> Ol>

    Au-dessus de 4 choses sont mises à jour au cours de la beforeTextChanged () code> rappel. P>

    au cours du OnTextChanged () code> rappel, on calcule après deux choses - p>

    1. Nouvelle séquence de texte avant le curseur / sélection. Li>
    2. Nouvelle séquence de texte après le curseur / sélection. Li> Ol>

      cas suivants sont possibles - p>

      Cas 1 strong> 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>

      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 ( | code> représente le curseur) p>

      séquence de texte Ancien avant le curseur / sélection = Bonjour wo code> p>

      séquence de texte Ancien après le curseur / sélection = RLD code> p>

      ancienne taille de la sélection = 0 code> p>

      le nouveau texte = Bonjour wo | ld ( | code> représente le curseur) p>

      Nouvelle séquence de texte avant le curseur / sélection = Bonjour wo code> p>

      Nouvelle séquence de texte après le curseur / sélection = ld code> p >

      Il est clair que cela est un cas de suppression vers l'avant par 1 caractère. p>

      cas n ° 2 strong> 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>

      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 ( | code> représente le curseur) p>

      séquence de texte Ancien avant le curseur / sélection = Bonjour wo code> p>

      séquence de texte Ancien après le curseur / sélection = RLD code> p>

      ancienne taille de la sélection = 0 code> p>

      le nouveau texte = Bonjour w | DNR ( | code> représente le curseur) p>

      Nouvelle séquence de texte avant le curseur / sélection = Bonjour w code> p>

      Nouvelle séquence de texte après le curseur / sélection = RLD code> p >

      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>

      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>

      est un boîtier d'insert. La chaîne d'insertion exacte peut être calculée en supprimant le 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>

      Exemple -. P>

      Old text = Bonjour wo | DNR ( | code> représente le curseur) p>

      séquence de texte ancien avant le curseur / sélection = Bonjour wo code> p> séquence de texte Ancien après le curseur / sélection = RLD code> p>

      ancienne taille de la sélection = 0 code> p>

      le nouveau texte = Bonjour wo123 | DNR ( | code> représente le curseur) p>

      Nouvelle séquence de texte avant le curseur / sélection = Bonjour wo123 code> p>

      Nouvelle séquence de texte après le curseur / sélection = RLD code> p>

      Il est clair que ceci est un cas d'insert et la chaîne inséré est 123 code>. p>

      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 OnTextChanged code> rappel p>

      Voici le code pour l'algorithme ci-dessus -. 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?) {
              }
          }
      
      


0 commentaires