2013-10-23 14 views
8

Sto provando a mettere le emoticon all'interno di un EditText. Sono riuscito a farlo e funziona bene, ma ho un problema quando provo a eliminare queste emoticon da EditText utilizzando la tastiera virtuale. Non riesco a fare questa azione con un solo clic del pulsante di eliminazione. Quando inserisco un nuovo ImageSpan, sostituisco un imageId, ma quando provo a eliminare l'icona devo eliminare tutti i caratteri imageId prima di eliminare l'immagine.EditText con SpannableStringBuilder e ImageSpan non funziona correttamente

String fileName = "emoticon1.png"; 
Drawable d = new BitmapDrawable(getResources(), fileName); 
String imageId = "[" + fileName + "]"; 
int cursorPosition = content.getSelectionStart(); 
int end = cursorPosition + imageId.length(); 
content.getText().insert(cursorPosition, imageId); 

SpannableStringBuilder ss = new SpannableStringBuilder(content.getText()); 
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); 
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE); 
ss.setSpan(span, cursorPosition, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
content.setText(ss, TextView.BufferType.SPANNABLE); 
content.setSelection(end); 

Ho bisogno di rimuovere le emoticon con un solo clic del pulsante di eliminazione. Potresti aiutarmi per favore?

Grazie!

+0

che dire del salvataggio della posizione iniziale e finale della tua emoticon (ad esempio "HashMap") ?! su ogni carattere cancellato devi controllare, se la posizione è la fine di una emoticon nella tua hashmap. se è così, cancella il tutto. (ma è necessario occuparsi delle modifiche prima delle emoticon) – longilong

risposta

28

Questa è l'implementazione per gestire le emoticon all'interno di EditText. Questa implementazione utilizza TextWatcher per monitorare le modifiche EditText e rilevare se alcune emoticon sono state rimosse quando si elimina del testo.

Si noti che questa implementazione verifica anche se è stata eliminata una selezione di testo (non solo la chiave di cancellazione).

Per evitare problemi con la predizione del testo quando si digita un testo, si consiglia di racchiudere il testo dell'emoticon con spazi (la predizione del testo può unire il testo dell'emoticon al testo adiacente).

package com.takamori.testapp; 

import java.util.ArrayList; 

import android.app.Activity; 
import android.graphics.drawable.Drawable; 
import android.os.Bundle; 
import android.text.Editable; 
import android.text.Spanned; 
import android.text.TextWatcher; 
import android.text.style.ImageSpan; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.EditText; 

public class MainActivity extends Activity { 

    private EmoticonHandler mEmoticonHandler; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     EditText editor = (EditText) findViewById(R.id.messageEditor); 
     // Create the emoticon handler. 
     mEmoticonHandler = new EmoticonHandler(editor); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.action_insert_emoticon: 
       // WARNING: The emoticon text shall be surrounded by spaces 
       // to avoid issues with text prediction. 
       mEmoticonHandler.insert(" :-) ", R.drawable.smile); 
       return true; 

      default: 
       return super.onOptionsItemSelected(item); 
     } 
    } 

    private static class EmoticonHandler implements TextWatcher { 

     private final EditText mEditor; 
     private final ArrayList<ImageSpan> mEmoticonsToRemove = new ArrayList<ImageSpan>(); 

     public EmoticonHandler(EditText editor) { 
      // Attach the handler to listen for text changes. 
      mEditor = editor; 
      mEditor.addTextChangedListener(this); 
     } 

     public void insert(String emoticon, int resource) { 
      // Create the ImageSpan 
      Drawable drawable = mEditor.getResources().getDrawable(resource); 
      drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 
      ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE); 

      // Get the selected text. 
      int start = mEditor.getSelectionStart(); 
      int end = mEditor.getSelectionEnd(); 
      Editable message = mEditor.getEditableText(); 

      // Insert the emoticon. 
      message.replace(start, end, emoticon); 
      message.setSpan(span, start, start + emoticon.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
     } 

     @Override 
     public void beforeTextChanged(CharSequence text, int start, int count, int after) { 
      // Check if some text will be removed. 
      if (count > 0) { 
       int end = start + count; 
       Editable message = mEditor.getEditableText(); 
       ImageSpan[] list = message.getSpans(start, end, ImageSpan.class); 

       for (ImageSpan span : list) { 
        // Get only the emoticons that are inside of the changed 
        // region. 
        int spanStart = message.getSpanStart(span); 
        int spanEnd = message.getSpanEnd(span); 
        if ((spanStart < end) && (spanEnd > start)) { 
         // Add to remove list 
         mEmoticonsToRemove.add(span); 
        } 
       } 
      } 
     } 

     @Override 
     public void afterTextChanged(Editable text) { 
      Editable message = mEditor.getEditableText(); 

      // Commit the emoticons to be removed. 
      for (ImageSpan span : mEmoticonsToRemove) { 
       int start = message.getSpanStart(span); 
       int end = message.getSpanEnd(span); 

       // Remove the span 
       message.removeSpan(span); 

       // Remove the remaining emoticon text. 
       if (start != end) { 
        message.delete(start, end); 
       } 
      } 
      mEmoticonsToRemove.clear(); 
     } 

     @Override 
     public void onTextChanged(CharSequence text, int start, int before, int count) { 
     } 

    } 
} 
+0

"Per evitare problemi con la predizione del testo quando si digita un testo, si consiglia di racchiudere il testo dell'emoticon con spazi (la predizione del testo può unire il testo dell'emoticon al testo adiacente). " C'è una soluzione migliore a questo problema? –

+0

Grazie mille per questa soluzione. Funziona ancora e utile dopo 4 anni (considerando la velocità con cui Android cambia). – abhiank

Problemi correlati