Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ImageSpan on EditText (smileys). With SwiftKey Keyboard doesnt work

I am doing a simple chat application and i want to show smileys on edittext while writing the message.

I have this to identify wich characters will be subsituted by an Image throught an ImageSpan (this is called only when an smileys character is inserted on EditText):

for (index = start; index < start+num_chars; index++) {
        if (index + 1 > editable.length())
            continue;  
          if(emoticons.containsKey(editable.subSequence(index, index + 1).toString())){
            int length=1; 

            Drawable drawable = context.getResources().getDrawable(emoticons.get(editable.subSequence(index, index + 1).toString()));
            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();


            int size=Utils.GetDipsFromPixel(context, (int)(textSize*1.3));

            Drawable d = new BitmapDrawable(Bitmap.createScaledBitmap(bitmap, size, size, true));
            int dWidth = d.getIntrinsicWidth();
            int dHeight = d.getIntrinsicHeight();

            d.setBounds(0 , -dHeight, dWidth, 0);
            ImageSpan span;
            span = new ImageSpan(d,ImageSpan.ALIGN_BASELINE);
            editable.setSpan(span, index, index + length,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            index += length - 1;
          }

      }

I am using SPAN_EXCLUSIVE_EXCLUSIVE tag to set the span, but i have problems with swiftkey keyboard because when i insert an smiley in the edittext, everything i write just after the imageSpan it keeps below the image (like SPAN_EXCLUSIVE_INCLUSIVE). With the Android default keyboard i havent this problem.

I only want whatsapp application same behaviour whit smileys on EditText.

Any suggestions? Any change i have to do to my code?

EDIT: "editable" variable is passed to the method. It is txtMessage.getText() value where txtMessage is an EditText.

Thanks!

EDIT: Only Span one portion of code! This works good in multiline! I think the problem was in using Drawable->Bitmap->ResizedBitmap->Drawable.

public static final HashMap<String, Integer> emoticons = new HashMap();
static {
    emoticons.put("\ue415", R.drawable.e415);
    emoticons.put("\ue056", R.drawable.e056);
    emoticons.put("\ue057", R.drawable.e057);
...
public static Spannable getSmiledText(Context context, Spannable editable,
        int start, int num_chars, float textSize) {

    int index;
    for (index = start; index < start + num_chars; index++) {
        if (index + 1 > editable.length())
            continue;
        if (EmojiLayout.emoticons.containsKey(editable.subSequence(index,
                index + 1).toString())) {
            int length = 1;

            Bitmap smiley = BitmapFactory.decodeResource(context.getResources(), ((Integer) EmojiLayout.emoticons.get(editable.subSequence(index,
                    index + 1).toString())));
            int size = Utils.GetDipsFromPixel(context,
            (int) (textSize * 1.37));

            Bitmap scaledbmp=Bitmap.createScaledBitmap(
                    smiley, size, size, false);
            ImageSpan span;
            span = new ImageSpan(scaledbmp);
            Log.d("EmojiLayout", "Index: " + String.valueOf(index) + "To: "
                    + String.valueOf(index + length));
            editable.setSpan(span, index, index + length,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            index += length - 1;
        }
    }
    return editable;
}
like image 559
Igor Avatar asked Jul 15 '12 17:07

Igor


2 Answers

Use this one ::

    public static CharSequence addSmileySpans(Context ch, CharSequence your_recieved_message)
{
    //smilyRegexMap = new HashMap<Integer, String>();

private static final HashMap<String, Integer> smilyRegexMap = new HashMap<String, Integer>();
smilyRegexMap.put( ">:-\\(" , R.drawable.fb_grumpy);
        smilyRegexMap.put( ">:\\(" , R.drawable.fb_grumpy);
        smilyRegexMap.put( ">:-O" , R.drawable.fb_upset);
        smilyRegexMap.put( ":-\\)" , R.drawable.fb_smile);
        smilyRegexMap.put( ":\\)",R.drawable.fb_smile);
        smilyRegexMap.put( ":-\\]" , R.drawable.fb_smile);
        smilyRegexMap.put( ":-\\(", R.drawable.fb_frown);




    System.out.println("==In Spannable Function..........");
    SpannableStringBuilder builder = new SpannableStringBuilder(your_recieved_message);

    System.out.println("==================Size of Smily  : "+ smilyRegexMap.size());

    @SuppressWarnings("rawtypes")
    Iterator it = smilyRegexMap.entrySet().iterator();
    while (it.hasNext()) {
        @SuppressWarnings("rawtypes")
        Map.Entry pairs = (Map.Entry) it.next();




        Pattern mPattern = Pattern.compile((String) pairs.getKey(),Pattern.CASE_INSENSITIVE);
        Matcher matcher = mPattern.matcher(your_recieved_message);

        while (matcher.find()) {

                Bitmap smiley = BitmapFactory.decodeResource(ch.getResources(), ((Integer) pairs.getValue()));
                Object[] spans = builder.getSpans(matcher.start(), matcher.end(), ImageSpan.class);
                if (spans == null || spans.length == 0) {
                    builder.setSpan(new ImageSpan(smiley), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
        }
    }
    return builder;
}
like image 123
Gautam Vasoya Avatar answered Oct 16 '22 23:10

Gautam Vasoya


You have just to build a Spannable text using ImageSpan and then setText the Spannable to TextView or EditText as CommonsWare suggested in this post. You can also try to use A-IV's solution:

private static final HashMap<String, Integer> emoticons = new HashMap();
    static {
        emoticons.put(":*", R.drawable.emo_im_kiss);
        emoticons.put(":-D", R.drawable.emo_im_glad);
        emoticons.put(":)", R.drawable.emo_im_happy);
        emoticons.put(":-(", R.drawable.emo_im_sad);
        ...
    }

    public static Spannable getSmiledText(Context context, String text) {

    SpannableStringBuilder builder = new SpannableStringBuilder(text);
    int index;

    for (index = 0; index < builder.length(); index++) {
        for (Entry<String, Integer> entry : emoticons.entrySet()) {
            int length = entry.getKey().length();
            if (index + length > builder.length())
                continue;
            if (builder.subSequence(index, index + length).toString().equals(entry.getKey())) {
                builder.setSpan(new ImageSpan(context, entry.getValue()), index, index + length,
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                index += length - 1;
                break;
            }
    }
    }
    return builder;
    }
like image 41
K_Anas Avatar answered Oct 16 '22 23:10

K_Anas