2013-04-11 33 views
3

我有一个TextView,显示一些HTML代码(图像包括,ImageGetter)。 该html不是我的,但我可以要求他们包括自定义计划链接,甚至可能是标签。

目的:显示一些动态生成的内容,无需玩嵌套的Android布局。
问题:一些链接必须在应用程序中处理(新的Fragment已加载)。
不能使用receiver for action.VIEW,因为它是一个活动意图,而不是广播,并且它的使用将非常有用,所以只有通过程序注册的接收器才能做到。我正在使用textView.setText(Html.fromHtml(content.content, imageGetter, null)。需要一切保持不变,除了一些跨度应该有我自己的onClick就可以了。我不是很熟悉,跨区,所以我看到这些选项:从Html.fromHtml跨越,但自定义方案的自定义ClickableSpan

  1. 编辑SpannableStringBuilder从Html.fromHtml回来,并用自定义ClickableSpan(如何?)
  2. 如上代替我想URLSpans,但复制所有东西都交给一个新的构建器,为我自己交换URLSpans(append只接受CharSequence,我得到RelativeSizeSpan,StyleSpan,ImageSpan,URLSpan ...)
  3. 手动创建一个Spanned。我可以为自定义方案执行此操作,但是如何复制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 
} 
})); 

回答

3

选项1是可能是最简单,最它的辛勤工作已经做过的事情。您的总体思路是正确的:处理完HTML后,您可以请求生成的所有URLSpan实例并循环访问它们。然后,您可以用定制的可点击范围替换它,以全面控制任何跨度点击。

在下面的例子中,我只是用每个URLSpan这个类的简单扩展来取代原始url(实际上,我应该说'uri')并替换它的方案部分。我已经将实际的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

正如你将使用TextView.setMovementMethod(LinkMovementMethod.getInstance())使其响应对于部分点击,您可以实施自定义的LinkMovementMethod来拦截点击事件并处理您自己的逻辑。

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); 
       } 
      } 
     }));