Статьи

Пользовательский гиперссылкой TextView для Android

Найти ссылки в Android очень просто, вы, возможно, слышали о Linkify, который является отличным классом, в котором есть много статических методов для выполнения простой работы, но проблема в том, что в Linkify вы не можете указать поведение, которое вам требуется при нажатии на ссылки Самое большее, что делает Linkify — это то, что он просто находит ссылки на основе предоставленного вами «шаблона», добавляет строку «Схема» для завершения URL-адреса и создает намерение Android для запуска браузера. Поведение Linkify нельзя переопределить, так как все методы в классе Linkify являются статическими final.

Это была проблема, которая вдохновила меня на создание пользовательского виджета TextView, который собирает ссылки в моем сценарии. Я также запрограммировал его на сбор строк, начинающихся с «@» и «#», но это можно изменить, просто изменив Шаблоны, которые вам нужны, и дающие им правильное регулярное выражение.

Класс LinkEnableTextView выглядит так:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
 
 
public class LinkEnabledTextView  extends TextView
{
// The String Containing the Text that we have to gather links from private SpannableString linkableText;
// Populating and gathering all the links that are present in the Text
private ArrayList<Hyperlink> listOfLinks;
 
// A Listener Class for generally sending the Clicks to the one which requires it
TextLinkClickListener mListener;
 
// Pattern for gathering @usernames from the Text
Pattern screenNamePattern = Pattern.compile('(@[a-zA-Z0-9_]+)');
 
// Pattern for gathering #hasttags from the Text
Pattern hashTagsPattern = Pattern.compile('(#[a-zA-Z0-9_-]+)');
 
// Pattern for gathering http:// links from the Text
Pattern hyperLinksPattern = Pattern.compile('([Hh][tT][tT][pP][sS]?:\\/\\/[^ ,'\'>\\]\\)]*[^\\. ,'\'>\\]\\)])');
 
public LinkEnabledTextView(Context context, AttributeSet attrs)
{
    super(context, attrs);
    listOfLinks = new ArrayList<Hyperlink>();
 
}
 
public void gatherLinksForText(String text)
{
    linkableText = new SpannableString(text);
 //gatherLinks basically collects the Links depending upon the Pattern that we supply
 //and add the links to the ArrayList of the links
   
    gatherLinks(listOfLinks, linkableText, screenNamePattern);
    gatherLinks(listOfLinks, linkableText, hashTagsPattern);
    gatherLinks(listOfLinks, linkableText, hyperLinksPattern);
 
    for(int i = 0; i< listOfLinks.size(); i++)
    {
        Hyperlink linkSpec = listOfLinks.get(i);
        android.util.Log.v('listOfLinks :: ' + linkSpec.textSpan, 'listOfLinks :: ' + linkSpec.textSpan);
         
        // this process here makes the Clickable Links from the text
          
        linkableText.setSpan(linkSpec.span, linkSpec.start, linkSpec.end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
 
     
     // sets the text for the TextView with enabled links
      
    setText(linkableText);
}
 
 
 // sets the Listener for later click propagation purpose
  
public void setOnTextLinkClickListener(TextLinkClickListener newListener)
{
    mListener = newListener;
}
 
  //The Method mainly performs the Regex Comparison for the Pattern and adds them to
  //listOfLinks array list
  
 
private final void gatherLinks(ArrayList<Hyperlink> links,
                               Spannable s, Pattern pattern)
{
    // Matcher matching the pattern
    Matcher m = pattern.matcher(s);
 
    while (m.find())
    {
        int start = m.start();
        int end = m.end();
 
         
    // Hyperlink is basically used like a structure for storing the information about
    // where the link was found.
         
        Hyperlink spec = new Hyperlink();
 
        spec.textSpan = s.subSequence(start, end);
        spec.span = new InternalURLSpan(spec.textSpan.toString());
        spec.start = start;
        spec.end = end;
 
        links.add(spec);
    }
}
 
 
// This is class which gives us the clicks on the links which we then can use.
  
 
public class InternalURLSpan extends ClickableSpan
{
    private String clickedSpan;
 
    public InternalURLSpan (String clickedString)
    {
        clickedSpan = clickedString;
    }
 
    @Override
    public void onClick(View textView)
    {
        mListener.onTextLinkClick(textView, clickedSpan);
    }
}
 
 
// Class for storing the information about the Link Location
 
 
class Hyperlink
{
    CharSequence textSpan;
    InternalURLSpan span;
    int start;
    int end;
}

Теперь, имея это, вам потребуется еще один интерфейс для распространения кликов в то место, которое вам требуется для их обработки, в моем случае я реализовал этот интерфейс в своей Activity и просто написал там команду Log.

Интерфейс TextLinkClickListener выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
import android.view.View;
 
public interface TextLinkClickListener
{
 
  
  //  This method is called when the TextLink is clicked from LinkEnabledTextView
   
public void onTextLinkClick(View textView, String clickedString)
}

После всего этого вам просто нужно создать Activity с помощью Custom LinkEnabledTextView и проверить все самостоятельно. Есть несколько вещей, которые вы должны сделать при создании объекта Custom LinkEnabledTextView, которые упомянуты и описаны в коде действия ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import android.text.method.MovementMethod;
import com.umundoinc.Tvider.Component.LinkEnabledTextView.LinkEnabledTextView;
import com.umundoinc.Tvider.Component.LinkEnabledTextView.TextLinkClickListener;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
 
//Here the Activity is implementing the TextLinkClickListener the one we have created
//the Clicks over the Links are forwarded over here from the LinkEnabledTextView
  
public class TextViewActivity  extends Activity  implements TextLinkClickListener
{
private LinkEnabledTextView check;
protected void onCreate(Bundle savedInstance)
{
    super.onCreate(savedInstance);
 
    String text  =  "This is a #test of regular expressions with http://example.com/ links as used in @twitter for performing various operations based on the links this handles multiple links like http://this_is_fun.com/ and #Awesomess and @Cool";
 
    check = new LinkEnabledTextView(this, null);
    check.setOnTextLinkClickListener(this);
    check.gatherLinksForText(text);
    check.setTextColor(Color.WHITE);
    check.setLinkTextColor(Color.GREEN);
 
    MovementMethod m = check.getMovementMethod();
    if ((m == null) || !(m instanceof LinkMovementMethod)) {
        if (check.getLinksClickable()) {
            check.setMovementMethod(LinkMovementMethod.getInstance());
        }
    }
 
    setContentView(check);
}
 
public void onTextLinkClick(View textView, String clickedString)
{
    android.util.Log.v('Hyperlink clicked is :: ' + clickedString, 'Hyperlink clicked is :: ' + clickedString);
}

Вот снимок экрана, описывающий вывод в моем методе Listener, который я запрограммировал для отображения тоста, но все можно достичь тем же методом.

Теперь это почти все, что вам нужно для работы Custom LinkEnabledTextView, опробуйте его и поделитесь своими взглядами и отзывами.

Ссылка: Android Custom Hyperlinked TextView от нашего партнера JCG Y Камеш Рао в блоге OrangeApple .