欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TextView实现图文混排

程序员文章站 2022-06-09 20:16:23
...

前言

我们都知道很多时候后台返回给我们的一段富文本类似这样:

<p><img alt="laugh" height="23" src="http://img3.imgtn.bdimg.com/it/u=3140599426,288343775&fm=26&gp=0.jpg" " +
                "title=\"laugh\" width=\"23\" /> 简单的图文混排" +
                "<img alt=\"cheeky\" height=\"23\" src=\"http://img3.imgtn.bdimg.com/it/u=3140599426,288343775&fm=26&gp=0.jpg\" " +
                "title="cheeky" width="23" />这是展示内容</p>

这个时候我们肯定会想到TextVIew有加载富文本的方法呀

html.setText(Html.fromHtml(string))

但是这个并不是万能这个方法默认是只能把文字显示出来的。
如果要显示文字呢?

Html.ImageGetter???

对其实Html是提供方法的

  final Html.ImageGetter imgGetter = new Html.ImageGetter() {
            public Drawable getDrawable(String source) {
                Drawable drawable = null;
                URL url = null;
                try {
                    url = new URL(source);
                    drawable = Drawable.createFromStream(url.openStream(), "img");
                } catch (Exception e) {
                    return null;
                }
                drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable
                        .getIntrinsicHeight());
                return drawable;
            }
        };

但是对于好同学来说一定很郁闷这个方法是怎么实现把图片加载出来的呢?
不妨来一个大的猜想:既然是标签,那是不是可以遍历每个节点,拿到图片后再通过imageview图加载图片
我们先看看是如何加载文字的:

fromHtml方法里面
//这个是只解析文字的构造方法我们从传进去的参数可以看出
  @Deprecated
    public static Spanned fromHtml(String source) {
        return fromHtml(source, FROM_HTML_MODE_LEGACY, null, null);
    }

这个是只解析文字的构造方法我们从传进去的参数也可以看出我们继续往里看:

 public static Spanned fromHtml(String source, int flags, ImageGetter imageGetter,
            TagHandler tagHandler) {
        Parser parser = new Parser();
        try {
            parser.setProperty(Parser.schemaProperty, HtmlParser.schema);
        } catch (org.xml.sax.SAXNotRecognizedException e) {
            // Should not happen.
            throw new RuntimeException(e);
        } catch (org.xml.sax.SAXNotSupportedException e) {
            // Should not happen.
            throw new RuntimeException(e);
        }

        HtmlToSpannedConverter converter =
                new HtmlToSpannedConverter(source, imageGetter, tagHandler, parser, flags);
        return converter.convert();
    }

他是返回这个方法那这个地方我们继续往里看:

public Spanned convert() {
.
.
.
      // Fix flags and range for paragraph-type markup.
        Object[] obj = mSpannableStringBuilder.getSpans(0, mSpannableStringBuilder.length(), ParagraphStyle.class);
        for (int i = 0; i < obj.length; i++) {
            int start = mSpannableStringBuilder.getSpanStart(obj[i]);
            int end = mSpannableStringBuilder.getSpanEnd(obj[i]);

            // If the last line of the range is blank, back off by one.
            if (end - 2 >= 0) {
                if (mSpannableStringBuilder.charAt(end - 1) == '\n' &&
                    mSpannableStringBuilder.charAt(end - 2) == '\n') {
                    end--;
                }
            }

            if (end == start) {
                mSpannableStringBuilder.removeSpan(obj[i]);
            } else {
                mSpannableStringBuilder.setSpan(obj[i], start, end, Spannable.SPAN_PARAGRAPH);
            }
        }

        return mSpannableStringBuilder;
    }
}
.
.
.

哈哈到这其实就该明白了,其实他内部就是调用这个SpannableStringBuilder()来解析标间而这个方法相信大家应该明白:

SpannableStringBuilder和SpannableString主要通过使用setSpan(Object what, int start, int end, int flags)改变

其实就是回到了span嘛而他内部也是通过span来解析的。到这是不是很明了。

end

贴一下代码

这里贴一下代码

 <uses-permission android:name="android.permission.INTERNET"/>

MainActivity

public class MainActivity extends AppCompatActivity {
    private TextView html;
   public static   Handler handler= new Handler();

    //图文混排
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        html=findViewById(R.id.html);

        final String string = "<p><img alt=\"laugh\" height=\"23\" src=\"http://img3.imgtn.bdimg.com/it/u=3140599426,288343775&fm=26&gp=0.jpg\" " +
                "title=\"laugh\" width=\"23\" /> 简单的图文混排" +
                "<img alt=\"cheeky\" height=\"23\" src=\"http://img3.imgtn.bdimg.com/it/u=3140599426,288343775&fm=26&gp=0.jpg\" " +
                "title=\"cheeky\" width=\"23\" />这是展示内容</p>";

        //展示图片
        final Html.ImageGetter imgGetter = new Html.ImageGetter() {
            public Drawable getDrawable(String source) {
                Drawable drawable = null;
                URL url = null;
                try {
                    url = new URL(source);
                    drawable = Drawable.createFromStream(url.openStream(), "img");
                } catch (Exception e) {
                    return null;
                }
                drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable
                        .getIntrinsicHeight());
                return drawable;
            }
        };

        new Thread(new Runnable() {
            @Override
            public void run() {

                final Spanned spanned = Html.fromHtml(string, imgGetter, null);
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"gascjsdf ceds",Toast.LENGTH_LONG).show();
                        html.setText(spanned);
                    }
                });

            }
        }).start();
    }

}
//由于加载图片是费时操作所以这里开启子线程,并用handler切回到主线程,及得一定要创建是静态的不然会内存泄漏

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="example.xueguoxue.taiji.MainActivity">

        <TextView
            android:id="@+id/html"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
</RelativeLayout>

效果图

TextView实现图文混排

相关标签: Study