2010-09-02 19 views
32

Ich verwende eine TextView, für die ich autolink="web" Eigenschaft in XML-Datei festgelegt habe. Ich habe auch die onClickListener für diese TextView implementiert. Das Problem ist, wenn der Text in TextView einen Hyperlink enthält, und wenn ich diesen Link berühre, öffnet sich der Link im Browser, aber gleichzeitig löst die onClickListener auch aus. Ich will das nicht.Steuerung onclicklistener in Autolink aktiviert Textansicht

Was ich will ist, wenn ich den Hyperlink der ClickListener sollte nicht ausgelöst werden. Es sollte nur ausgelöst werden, wenn ich den Teil des Textes berühre, der nicht verlinkt ist. Irgendein Vorschlag?

+0

Upvote für eine nette Frage.Aber nicht möglich, meiner Meinung nach – Sameer

+1

müssen Sie den Text als verschiedene Textansichten trennen, und separate Hörer einstellen, kann nicht an eine andere Möglichkeit – Mal

Antwort

0

Anstatt einen onClickListener zu verwenden, können Sie dies versuchen.

private void addLink() { 
     tvLink = (TextView) findViewById(R.id.tvInfo2); 

     String strURL = UrlLoader.getCodeUrl(); 

     // Make the url string clicable and take action in its onclick 
     SpannableString spanUrl = SpannableString.valueOf(strURL); 
     spanUrl.setSpan(new InternalURLSpan(new OnClickListener() { 
      public void onClick(View v) { 

       //Do Some action 
      } 
     }), 0, spanUrl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
     tvLink.setText(spanUrl); 

     // We probably also want the user to jump to your link by moving the 
     // focus (e.g. using the trackball), which we can do by setting the 
     // proper movement method: 
     MovementMethod m = tvLink.getMovementMethod(); 
     if ((m == null) || !(m instanceof LinkMovementMethod)) { 
      if (tvLink.getLinksClickable()) { 
       tvLink.setMovementMethod(LinkMovementMethod.getInstance()); 
      } 
     } 
    } 

Auch in der Layout-XML-Datei, vergessen Sie nicht,

<TextView android:layout_width="wrap_content" android:linksClickable="true" 
android:layout_height="wrap_content" android:id="@+id/tvInfo2" android:text="@string/url_link" /> 
20

Sie können hinzufügen, damit diese eine Arbeit um in getSelectionStart mit() und getSelectionEnd() Funktionen der Textview-Klasse,

tv.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     ClassroomLog.log(TAG, "Textview Click listener "); 
     if (tv.getSelectionStart() == -1 && tv.getSelectionEnd() == -1) { 
      //This condition will satisfy only when it is not an autolinked text 
      //Fired only when you touch the part of the text that is not hyperlinked 
     } 
    } 
}); 

Es kann eine späte Antwort sein, aber möglicherweise nützlich für diejenigen, die nach einer Lösung suchen.

+2

denken, wenn ich außerhalb des Textes sowie Links klicken in textview öffnet es immer noch die link-ansicht, die ich nur dann aufrufen möchte, wenn ich auf den link klicke. –

+0

Dude life save on this one! Danke meins war das Gegenteil, ich musste einige Vorverarbeitung, bevor es ging auf Hyperlink, so änderte nur die -1 zu> 0 und Viola es funktionierte – JPM

+0

hat gut funktioniert! Vielen Dank! : D – Jan

1

Verwenden Sie textView.getSelectionStart() und textView.getSelectionEnd(). Wenn Sie auf einen anderen Text als link textView.getSelectionStart() und textView.getSelectionEnd() klicken, wird -1 .So mit einer if-Bedingung in onClickListner Sie kann die onClick-Aktion blockieren, wenn auf die Verknüpfung geklickt wird.

//inside onClickListner 

if(textView.getSelectionStart()==-1&&textView.getSlectionEnd==-1){ 

    //onClick action 
} 
1

, wenn Sie möchten, können Sie den nächsten Code benutzen, die die klickbare Links innerhalb der Zeichenfolge anpassen können (basierend auf this post):

Nutzung:

final TextView textView = (TextView) findViewById(R.id.textView); 
final Spanned text = Html.fromHtml(getString(...)); 
textView.setText(text); 
textView.setMovementMethod(new LinkMovementMethodExt()); 

LinkMovementMethodExt.java

public class LinkMovementMethodExt extends LinkMovementMethod { 
    private static LinkMovementMethod sInstance; 

    public static MovementMethod getInstance() { 
     if (sInstance == null) 
      sInstance = new LinkMovementMethodExt(); 
     return sInstance; 
    } 

    @Override 
    public boolean onTouchEvent(final TextView widget, final Spannable buffer, final MotionEvent event) { 
     final int action = event.getAction(); 
     if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { 
      final int x = (int) event.getX() - widget.getTotalPaddingLeft() + widget.getScrollX(); 
      final int y = (int) event.getY() - widget.getTotalPaddingTop() + widget.getScrollY(); 
      final Layout layout = widget.getLayout(); 
      final int line = layout.getLineForVertical(y); 
      final int off = layout.getOffsetForHorizontal(line, x); 
      final ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); 
      if (link.length != 0) { 
       //do something with the clicked item... 
       return true; 
      } 
     } 
     return super.onTouchEvent(widget, buffer, event); 
    } 

} 
3

