Android textView展示html图片,实现图文混排,点击查看大图片

Android textView展示html图片,实现图文混排,点击查看大图片

最近要展示html在textView上,实现图文混排,并且图片可以点击放大,所以去研究了一下,效果图如下:
Android textView展示html图片,实现图文混排,点击查看大图片_第1张图片

我们知道textView的setText(Html.fromHtml(html))可以直接展示html的内容,但是如果html的标签包含imgd的话,直接用这个方法图片会展示不出来,然后我们看fromHtml的另一个构造方法的源码:

public static Spanned fromHtml(String source, 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);
    return converter.convert();
}

通过上面的代码我们知道要想展示图片,我们可以重写imageGetter,下面是我重写imageGetter:

public class MImageGetter implements ImageGetter{
    Context c;
    TextView container;

    public MImageGetter(TextView text,Context c) {
        this.c = c;
        this.container = text;
    }
 public Drawable getDrawable(String source) {
     final LevelListDrawable drawable = new LevelListDrawable();
     Glide.with(c).load(source).asBitmap().into(new SimpleTarget() {
         @Override
         public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
             if(resource != null) {
                 BitmapDrawable bitmapDrawable = new BitmapDrawable(resource);
                 drawable.addLevel(1, 1, bitmapDrawable);
                 drawable.setBounds(0, 0, resource.getWidth(),resource.getHeight());
                 drawable.setLevel(1);
                 container.invalidate();
                 container.setText(container.getText());
             }
         }
     });


     return drawable;
 }

}

加载图片的时候我用的是glide异步加载,其他原理一样。现在图片已经可以正常展示出来了,接下来要获取它的点击事件,这就首先需要设置textView的setMovementMethod方法,然后重写LinkMovementMethod获取到点击事件:

/**
 * 重写LinkMovementMethod类,获取图片的点击事件
 */
public class LinkMovementMethodExt extends LinkMovementMethod {
    private static LinkMovementMethod sInstance;
    private  Handler handler = null;
    private  Class spanClass = null;

    public static  MovementMethod getInstance(Handler _handler,Class _spanClass) {
        if (sInstance == null) {
            sInstance = new LinkMovementMethodExt();
            ((LinkMovementMethodExt)sInstance).handler = _handler;
            ((LinkMovementMethodExt)sInstance).spanClass = _spanClass;
        }

        return sInstance;
    }

    int x1;
    int x2;
    int y1;
    int y2;

     @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer,
                                    MotionEvent event) {
            int action = event.getAction();

            if (event.getAction() == MotionEvent.ACTION_DOWN){
                x1 = (int) event.getX();
                y1 = (int) event.getY();
            }

            if (event.getAction() == MotionEvent.ACTION_UP) {
                x2 = (int) event.getX();
                y2 = (int) event.getY();

            if (Math.abs(x1 - x2) < 10 && Math.abs(y1 - y2) < 10) {

                x2 -= widget.getTotalPaddingLeft();
                y2 -= widget.getTotalPaddingTop();

                x2 += widget.getScrollX();
                y2 += widget.getScrollY();

                Layout layout = widget.getLayout();
                int line = layout.getLineForVertical(y2);
                int off = layout.getOffsetForHorizontal(line, x2);
                /**
                 * get you interest span
                 */
                Object[] spans = buffer.getSpans(off, off, spanClass);
                if (spans.length != 0) {

                    Selection.setSelection(buffer,
                            buffer.getSpanStart(spans[0]),
                            buffer.getSpanEnd(spans[0]));
                    MessageSpan obj = new MessageSpan();
                    obj.setObj(spans);
                    obj.setView(widget);
                    Message message = handler.obtainMessage();
                    message.obj = obj;
                    message.what = 200;
                    message.sendToTarget();
                    return true;
                }
            }
            }             
            return super.onTouchEvent(widget, buffer, event);                        
        }

     public boolean canSelectArbitrarily() {
            return true;
        }

    public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode,
            KeyEvent event) {
        return false;
    }
}

这样,我们就可以在mainactivity里面根据需要处理了:

public class MainActivity extends AppCompatActivity {

private TextView tv;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv = (TextView) findViewById(R.id.tv);
    ScrollView sv = (ScrollView) findViewById(R.id.sv);

    final String html = "下面是第一张图片了 " + "" +
            "这也是第二张图片" + "" +
            "最后一张" + "";

    tv.setText(Html.fromHtml(html, new MImageGetter(tv, getApplicationContext()), null));
    final Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            int what = msg.what;
            if (what == 200) {
                MessageSpan ms = (MessageSpan) msg.obj;
                Object[] spans = (Object[]) ms.getObj();
                final ArrayList list = new ArrayList<>();
                for (Object span : spans) {
                    if (span instanceof ImageSpan) {
                        Log.i("picUrl==", ((ImageSpan) span).getSource());
                        list.add(((ImageSpan) span).getSource());
                        Intent intent = new Intent(getApplicationContext(), ImageGalleryActivity.class);
                        intent.putStringArrayListExtra("images", list);
                        startActivity(intent);
                    }
                }
            }
        }
    };
    tv.setMovementMethod(LinkMovementMethodExt.getInstance(handler, ImageSpan.class));
}
}

上面的代码判断span是否是imagespan,如果是的话,我们就获取到它的地址,然后进行相应的操作。

到了这里,利用textView展示html,进行图文混排就完成了。

你可能感兴趣的:(原创)