Java 如何通过Html.fromHtml(text)更改在文本视图中加载的默认图像(占位符)
我的应用程序上有一个新闻部分,从我的网站加载一些新闻,其中一些包含图片,所以我从互联网加载它们。但是,虽然没有加载图像,但只有在加载图像时才会出现一个绿色正方形 未加载图像: 然后加载图像: 我想让那个绿色的正方形隐形 为了简单起见,让我们假设我甚至不加载图像,只想使绿色的方块不可见,而不使用空文本替换图像标记 代码:Java 如何通过Html.fromHtml(text)更改在文本视图中加载的默认图像(占位符),java,android,html,kotlin,spanned,Java,Android,Html,Kotlin,Spanned,我的应用程序上有一个新闻部分,从我的网站加载一些新闻,其中一些包含图片,所以我从互联网加载它们。但是,虽然没有加载图像,但只有在加载图像时才会出现一个绿色正方形 未加载图像: 然后加载图像: 我想让那个绿色的正方形隐形 为了简单起见,让我们假设我甚至不加载图像,只想使绿色的方块不可见,而不使用空文本替换图像标记 代码: val exampleText=“Example示例” tv_body.text=fromHtml(示例文本) 乐趣来自html(html:String?):跨越?{ 返回i
val exampleText=“Example
示例”
tv_body.text=fromHtml(示例文本)
乐趣来自html(html:String?):跨越?{
返回if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.N){
Html.fromHtml(Html,Html.FROM\u Html\u MODE\u LEGACY);
}否则{
fromHtml(Html);
}
}
有没有一种方法可以在不做任何恶作剧的情况下更改默认图像
我的解决方法:
为了解决这个问题,我采用了一个定制的fromHtml函数
private var drawable: Drawable? = null
fun fromHtml(context: Activity?, tv: TextView?, text: String?) {
if (TextUtils.isEmpty(text) || context == null || tv == null) return
//Replace all image tags with an empty text
val noImageText = text!!.replace("<img.*?>".toRegex(), "")
//Set the textview text with the imageless html
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
tv.text = Html.fromHtml(noImageText, Html.FROM_HTML_MODE_LEGACY)
} else {
tv.text = Html.fromHtml(noImageText)
}
Thread {
//Creating the imageGetter
val imageGetter = ImageGetter { url ->
drawable = getImageFromNetwork(url)
if (drawable != null) {
var w = drawable!!.intrinsicWidth
var h = drawable!!.intrinsicHeight
// Scaling the width and height
if (w < h && h > 0) {
val scale = 400.0f / h
w = (scale * w).toInt()
h = (scale * h).toInt()
} else if (w > h && w > 0) {
val scale = 1000.0f / w
w = (scale * w).toInt()
h = (scale * h).toInt()
}
drawable!!.setBounds(0, 0, w, h)
} else if (drawable == null) {
return@ImageGetter null
}
drawable!!
}
val textWithImage = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY, imageGetter, null)
} else {
Html.fromHtml(text, imageGetter, null)
}
// update runOnUiThread and change the textview text from the textWithoutImage to the textWithImage
context.runOnUiThread(Runnable { tv.text = textWithImage })
}.start()
}
private fun getImageFromNetwork(imageUrl: String): Drawable? {
var myFileUrl: URL? = null
var drawable: Drawable? = null
try {
myFileUrl = URL(imageUrl)
val conn = myFileUrl
.openConnection() as HttpURLConnection
conn.doInput = true
conn.connect()
val `is` = conn.inputStream
drawable = Drawable.createFromStream(`is`, null)
`is`.close()
} catch (e: Exception) {
e.printStackTrace()
return null
}
return drawable
}
private var drawable:drawable?=无效的
来自HTML的乐趣(上下文:活动?、电视:文本视图?、文本:字符串?){
if(TextUtils.isEmpty(text)| | context==null | | tv==null)返回
//用空文本替换所有图像标记
val noImageText=text!!.replace(“
示例”
fromHtml((活动作为新闻活动?),tv_body,exampleText)
它首先表明:
(因为我用空文本替换了图像标记)
然后,当图像加载时,它显示以下内容:
我仍然认为制作无图像文本与其说是一个合适的解决方案,不如说是一个解决方案,我认为可能有一些更简单的方法,比如:
val exampleText = "Example <br> <img src=\"https://www.w3schools.com/images/w3schools_green.jpg\" alt=\"W3Schools.com\"> <br> Example"
fromHtml((activity as NewsActivity?), tv_body, exampleText)
@可拉伸/不可见
因此,绿色方块将是一个不可见的可绘制图像,我不需要设置两次html文本,尽管我真的不知道如何更改默认的占位符图像。我想我会坚持解决方法,您看到的占位符图像来自com.android.internal.R.drawable.unknown\u图像,如果ImageGetter返回n,则设置它从Html中的函数 因此,在原始代码中的某个地方,您正在从ImageGetter返回一个null。因为未知的图像可绘制是硬编码的,所以无法通过样式或主题来处理它。如果您想解决这个问题,您可以使用反射做些事情 与其在下载的图像可用之前或之后操作HTML文本,我建议包装从ImageGetter返回的drawable,以便在不直接操作文本的情况下更改图像当它可用时,法师 下面是一些显示此技术的示例代码。占位符是一个可以显示的可绘制文件,但它可以是您想要的任何内容。我使用一个可见的可绘制文件(Html.java中的默认值,但带有一个“E”表示“empty”。)来表示它确实显示并且可以更改。您可以提供一个透明的可绘制文件,以便不显示任何内容 MainActivity.kt
private static void startImg(Editable text, Attributes attributes, Html.ImageGetter img) {
...
if (d == null) {
d = Resources.getSystem().
getDrawable(com.android.internal.R.drawable.unknown_image);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
}
....
}
class MainActivity:AppCompatActivity(){
私有lateinit变量tvBody:TextView
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvBody=findviewbyd(R.id.tv\u body)
val示例文本=
“示例
示例”
tvBody.text=fromHtml(例如,this)
}
来自html的私有乐趣(html:String?,context:context):跨越{
//为Html定义ImageGetter。默认的“无图像,但”是可绘制的
//R.drawable.placeholder,但可以是另一个可绘制的。
val imageGetter=Html.imageGetter{url->
val d=ContextCompat.getDrawable(context,R.drawable.placeholder)作为BitmapDrawable
//模拟我们要显示的真实图像的网络提取。
ImageWrapper(d).应用{
simulateNetworkFetch(上下文、此、url)
}
}
返回if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.N){
Html.fromHtml(Html,Html.FROM\u Html\u MODE\u LEGACY,imageGetter,null)
}否则{
fromHtml(Html,imageGetter,null)
}
}
private-workfetch(上下文:context,imageWrapper:imageWrapper,url:String){
环球镜发射{
Log.d(“Applog”,“模拟获取$url”)
//等待繁忙的网络回复我们。
延迟(4000)
//获取“下载”的图像并将其放入我们的图像包装器中。
val d=ContextCompat.getDrawable(context,R.drawable.download)作为BitmapDrawable
imageWrapper.setBitmapDrawable(d)
//使用新图像强制重新测量/重新显示TextView。
this@MainActivity.runOnUiThread {
tvBody.text=tvBody.text
}
}
}
//BitmapDrawable的简单包装器。
私有类ImageWrapper(d:BitmapDrawable):Drawable(){
私有lateinit变量mBitMapDrawable:BitmapDrawable
初始化{
立根图可绘制(d)
}
覆盖有趣的绘图(画布:画布){
mBitMapDrawable.draw(画布)
}
覆盖函数setAlpha(alpha:Int){
}
覆盖有趣的设置colorFilter(colorFilter:colorFilter?){
}
覆盖getOpacity():Int{
返回PixelFormat.OPAQUE
}
有趣的setBitmapDrawable(bitmapDrawable:bitmapDrawable){
mBitMapDrawable=位图可绘制
mBitMapDrawable.setBounds(
0,
0,
mBitMapDrawable.intrinsicWidth,
mBitMapDrawable.intrinsicHeight
)
<style name="LIGHT" parent="Theme.AppCompat.DayNight.DarkActionBar">
<item name="android:placeHolderDefaultImage">@drawable/invisible</item>
private static void startImg(Editable text, Attributes attributes, Html.ImageGetter img) {
...
if (d == null) {
d = Resources.getSystem().
getDrawable(com.android.internal.R.drawable.unknown_image);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
}
....
}
class MainActivity : AppCompatActivity() {
private lateinit var tvBody: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvBody = findViewById(R.id.tv_body)
val exampleText =
"Example <br> <img src=\"https://www.w3schools.com/images/w3schools_green.jpg\" alt=\"W3Schools.com\"> <br> Example"
tvBody.text = fromHtml(exampleText, this)
}
private fun fromHtml(html: String?, context: Context): Spanned? {
// Define the ImageGetter for Html. The default "no image, yet" drawable is
// R.drawable.placeholder but can be another drawable.
val imageGetter = Html.ImageGetter { url ->
val d = ContextCompat.getDrawable(context, R.drawable.placeholder) as BitmapDrawable
// Simulate a network fetch of the real image we want to display.
ImageWrapper(d).apply {
simulateNetworkFetch(context, this, url)
}
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY, imageGetter, null)
} else {
Html.fromHtml(html, imageGetter, null)
}
}
private fun simulateNetworkFetch(context: Context, imageWrapper: ImageWrapper, url: String) {
GlobalScope.launch {
Log.d("Applog", "Simulating fetch of $url")
// Just wait for a busy network to get back to us.
delay(4000)
// Get the "downloaded" image and place it in our image wrapper.
val d = ContextCompat.getDrawable(context, R.drawable.downloaded) as BitmapDrawable
imageWrapper.setBitmapDrawable(d)
// Force a remeasure/relayout of the TextView with the new image.
this@MainActivity.runOnUiThread {
tvBody.text = tvBody.text
}
}
}
// Simple wrapper for a BitmapDrawable.
private class ImageWrapper(d: BitmapDrawable) : Drawable() {
private lateinit var mBitMapDrawable: BitmapDrawable
init {
setBitmapDrawable(d)
}
override fun draw(canvas: Canvas) {
mBitMapDrawable.draw(canvas)
}
override fun setAlpha(alpha: Int) {
}
override fun setColorFilter(colorFilter: ColorFilter?) {
}
override fun getOpacity(): Int {
return PixelFormat.OPAQUE
}
fun setBitmapDrawable(bitmapDrawable: BitmapDrawable) {
mBitMapDrawable = bitmapDrawable
mBitMapDrawable.setBounds(
0,
0,
mBitMapDrawable.intrinsicWidth,
mBitMapDrawable.intrinsicHeight
)
setBounds(mBitMapDrawable.bounds)
}
}
}