Sie können die Eigenschaft android: linksClickable = "false" in Ihnen festlegen r TextView, in Verbindung mit Android: autoLink = "web"; Dies macht die Links sichtbar, aber nicht anklickbar.

+2

Ich denke, das wird zu einem umgekehrten Verhalten führen, als was erforderlich ist. – Adnan

+0

Aber es ist genau das, was ich brauchte :) – Kevin

9

one of the @CommonsWare post hilft abfangen Autolink Ereignis.

private void fixTextView(TextView tv) { 
    SpannableString current = (SpannableString) tv.getText(); 
    URLSpan[] spans = 
      current.getSpans(0, current.length(), URLSpan.class); 

    for (URLSpan span : spans) { 
     int start = current.getSpanStart(span); 
     int end = current.getSpanEnd(span); 

     current.removeSpan(span); 
     current.setSpan(new DefensiveURLSpan(span.getURL()), start, end, 
       0); 
    } 
} 

public static class DefensiveURLSpan extends URLSpan { 
    private String mUrl; 

    public DefensiveURLSpan(String url) { 
     super(url); 
     mUrl = url; 
    } 

    @Override 
    public void onClick(View widget) { 
     // openInWebView(widget.getContext(), mUrl); // intercept click event and do something. 
     // super.onClick(widget); // or it will do as it is. 
    } 
} 

Wenden Sie den obigen Code einfach wie unten an. Es durchläuft alle verknüpfbaren Texte und ersetzt Klickereignisse durch den obigen Ereignishandler.

fixTextView(textViewContent); 
+0

Dieser Beitrag machte den Unterschied. Sehr wichtiger Hinweis am Ende: "Beachten Sie, dass Sie setText() nicht in TextView aufrufen möchten, da Sie den Text durch die geänderte Version ersetzen würden. Sie ändern den TextView-Text in dieser fixTextView() -Methode Daher ist setText() nicht erforderlich. Schlimmer noch: Wenn Sie android: autoLink verwenden, würde setText() dazu führen, dass Android wieder zurückgeht und URLSpans erneut hinzufügt. " – trans

+0

Exzellent, genau das, was ich brauchte – MykeAngel

1

Hinzufügen Nur

textView.setMovementMethod(CustomLinkMovementMethod.getInstance());

zu @binary ‚s Antwort für diejenigen, die die Methode nicht mit ihnen funktionierten

1
private void fixTextView(TextView tv) { 
    SpannableString current = (SpannableString) tv.getText(); 
    URLSpan[] spans = 
      current.getSpans(0, current.length(), URLSpan.class); 

    for (URLSpan span : spans) { 
     int start = current.getSpanStart(span); 
     int end = current.getSpanEnd(span); 

     current.removeSpan(span); 
     current.setSpan(new DefensiveURLSpan(span.getURL()), start, end, 
       0); 
    } 
} 

public static class DefensiveURLSpan extends URLSpan { 

    public final static Parcelable.Creator<DefensiveURLSpan> CREATOR = 
      new Parcelable.Creator<DefensiveURLSpan>() { 

     @Override 
     public DefensiveURLSpan createFromParcel(Parcel source) { 
      return new DefensiveURLSpan(source.readString()); 
     } 

     @Override 
     public DefensiveURLSpan[] newArray(int size) { 
      return new DefensiveURLSpan[size]; 
     } 

    }; 

private String mUrl; 

public DefensiveURLSpan(String url) { 
    super(url); 
    mUrl = url; 
} 

    @Override 
    public void onClick(View widget) { 
     // openInWebView(widget.getContext(), mUrl); // intercept click event and do something. 
     // super.onClick(widget); // or it will do as it is. 
    } 
} 

Sie würden dann Rufen Sieanauf der Ansicht nach der es (über Inflation oder findViewById) deklariert oder in das Fenster (über addView)

hinzugefügt wird Dies enthält die fehlende Anforderung, einen ERSTELLER festzulegen, wenn ein Parcelable erweitert wird.

Es wurde als Bearbeitung vorgeschlagen, aber abgelehnt. Leider müssen zukünftige Benutzer erst herausfinden, dass das Original unvollständig ist. Netter, Rezensenten!

+0

Warum denken Sie, dass es gebraucht wird? Antwort, auf die Sie sich beziehen, funktioniert ohne 'CREATOR' Feld – wzieba

+0

@wzieba es hängt von Ihrer Ziel-API, IDE und Fehlereinstellungen ab. Wenn Sie eine abgeschnittene Version verwenden wollen und Ihre spezielle Konfiguration dies erlaubt, dann auf alle Fälle. Sei dir bewusst, dass es zu jeder Zeit aufhören kann zu arbeiten. – LoungeKatt

+0

Ich bekomme immer noch nicht, wie Ziel-API und insbesondere IDE eine Ursache für einen Fehler in diesem Code sein könnte. Es wäre sehr nützlich, wenn Sie ein Beispiel an Ihre Antwort schreiben würden, dass das Feld "CREATOR" sinnvoll ist. – wzieba