t= (TextView) findViewById(R.id.PP1);
t.setText(Html.fromHtml("<bThis is normal text </b>" +
"<a href=\"http://www.xyz-zyyx.com\">This is cliclable text</a> "));
t.setMovementMethod(LinkMovementMethod.getInstance());
public static TextView createLink(TextView targetTextView, String completeString,
String partToClick, ClickableSpan clickableAction) {
SpannableString spannableString = new SpannableString(completeString);
// make sure the String is exist, if it doesn't exist
// it will throw IndexOutOfBoundException
int startPosition = completeString.indexOf(partToClick);
int endPosition = completeString.lastIndexOf(partToClick) + partToClick.length();
spannableString.setSpan(clickableAction, startPosition, endPosition,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
targetTextView.setText(spannableString);
targetTextView.setMovementMethod(LinkMovementMethod.getInstance());
return targetTextView;
}
下面是你如何使用它
private void initSignUp() {
String completeString = "New to Reddit? Sign up here.";
String partToClick = "Sign up";
ClickableTextUtil
.createLink(signUpEditText, completeString, partToClick,
new ClickableSpan() {
@Override
public void onClick(View widget) {
// your action
Toast.makeText(activity, "Start Sign up activity",
Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
// this is where you set link color, underline, typeface etc.
int linkColor = ContextCompat.getColor(activity, R.color.blumine);
ds.setColor(linkColor);
ds.setUnderlineText(false);
}
});
}
fun TextView.makeLinks(vararg links: Pair<String, View.OnClickListener>) {
val spannableString = SpannableString(this.text)
var startIndexOfLink = -1
for (link in links) {
val clickableSpan = object : ClickableSpan() {
override fun updateDrawState(textPaint: TextPaint) {
// use this to change the link color
textPaint.color = textPaint.linkColor
// toggle below value to enable/disable
// the underline shown below the clickable text
textPaint.isUnderlineText = true
}
override fun onClick(view: View) {
Selection.setSelection((view as TextView).text as Spannable, 0)
view.invalidate()
link.second.onClick(view)
}
}
startIndexOfLink = this.text.toString().indexOf(link.first, startIndexOfLink + 1)
// if(startIndexOfLink == -1) continue // todo if you want to verify your texts contains links text
spannableString.setSpan(
clickableSpan, startIndexOfLink, startIndexOfLink + link.first.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
this.movementMethod =
LinkMovementMethod.getInstance() // without LinkMovementMethod, link can not click
this.setText(spannableString, TextView.BufferType.SPANNABLE)
}
使用
my_text_view.makeLinks(
Pair("Terms of Service", View.OnClickListener {
Toast.makeText(applicationContext, "Terms of Service Clicked", Toast.LENGTH_SHORT).show()
}),
Pair("Privacy Policy", View.OnClickListener {
Toast.makeText(applicationContext, "Privacy Policy Clicked", Toast.LENGTH_SHORT).show()
}))
XML
<TextView
android:id="@+id/my_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Please accept Terms of Service and Privacy Policy"
android:textColorHighlight="#f00" // background color when pressed
android:textColorLink="#0f0"
android:textSize="20sp" />
public void setClickableString(String clickableValue, String wholeValue, TextView yourTextView){
String value = wholeValue;
SpannableString spannableString = new SpannableString(value);
int startIndex = value.indexOf(clickableValue);
int endIndex = startIndex + clickableValue.length();
spannableString.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false); // <-- this will remove automatic underline in set span
}
@Override
public void onClick(View widget) {
// do what you want with clickable value
}
}, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
yourTextView.setText(spannableString);
yourTextView.setMovementMethod(LinkMovementMethod.getInstance()); // <-- important, onClick in ClickableSpan won't work without this
}
下面是如何使用它:
TextView myTextView = findViewById(R.id.myTextView);
setClickableString("stack", "Android is a Software stack", myTextView);
/**
* Method is used to Linkify words in a TextView
*
* @param textView TextView who's text you want to change
* @param textToLink The text to turn into a link
* @param url The url you want to send the user to
*/
fun linkify(textView: TextView, textToLink: String, url: String) {
val pattern = Pattern.compile(textToLink)
Linkify.addLinks(textView, pattern, url, { _, _, _ -> true })
{ _, _ -> "" }
}
使用这个函数非常简单。这里有一个例子
// terms and privacy
val tvTerms = findViewById<TextView>(R.id.tv_terms)
val tvPrivacy = findViewById<TextView>(R.id.tv_privacy)
Utils.linkify(tvTerms, resources.getString(R.string.terms),
Constants.TERMS_URL)
Utils.linkify(tvPrivacy, resources.getString(R.string.privacy),
Constants.PRIVACY_URL)
/*
* Receive Pair of Text and Action and set it clickable and appearing as link
* */
fun TextView.setClickableText(vararg textToSpanAndClickAction: Pair<String, (String) -> Unit>) {
val builder = SpannableStringBuilder(text.toString())
textToSpanAndClickAction.forEach { argPair ->
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View) {
argPair.second.invoke(argPair.first)
}
}
this.text.toString().let { fullText ->
val indexOfFirst = fullText.indexOf(argPair.first)
val indexOfLast = indexOfFirst + argPair.first.length
if (indexOfFirst < 0){
//No match found
return
}else{
builder.setSpan(
clickableSpan,
indexOfFirst,
indexOfLast,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
}
this.text = builder
this.movementMethod = LinkMovementMethod.getInstance()
}
public class MainActivity extends AppCompatActivity {
SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sp = getSharedPreferences("MyUserPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
TextView fulltext = (TextView) findViewById(R.id.fulltext);
//replace setText("") to setText("Android is a Software stack") for his case
fulltext.setText("Search [1] this full [1] text with repeated strings. Search [2] Search [3] full [2] full [3]");
List<Pair<String, View.OnClickListener>> links = new ArrayList<>();
//replace "Search" with "stack" for his case
String stringtohyperlink = "Search";
String stringtohyperlink2 = "full";
links.add(new Pair<>(stringtohyperlink, new View.OnClickListener() {
@Override
public void onClick(View v) {
String position = sp.getString("position","0");
if (position.equals("1")) {
Toast.makeText(MainActivity.this, "Search 1 has been Clicked.", Toast.LENGTH_SHORT).show();
editor.putString("position","0");
editor.apply();
}
if (position.equals("2")) {
Toast.makeText(MainActivity.this, "Search 2 has been Clicked.", Toast.LENGTH_SHORT).show();
editor.putString("position","0");
editor.apply();
}
if (position.equals("3")) {
Toast.makeText(MainActivity.this, "Search 3 has been Clicked.", Toast.LENGTH_SHORT).show();
editor.putString("position","0");
editor.apply();
}
}
}));
links.add(new Pair<>(stringtohyperlink2, new View.OnClickListener() {
@Override
public void onClick(View v) {
String position = sp.getString("position","0");
if (position.equals("1")) {
Toast.makeText(MainActivity.this, "full 1 has been Clicked.", Toast.LENGTH_SHORT).show();
editor.putString("position","0");
editor.apply();
}
if (position.equals("2")) {
Toast.makeText(MainActivity.this, "full 2 has been Clicked.", Toast.LENGTH_SHORT).show();
editor.putString("position","0");
editor.apply();
}
if (position.equals("3")) {
Toast.makeText(MainActivity.this, "full 3 has been Clicked.", Toast.LENGTH_SHORT).show();
editor.putString("position","0");
editor.apply();
}
}
}));
makeLinks(fulltext, links);
}
public void makeLinks(TextView textView, List<Pair<String, View.OnClickListener>> links) {
SpannableString spannableString = new SpannableString(textView.getText().toString());
int startIndexState = -1;
SharedPreferences.Editor editor = sp.edit();
for (Pair<String, View.OnClickListener> link : links) {
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
editor.putString("position","1");
editor.apply();
widget.invalidate();
assert link.second != null;
link.second.onClick(widget);
}
};
ClickableSpan clickableSpan2 = new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
editor.putString("position","2");
editor.apply();
widget.invalidate();
assert link.second != null;
link.second.onClick(widget);
}
};
ClickableSpan clickableSpan3 = new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
editor.putString("position","3");
editor.apply();
widget.invalidate();
assert link.second != null;
link.second.onClick(widget);
}
};
//... This only allows for 3 repeated words
//... Add more of it, if there are more repeated words.
assert link.first != null;
int startIndexOfLink = textView.getText().toString().indexOf(link.first, startIndexState + 1);
spannableString.setSpan(clickableSpan, startIndexOfLink, startIndexOfLink + link.first.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
int startIndexOfLink2 = textView.getText().toString().indexOf(link.first, startIndexOfLink + 1);
if (startIndexOfLink2 != -1) {
spannableString.setSpan(clickableSpan2, startIndexOfLink2, startIndexOfLink2 + link.first.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
}
int startIndexOfLink3 = textView.getText().toString().indexOf(link.first, startIndexOfLink2 + 1);
if (startIndexOfLink3 != -1) {
spannableString.setSpan(clickableSpan3, startIndexOfLink3, startIndexOfLink3 + link.first.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
}
//... This only allows for 3 repeated words
//... Add more of it, if there are more repeated words.
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(spannableString, TextView.BufferType.SPANNABLE);
}
}
}