【问题标题】:ImageSpan on EditText (smileys). With SwiftKey Keyboard doesnt workEditText 上的 ImageSpan(笑脸)。使用 SwiftKey 键盘不起作用
【发布时间】:2012-07-15 17:24:58
【问题描述】:

我正在做一个简单的聊天应用程序,我想在编写消息时在 edittext 上显示笑脸。

我有这个来确定哪些字符将通过 ImageSpan 被图像替换(仅当在 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;
          }

      }

我正在使用 SPAN_EXCLUSIVE_EXCLUSIVE 标签来设置跨度,但是我在使用 swiftkey 键盘时遇到问题,因为当我在编辑文本中插入笑脸时,我在 imageSpan 之后写的所有内容都会保留在图像下方(如 SPAN_EXCLUSIVE_INCLUSIVE)。使用Android默认键盘我没有这个问题。

我只希望 whatsapp 应用程序与 EditText 上的表情相同。

有什么建议吗?我必须对我的代码做任何更改吗?

编辑:“可编辑”变量被传递给方法。它是 txtMessage.getText() 值,其中 txtMessage 是 EditText。

谢谢!

编辑:只跨越一部分代码!这在多行中效果很好!我认为问题在于使用 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;
}

【问题讨论】:

  • 将此缺陷邮寄给开发人员,看看他们怎么说..

标签: android android-edittext spannable


【解决方案1】:

使用这个 ::

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

【讨论】:

  • 耶!!!!我对 Swiftkey 有同样的问题,但是通过这种方法,您已经解决了带有笑脸的列表视图项目上的自动换行的其他问题!!!!现在我只需要提高滚动速度,因为我有 470 个笑脸!有什么提高滚动速度的建议吗?
  • 我已将您的代码编辑为仅跨越字符串的一部分。我已经在第一条消息中发布了它
  • 我正在使用对话框视图来显示笑脸。我已经用图像和代码添加了新的答案。可能是这个帮助你...
【解决方案2】:

您只需要使用 ImageSpan 构建一个 Spannable 文本,然后将 Spannable 设置为 TextView 或 EditText,就像 CommonsWare 在此 post 中建议的那样。也可以尝试使用A-IV's解决方案:

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

【讨论】:

  • 我已经尝试过这个解决方案,但我的问题是我每次在 EditText 上插入笑脸时都会这样做,我只想更改新插入的笑脸字符。我必须将 txtMessage.getText() (Spannable) 传递给该方法,因此我只能更改新字符。如果我每次插入笑脸时都必须检查所有字符,那么您发送的方法是无效的。
  • 我试图将 ImageSpan 设置为 SpannableStringBuilder,结果是一样的......使用 SwiftKey 键盘我不能在 ImageSpan 之后写,因为所有字符都被 ImageSpan 隐藏......: -(
【解决方案3】:

试试这个方法,希望能帮助你解决问题。

    private static LinkedHashMap<String,Integer> emojisHashMap;

    public static LinkedHashMap<String, Integer> getEmojisHashMap() {
        if (emojisHashMap == null || emojisHashMap.size() == 0) {
            emojisHashMap = new LinkedHashMap<String, Integer>();

            emojisHashMap.put(":=q", R.drawable.smiley1);
            emojisHashMap.put(":=w", R.drawable.smiley2);
            emojisHashMap.put(":=e", R.drawable.smiley3);
            emojisHashMap.put(":=r", R.drawable.smiley4);

            return emojisHashMap;
        } else {
            return emojisHashMap;
        }

    }

    public Spannable getSmiledText(CharSequence text) {
        SpannableStringBuilder builder;

        try {
            builder = (SpannableStringBuilder) text;
        }catch (Exception e){
            builder = new SpannableStringBuilder(text);
        }
        if (getEmojisHashMap().size() > 0) {
            int index;
            for (index = 0; index < builder.length(); index++) {
                if (Character.toString(builder.charAt(index)).equals(":")) {
                    for (Map.Entry<String, Integer> entry : getEmojisHashMap().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(getContext(), entry.getValue()), index, index + length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                            index += length - 1;
                            break;
                        }
                    }
                }
            }
        }
        return builder;
    }

