原先项目用的github上的一个richtext图文编辑器,但是不太符合我的输入习惯,因此改进了一下,只支持简单的文字和图片输入,其他功能可以自己加,代码如下:
Glide.with(this)
.asBitmap()
.load(it)
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
Dialog.instance.dismiss()
val mWidth: Int = resource.width
val mHeight: Int = resource.height
val matrix = Matrix()
val mEditRealWidth = mEdit.width - mEdit.paddingStart - mEdit.paddingEnd
val scale = mEditRealWidth.toFloat() / mWidth.toFloat()
if (mWidth > mEditRealWidth) {
matrix.postScale(scale, scale)
} else {
matrix.postScale(1F, 1F)
}
val tempUrl = if (scale > 1.25) {
" <img src=\"$it\" > "
} else {
" <img src=\"$it\" > \r\n"
}
val bitmap = Bitmap.createBitmap(resource, 0, 0, mWidth, mHeight, matrix, true)
val imageSpan = ImageSpan(this@InsEditActivity, bitmap)
val spannableString = SpannableString(tempUrl)
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
//点击图片预览
val regex = "<img.*?src=\\\"(.*?)\\\".*?>"
val imageList = Regex(regex).findAll(mEdit.text.toString()).toList()
val position = imageList.map { it.groups[1]?.value }.indexOf(it)
PictureSelector.create(this@InsEditActivity).themeStyle(R.style.picture_white_style).openExternalPreview(position, Environment.getDataDirectory().path + "/jubianshi/",
imageList.map { bean ->
LocalMedia().apply {
cutPath = bean.groups[1]?.value
path = bean.groups[1]?.value
}
})
}
}
spannableString.setSpan(imageSpan, 1, tempUrl.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
spannableString.setSpan(clickableSpan, 1, tempUrl.length - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
val cursorIndex = mEdit.selectionStart
val editableText = mEdit.editableText
if (cursorIndex < 0 || cursorIndex >= mEdit.length()) {
editableText.append(spannableString)
} else {
editableText.insert(cursorIndex, spannableString)
}
mEdit.movementMethod = LinkMovementMethod.getInstance()
}
})
it是图片路径,这是伪代码,没有封装,需要的可以封装,上面是输入的,下面是回显输入:
mEdit.post {
if (info != null) {
Logger.d(info)
val span = SpannableStringBuilder(info)
val regex = "<img.*?src=\\\"(.*?)\\\".*?>"
val imageList = Regex(regex).findAll(info).toList()
imageList.forEachIndexed { index, it ->
val imageUrl = it.groups[1]?.value
val range = it.groups[0]?.range
Glide.with(this)
.asBitmap()
.load(imageUrl)
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val mWidth: Int = resource.width
val mHeight: Int = resource.height
val mEditRealWidth = mEdit.width - mEdit.paddingStart - mEdit.paddingEnd
val matrix = Matrix()
if (mWidth > mEditRealWidth) {
val scale = mEditRealWidth.toFloat() / mWidth.toFloat()
matrix.postScale(scale, scale)
} else {
matrix.postScale(1F, 1F)
}
val bitmap = Bitmap.createBitmap(resource, 0, 0, mWidth, mHeight, matrix, true)
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
//点击图片预览
PictureSelector.create(this@InsEditActivity).themeStyle(R.style.picture_white_style).openExternalPreview(index, Environment.getDataDirectory().path + "/jubianshi/",
imageList.map { bean ->
LocalMedia().apply {
cutPath = bean.groups[1]?.value
path = bean.groups[1]?.value
}
})
}
}
val imageSpan = ImageSpan(this@InsEditActivity, bitmap)
span.setSpan(imageSpan, range!!.first, range.last + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
span.setSpan(clickableSpan, range.first, range.last + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
mEdit.text = span
mEdit.setSelection(mEdit.length())
mEdit.movementMethod = LinkMovementMethod.getInstance()
}
})
}
}
}
info是文本内容,回显编辑的时候,需要post处理一下,不然编辑框的宽度拿不到,仅此记录一下
最后封装成几个扩展函数,供项目调用,kotlin大法好:
/**
* TextView 显示图文信息
*/
fun TextView.setImageText(text: String) {
post {
this.text = Html.fromHtml(text, Html.ImageGetter { source ->
val mDrawable = LevelListDrawable()
Glide.with(this).asBitmap().load(source).into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val mWidth: Int
val mHeight: Int
val mTextRealWidth = width - paddingStart - paddingEnd
if (resource.width > mTextRealWidth) {
mWidth = mTextRealWidth
mHeight = (resource.height / resource.width) * mTextRealWidth
} else {
mWidth = resource.width
mHeight = resource.height
}
val drawable = BitmapDrawable(resource)
mDrawable.addLevel(1, 1, drawable)
mDrawable.setBounds(0, 0, mWidth, mHeight)
mDrawable.level = 1
invalidate()
setText(getText())
}
})
mDrawable
}, null)
}
}
调用:
text?.let { mTextView.setImageText(it) }
Editext的,
/**
* Edittext 显示图文信息
*/
fun EditText.setImageText(text: String) {
post {
val span = SpannableStringBuilder(text)
val regex = "<img.*?src=\"(.*?)\".*?>"
val imageList = Regex(regex).findAll(text).toList()
imageList.forEachIndexed { index, it ->
val imageUrl = it.groups[1]?.value
val range = it.groups[0]?.range
Glide.with(this)
.asBitmap()
.load(imageUrl)
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val mWidth: Int = resource.width
val mHeight: Int = resource.height
val mEditRealWidth = width - paddingStart - paddingEnd
val matrix = Matrix()
if (mWidth > mEditRealWidth) {
val scale = mEditRealWidth.toFloat() / mWidth.toFloat()
matrix.postScale(scale, scale)
} else {
matrix.postScale(1F, 1F)
}
val bitmap = Bitmap.createBitmap(resource, 0, 0, mWidth, mHeight, matrix, true)
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
//点击图片预览
PictureSelector.create(context as Activity).themeStyle(R.style.picture_white_style).openExternalPreview(index, Environment.getDataDirectory().path + "/jubianshi/",
imageList.map { bean ->
LocalMedia().apply {
cutPath = bean.groups[1]?.value
path = bean.groups[1]?.value
}
})
}
}
val imageSpan = ImageSpan(context, bitmap)
span.setSpan(imageSpan, range!!.first, range.last + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
span.setSpan(clickableSpan, range.first, range.last + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setText(span)
setSelection(length())
movementMethod = LinkMovementMethod.getInstance()
}
})
}
}
}
调用:
text?.let { mEdit.post { mEdit.setImageText(it) } }
编辑Edittext:
/**
* EditText 编辑图文信息
*/
fun EditText.appendImageText(url:String, onPictureReady: (() -> Unit)? =null){
Glide.with(this)
.asBitmap()
.load(url)
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
onPictureReady?.invoke()
val mWidth: Int = resource.width
val mHeight: Int = resource.height
val matrix = Matrix()
val mEditRealWidth = width - paddingStart - paddingEnd
val scale = mEditRealWidth.toFloat() / mWidth.toFloat()
if (mWidth > mEditRealWidth) {
matrix.postScale(scale, scale)
} else {
matrix.postScale(1F, 1F)
}
val tempUrl = if (scale > 1.25) {
" <img src=\"$url\" > "
} else {
" <img src=\"$url\" > \r\n"
}
val bitmap = Bitmap.createBitmap(resource, 0, 0, mWidth, mHeight, matrix, true)
val imageSpan = ImageSpan(context, bitmap)
val spannableString = SpannableString(tempUrl)
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
val regex = "<img.*?src=\"(.*?)\".*?>"
val imageList = Regex(regex).findAll(text.toString()).toList()
val position = imageList.map { it.groups[1]?.value }.indexOf(url)
PictureSelector.create(context as Activity).themeStyle(R.style.picture_white_style).openExternalPreview(position, Environment.getDataDirectory().path + "/jubianshi/",
imageList.map { bean ->
LocalMedia().apply {
cutPath = bean.groups[1]?.value
path = bean.groups[1]?.value
}
})
}
}
spannableString.setSpan(imageSpan, 1, tempUrl.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
spannableString.setSpan(clickableSpan, 1, tempUrl.length - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
val cursorIndex = selectionStart
val editableText = editableText
if (cursorIndex < 0 || cursorIndex >= length()) {
editableText.append(spannableString)
} else {
editableText.insert(cursorIndex, spannableString)
}
movementMethod = LinkMovementMethod.getInstance()
}
})
}
调用:
mEdit.appendImageText(url) {Dialog.instance.dismiss()}