700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > android富文本图片自适应 Android Span富文本图文混排 - ImageSpan(图文垂直居中)...

android富文本图片自适应 Android Span富文本图文混排 - ImageSpan(图文垂直居中)...

时间:2020-01-26 09:43:07

相关推荐

android富文本图片自适应 Android Span富文本图文混排 - ImageSpan(图文垂直居中)...

###为文字实现很丰富的特殊效果,当然少不了图文混排

so... 直接上效果(有直接使用和自定义垂直居中效果)

##1 ImageSpan:

ImageSpan(context, resourceId,ImageSpan.ALIGN_CENTER)//默认为ALIGN_BOTTOM

//ALIGN_BOTTOM,ALIGN_BASELINE,ALIGN_CENTER

#使用

sb.insert(index, TEXT_SPACE)//占位,该位置用来实现图片

sb.setSpan(

ImageSpan(context, resourceId,ImageSpan.ALIGN_CENTER),

index,

index + TEXT_SPACE.length,

Spanned.SPAN_INCLUSIVE_EXCLUSIVE

)

cc:上图中前半部分,使用ImageSpan来实现的,会发现如果是单行使用了属性DynamicDrawableSpan.ALIGN_CENTER,且添加显示的图片高度小于或等于文字高度时,该属性可以很好的起作用,但是如果是多行,其拼接后的效果有点...(具体可看看它源码实现,下面贴上DynamicDrawableSpan)

##2 DynamicDrawableSpan源码主要的两个方法:(供参考)

@Override

public int getSize(@NonNull Paint paint, CharSequence text,

@IntRange(from = 0) int start, @IntRange(from = 0) int end,

@Nullable Paint.FontMetricsInt fm) {

Drawable d = getCachedDrawable();

Rect rect = d.getBounds();

if (fm != null) {

fm.ascent = -rect.bottom;

fm.descent = 0;

fm.top = fm.ascent;

fm.bottom = 0;

}

return rect.right;

}

@Override

public void draw(@NonNull Canvas canvas, CharSequence text,

@IntRange(from = 0) int start, @IntRange(from = 0) int end, float x,

int top, int y, int bottom, @NonNull Paint paint) {

Drawable b = getCachedDrawable();

canvas.save();

int transY = bottom - b.getBounds().bottom;

if (mVerticalAlignment == ALIGN_BASELINE) {

transY -= paint.getFontMetricsInt().descent;

} else if (mVerticalAlignment == ALIGN_CENTER) {

transY = (bottom - top) / 2 - b.getBounds().height() / 2;

}

canvas.translate(x, transY);

b.draw(canvas);

canvas.restore();

}

##3图文混排,绝大多数需求实现是需要和文字对齐(图文垂直居中)

需要重写上面两个方法来实现自定义CenterImageSpan

class CenterImageSpan(context: Context, mResourceId: Int) :

ImageSpan(context, mResourceId, DynamicDrawableSpan.ALIGN_CENTER) {

var isSmallImage = false

override fun getSize(

paint: Paint,

text: CharSequence,

start: Int,

end: Int,

fm: Paint.FontMetricsInt?

): Int {

val drawable = drawable

val rect = drawable.bounds

if (fm != null) {

val fmPaint = paint.fontMetricsInt

val fontH = fmPaint.descent - fmPaint.ascent //文字行的高度(具体字符顶部到底部的真实高度)

val imageH = rect.bottom - rect.top // 图片的高度

//如果图片的高度 <= 文本的高度,可以直接使用 ImageSpan.ALIGN_CENTER 来实现垂直居中

//即将当前图片所在行的图片相对于文字的高度居中,但仅支持单行有效

if (imageH > fontH) {

isSmallImage = false

//这里直接将文字行的高度调整至Image高度对应的top和bottom,即将当前图片所在行的文字相对于图片的高度居中

fm.ascent = fmPaint.ascent - (imageH - fontH) / 2

fm.top = fmPaint.ascent - (imageH - fontH) / 2

fm.bottom = fmPaint.descent + (imageH - fontH) / 2

fm.descent = fmPaint.descent + (imageH - fontH) / 2

} else {

//如果是小图片,就直接使用DynamicDrawableSpan.getSize()里面但方法

isSmallImage = true

fm.ascent = -rect.bottom

fm.descent = 0

fm.top = fm.ascent

fm.bottom = 0

}

}

return rect.right

}

override fun draw(

canvas: Canvas,

text: CharSequence,

start: Int,

end: Int,

x: Float,

top: Int,

y: Int,

bottom: Int,

paint: Paint

) {

// 这里说明下:如果图片高度大于文字高度,通过重写getSize,使当前图片所在行的文字相对于图片的高度居中,可以直接用DynamicDrawableSpan.draw方法

val b = drawable

canvas.save()

var transY = bottom - b.bounds.bottom

if (isSmallImage) {

//但是对于多行使用小图标时,需要我们稍加改变使其居中

transY -= ((bottom - top) / 2 - b.bounds.height() / 2)

}

canvas.translate(x, transY.toFloat())

b.draw(canvas)

canvas.restore()

}

}

使用:

sb.insert(index, TEXT_SPACE)//占位,该位置用来实现图片

sb.setSpan(

CenterImageSpan(context, resourceId),//CenterImageSpan > ImageSpan

index,

index + TEXT_SPACE.length,

Spanned.SPAN_INCLUSIVE_EXCLUSIVE

)

附上Activity示例:

private const val TEXT_CONTENT =

"Today is Jul 25th Today is Jul 25thToday is Jul 25thToday is Jul 25th"

private const val TEXT_SPACE = "占位"

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_image_span)

text_type_image_size_center.text = displaySpannableSuperWithPic()

}

private fun displaySpannableSuperWithPic(): Spannable {

val sb = SpannableStringBuilder(TEXT_CONTENT)

sb.insert(37, TEXT_SPACE)//占位

var image = CenterImageSpan(this, R.drawable.ic_launcher_background)

val index = sb.indexOf(TEXT_SPACE)

sb.setSpan(

image,

index,

index + TEXT_SPACE.length,

Spanned.SPAN_INCLUSIVE_EXCLUSIVE

)

return sb

}

cc:开头的效果中后半部分,使用CenterImageSpan来实现,具体说明已贴在其中,欢迎回复讨论...

Spanable相关使用...

本文地址:/qq_20613731/article/details/107502304

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。