ImageSpan is cut off / incorrectly aligned
I am imple开发者_Python百科menting emoticons using the following code:
builder.setSpan(new ImageSpan(mContext, resId, ImageSpan.ALIGN_BASELINE),
start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
The result (builder) is set as text to a TextView. It works just fine if the span is surrounded by text, i.e. when the start > 0 and the end < length - 1, but the image is cut off (shifted up) if there is no text around it. how do I fix that?
Thanks a lot.
Following on to your solution, here is my custom DynamicDrawableSpan
I use in place of ImageSpan
. The draw()
method (copied from DynamicDrawableSpan and modified) ensures that there is text before aligning with the baseline.
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();
}
}
I also ran into this issue and could not find a proper solution. The workaround I used looks like this:
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);
Well, as there are no suggestions, I am going to use the following solution in the meantime: if there is no text - use ALIGN_BOTTOM flag, otherwise use ALIGN_BASELINE...
Try set the bound of the drawable. For example:
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);
For me I just hadn't set the bounds of the drawable before I passed it to the ImageSpan.
You can set the "intrinsic bounds" of the drawable by doing something like:
Drawable drawable = // what you use to create/get your drawable
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
ImageSpan span = new ImageSpan(drawable);
精彩评论