2013-10-23 2 views
8

EditText 안에 이모티콘을 넣으려고합니다. 나는 그것을 할 수 있었지만 잘 작동하지만 소프트 키보드를 사용하는 EditText에서 이모티콘을 삭제하려고 할 때 문제가 발생합니다. 하나의 삭제 버튼 클릭으로이 작업을 수행 할 수 없습니다. 새로운 ImageSpan을 삽입 할 때 imageId를 바꾸지 만 아이콘을 삭제하려고하면 이미지를 삭제하기 전에 모든 imageId 문자를 삭제해야합니다.SpannableStringBuilder 및 ImageSpan이있는 EditText가 제대로 작동하지 않습니다.

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

하나의 삭제 버튼을 클릭하여 이모티콘을 삭제해야합니다. 도와 주실 수 있겠습니까?

감사합니다.

+0

이모티콘의 시작과 끝 위치를 저장하는 방법은 무엇입니까 ('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