2013-10-23 8 views
8

私はEditTextの中に顔文字を入れようとしています。私はそれを行うことができたし、うまく動作しますが、ソフトキーボードを使用してEditTextからこれらの絵文字を削除しようとすると問題が発生します。 1回の削除ボタンのクリックでこの操作を行うことはできません。新しいImageSpanを挿入するとimageIdが置き換えられますが、アイコンを削除しようとするとイメージを削除する前にすべてのimageId文字を削除する必要があります。EditText SpannableStringBuilderとImageSpanでうまく動作しません。

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

削除ボタンを1回クリックするだけで、絵文字を削除する必要があります。私を手伝ってくれますか?

ありがとうございます!

+0

あなたの顔文字(f.e. 'HashMap')の開始位置と終了位置はどうですか?すべてのキャラクタを削除するには、ハッシュマップ内の顔文字の終わりであるかどうかを確認する必要があります。もしそうなら、全体を削除してください。 (ただし、顔文字の前に変更を加えなければなりません) – longilong

答えて

28

これは、EditText内の顔文字を処理する実装です。この実装ではTextWatcherを使用してEditTextの変更を監視し、一部のテキストが削除されたときに一部の顔文字が削除されたかどうかを検出します。

この実装は、テキスト選択が(削除キーだけでなく)削除されたかどうかを確認することにも注意してください。

テキストを入力するときにテキスト予測に問題が生じないようにするには、エモーティコンテキストをスペースで囲むことをお勧めします(テキスト予測は、隣接するテキストとエモーティコンテキストを結合できます)。

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

"テキストを入力するときにテキスト予測に問題が生じないようにするには、エモーティコンテキストをスペースで囲みます(テキスト予測は、 "この問題の解決策はありますか? –

+0

このソリューションにはありがとうございます。 4年後にはまだ有効であり、有用です(Androidの速さの変化を考慮して)。 – abhiank