【讨论】:

    【解决方案4】:

    在笑脸的 XML 文件中放置图像按钮

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#dddddd"
        android:padding="10dp" >
    
        <ImageButton
            android:id="@+id/btn_smile"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_smile" />
    
        <ImageButton
            android:id="@+id/btn_kiss"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_kiss" />
    
        <ImageButton
            android:id="@+id/btn_wink"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_wink" />
    
        <ImageButton
            android:id="@+id/btn_cry"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_cry" />
    
        <ImageButton
            android:id="@+id/btn_grumpy"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_grumpy" />
    
        <ImageButton
            android:id="@+id/btn_upset"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_upset" />
    </LinearLayout>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#dddddd"
        android:padding="10dp" >
    
        <ImageButton
            android:id="@+id/btn_frown"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_frown" />
    
        <ImageButton
            android:id="@+id/btn_tougn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_tounge" />
    
        <ImageButton
            android:id="@+id/btn_grin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_grin" />
    
        <ImageButton
            android:id="@+id/btn_gasp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_gasp" />
    
        <ImageButton
            android:id="@+id/btn_glasses"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_glasses" />
    
        <ImageButton
            android:id="@+id/btn_unsure"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:padding="10dp"
            android:src="@drawable/fb_unsure" />
    </LinearLayout>
    </LinearLayout>
    

    //============================================== ===========

    在 Dialog Class 中输入这段代码

        private class SmileyMenu extends Dialog implements android.view.View.OnClickListener{
    
        private Chat cht;
        Context con;
        public String MyStatus1="";
        public SmileyMenu(Chat cht) {
            super(cht);
            this.con = cht;
            this.cht = cht;
        }
    
    
    
        @Override
        protected void onStart() {
            // TODO Auto-generated method stub
            super.onStart();
    
    
            setTitle("Select Smileys :");
    
            setContentView(R.layout.smily_menu);
    
            ImageButton btnSmile = (ImageButton)findViewById(R.id.btn_smile);
            ImageButton btnkiss = (ImageButton)findViewById(R.id.btn_kiss);
            ImageButton btnwink = (ImageButton)findViewById(R.id.btn_wink);
            ImageButton btncry = (ImageButton)findViewById(R.id.btn_cry);
            ImageButton btngrupy = (ImageButton)findViewById(R.id.btn_grumpy);
            ImageButton btnupset = (ImageButton)findViewById(R.id.btn_upset);
            ImageButton btnfrown = (ImageButton)findViewById(R.id.btn_frown);
            ImageButton btngrin = (ImageButton)findViewById(R.id.btn_grin);
            ImageButton btngasp = (ImageButton)findViewById(R.id.btn_gasp);
            ImageButton btnglass = (ImageButton)findViewById(R.id.btn_glasses);
            ImageButton btnunsure = (ImageButton)findViewById(R.id.btn_unsure);
            ImageButton btndevil = (ImageButton)findViewById(R.id.btn_devil);
            ImageButton btnheart = (ImageButton)findViewById(R.id.btn_heart);
            ImageButton btnpacman = (ImageButton)findViewById(R.id.btn_pacman);
            ImageButton btn42 = (ImageButton)findViewById(R.id.btn_42);
    
    
            btnSmile.setOnClickListener(this);
            btnkiss.setOnClickListener(this);
            btnwink.setOnClickListener(this);
            btncry.setOnClickListener(this);
            btngrupy.setOnClickListener(this);
            btnupset.setOnClickListener(this);
            btnfrown.setOnClickListener(this);
            btngrin.setOnClickListener(this);
            btngasp.setOnClickListener(this);
            btnglass.setOnClickListener(this);
            btnunsure.setOnClickListener(this);
            btndevil.setOnClickListener(this);
            btnheart.setOnClickListener(this);
            btnpacman.setOnClickListener(this);
            btn42.setOnClickListener(this);
    
    
    
    
        }
    
    
    
        @Override
        public void onClick(View v) {
    
    
            switch (v.getId()) {
    
            case R.id.btn_smile:
                cht.setMyText(":-)");
                break;
    
            case R.id.btn_kiss:
                cht.setMyText(":-*");
                break;
    
            case R.id.btn_wink:
                cht.setMyText(";-)");
                break;
    
            case R.id.btn_cry:
                cht.setMyText(":'(");
                break;
    
            case R.id.btn_grumpy:
                cht.setMyText(">:-(");
                break;
    
            case R.id.btn_upset:
                cht.setMyText(">:-O");
                break;
    
            case R.id.btn_frown:
                cht.setMyText(":-(");
                break;
    
            case R.id.btn_tougn:
                cht.setMyText(":-p");
                break;
    
            case R.id.btn_grin:
                cht.setMyText(":-D");
                break;
    
            case R.id.btn_gasp:
                cht.setMyText(":-O");
                break;
    
            case R.id.btn_glasses:
                cht.setMyText("8-)");
                break;
    
            case R.id.btn_unsure:
                cht.setMyText(":-/");
                break;
    
            case R.id.btn_devil:
                cht.setMyText("3:-)");
                break;
    
            case R.id.btn_heart:
                cht.setMyText("<3");
                break;
    
            case R.id.btn_pacman:
                cht.setMyText(":v");
                break;
    
            case R.id.btn_42:
                cht.setMyText(":42:");
                break;
    
            default:
                Toast.makeText(con, "Sorryyyyyy", Toast.LENGTH_SHORT).show();
                break;
            }
    
            dismiss();
        }
    }
    

    //===================

    运行时笑脸菜单的点击按钮图片

    ================================================ ======

    试试这个可能对你有帮助..祝你好运..

    【讨论】:

    • 我的问题是要提高消息列表视图的速度,因为每次显示消息时列表适配器都必须找到笑脸。我已经实现了某种缓存,但用户可以在应用程序配置中更改字体大小,我重新计算笑脸大小,使它们与文本具有相同的高度。还是谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 2012-05-25
    • 1970-01-01
    • 2020-03-16
    相关资源
    最近更新 更多