我有一个显示一些HTML代码的TextView(包括图像,ImageGetter)。
html不是我的,但我可以要求他们包含自定义方案链接,甚至可能包含标签
目的:显示一些动态生成的内容,而无需使用嵌套的Android布局
问题:必须在应用程序中处理一些链接(加载新的片段)
不能使用receiver for action.VIEW,因为它是一个活动意图,而不是一个广播,它的使用将是非常上下文的,所以只有一个以编程方式注册的接收器才会这样做。
我正在使用textView.setText(Html.fromHtml(content.content, imageGetter, null)
。需要一切都保持不变,除了一些跨度应该有我自己的onClick
。我对Spanned不太熟悉,所以我看到了这些选项:
Html.fromHtml
返回的SpannableStringBuilder,并用自定义ClickableSpan替换我想要的URLSpans(如何?)append
只接受CharSequence,我得到RelativeSizeSpan,StyleSpan,ImageSpan,URLSpan ......)Html.fromHtml
(或足够接近)的效果?[编辑] 感谢MH。信息。我之前尝试过,但失败了。现在我回到了它,我发现我犯了一个错误,将错误的项目传递给了setSpan的第一个参数 如果有人有兴趣,我现在用这个:
public static interface OnSpanClickListener {
void onClick(String url);
}
public static SpannableStringBuilder getSpannable(String source, ImageGetter imageGetter, String scheme, final OnSpanClickListener clickHandler){
SpannableStringBuilder b = (SpannableStringBuilder) Html.fromHtml(source, imageGetter, null);
for(URLSpan s : b.getSpans(0, b.length(), URLSpan.class)){
String s_url = s.getURL();
if(s_url.startsWith(scheme+"://")){
URLSpan newSpan = new URLSpan(s_url.substring(scheme.length()+3)){
public void onClick(View view) {
clickHandler.onClick(getURL());
}
};
b.setSpan(newSpan, b.getSpanStart(s), b.getSpanEnd(s), b.getSpanFlags(s));
b.removeSpan(s);
}
}
return b;
}
(...)
body.setText(getSpannable(content.content, imageGetter, getResources().getString(R.string.poster_scheme), new OnSpanClickListener(){
public void onClick(String url) {
// do whatever
}
}));
答案 0 :(得分:3)
选项1可能是最直接的,并且之前的大部分艰苦工作已经完成。您的一般想法是正确的:在处理完HTML后,您可以请求所有生成的URLSpan
实例并循环遍历它们。然后,您可以使用自定义的可点击范围替换它,以获得对任何跨度点击的完全控制。
在下面的示例中,我只是将每个URLSpan
替换为带有原始url的类的简单扩展(实际上,我应该说'uri')并替换其scheme部分。我已经离开了实际的onClick()
逻辑未实现,但我会把它留给你的想象力。
SpannableStringBuilder builder = ...
URLSpan[] spans = builder .getSpans(0, builder .length(), URLSpan.class);
for (URLSpan span : spans) {
int start = builder .getSpanStart(span);
int end = builder .getSpanEnd(span);
s.removeSpan(span);
span = new CustomURLSpan(span.getURL().replace("http://", "scheme://"));
s.setSpan(span, start, end, 0);
}
textView.setText(builder);
如前所述,这里CustomURLSpan
类是URLSpan
的简单扩展,它接受一个url并覆盖onClick()
方法,因此我们自己的逻辑可以在那里执行。
public class CustomURLSpan extends URLSpan {
public CustomURLSpan(String url) {
super(url);
}
@Override public void onClick(View widget) {
// custom on click behaviour here
}
}
一些相关的Q& A基本上做了类似的事情(可能对一些更多的灵感有帮助):
答案 1 :(得分:1)
由于您将使用 TextView.setMovementMethod(LinkMovementMethod.getInstance())来响应部分点击,因此您可以实施自定义 LinkMovementMethod < / strong>拦截click事件并处理你自己的逻辑。
public class CustomLinkMovementMethod extends LinkMovementMethod {
private HashMap<Class, SpanProxy> spansProxy = new HashMap<>();
public CustomLinkMovementMethod setSpanProxy(Class spanClazz, SpanProxy proxy) {
spansProxy.put(spanClazz, proxy);
return this;
}
public CustomLinkMovementMethod removeSpanProxy(Class spanClazz) {
spansProxy.remove(spanClazz);
return this;
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
SpanProxy spanProxy = spansProxy.get(ClickableSpan.class);
if(spanProxy != null) {
spanProxy.proxySpan(link[0], widget);
} else {
link[0].onClick(widget);
}
return true;
}
}
}
return super.onTouchEvent(widget, buffer, event);
}
public interface SpanProxy {
void proxySpan(Object span, View widget);
}
}
并像这样使用:
textView.setMovementMethod(new CustomLinkMovementMethod().setSpanProxy(ClickableSpan.class,
new CustomLinkMovementMethod.SpanProxy() {
@Override
public void proxySpan(Object span, View widget) {
if (span instanceof URLSpan) {
URLSpan urlSpan = (URLSpan) span;
String url = urlSpan.getURL();
// do what you want with the link
// tbd
return;
}
if (span instanceof ClickableSpan) {
((ClickableSpan) span).onClick(widget);
}
}
}));