ImageSpan被截断/对齐不正确

10

我正在使用以下代码实现表情符号:

            builder.setSpan(new ImageSpan(mContext, resId, ImageSpan.ALIGN_BASELINE),
                        start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );

将结果(builder)设置为TextView的文本。如果span被文本包围,即当start > 0且end < length - 1时,它可以正常工作,但是如果周围没有文本,则图像会被裁剪(向上移动)。如何修复?

非常感谢。


记录一下,经过多个小时的尝试解决,不幸的是我认为这是一个 Android 的 bug,我没有找到“真正”的解决方案。最终我像 @plowman 的回答一样,在我的笑脸后面添加了一个空格。我想提一下,Google 的 Hangouts 应用程序也有同样的问题!在消息输入框中添加一个单独的笑脸,然后添加一个空格:笑脸会移动几个像素... - BoD
5个回答

7

继续您的解决方案,这是我自定义的DynamicDrawableSpan,我用它代替ImageSpandraw()方法(从DynamicDrawableSpan复制并修改)确保在与基线对齐之前有文本。

class StickerSpan extends DynamicDrawableSpan {
    Drawable mDrawable;

    public StickerSpan(Context context, Bitmap bitmap) {
        super(DynamicDrawableSpan.ALIGN_BASELINE);
        setBitmap(context, bitmap);
    }

    public void setBitmap(Context context, Bitmap bitmap) {
        mDrawable = new BitmapDrawable(context.getResources(), bitmap);
        int width = mDrawable.getIntrinsicWidth();
        int height = mDrawable.getIntrinsicHeight();
        mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); 
    }

    @Override
    public Drawable getDrawable() {
        return mDrawable;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text,
                     int start, int end, float x, 
                     int top, int y, int bottom, Paint paint) {
        Drawable b = mDrawable;
        canvas.save();

        int transY = bottom - b.getBounds().bottom;
        if (mVerticalAlignment == ALIGN_BASELINE) {
            int textLength = text.length();
            for (int i = 0; i < textLength; i++) {
                if (Character.isLetterOrDigit(text.charAt(i))) {
                    transY -= paint.getFontMetricsInt().descent;
                    break;
                }
            }
        }

        canvas.translate(x, transY);
        b.draw(canvas);
        canvas.restore();
    }
}

4

我也遇到了这个问题,但找不到合适的解决方案。我使用的解决方法如下:

if(message.length() == 1){
//This is a hack to get past an android bug that misaligns ImageSpan's when they are all alone.
    message += " ";
}
builder = new SpannableStringBuilder(message);

3

好的,由于没有其他建议,我暂时采用以下解决方案:如果没有文本,则使用ALIGN_BOTTOM标志,否则使用ALIGN_BASELINE...


还没有更好的答案吗? - Gohan

0

尝试设置可绘制对象的边界。例如:

        BitmapDrawable bmd = new BitmapDrawable(bm);
        int width = bmd.getIntrinsicWidth();
        int height = bmd.getIntrinsicHeight();
        bmd.setBounds(
                0,
                0,
                (int)width,
                (int)height);

        ImageSpan img = new ImageSpan(bmd);
        SpannableString spannableString = new SpannableString(
          someString);
        spannableString.setSpan(
          img, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

这对我没有任何改变。事实上,查看ImageSpan的源代码时,似乎在使用资源ID时已经调用了seBounds,因此这似乎是正常的,这并不能解决问题。 - BoD

0

对我来说,我只是在将它传递给ImageSpan之前没有设置可绘制对象的边界。

您可以通过执行以下操作来设置可绘制对象的“固有边界”:

Drawable drawable = // what you use to create/get your drawable
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
ImageSpan span = new ImageSpan(drawable);

这不仅是错误的(应该是0、0、drawable.getIntrinsicWidth()、drawable.getIntrinsicHeight()),而且即使修复后,对于我来说仍然无法解决问题。 - BoD
啊,你说的参数顺序是对的。我已经修复了打字错误。这确实解决了我的文本被截断的问题。我猜可能有几种情况下文本会被截断。这里的一些答案可能并不适用于每种情况,但有可能对某些人有所帮助,因此我将其保留为一个可能的答案。 - cottonBallPaws

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接