java PatternEditableBuilder - 在TextView中创建彩色可点击跨度的简便方法!
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java PatternEditableBuilder - 在TextView中创建彩色可点击跨度的简便方法!相关的知识,希望对你有一定的参考价值。
# PatternEditableBuilder
This Android utility is about making clickable colored spans within a `TextView` as painless and simple as possible! One common use case for this is building a Twitter or Facebook type app where **different words in a message have different meanings** and can be clicked to trigger an action. For example:
* Tweet items where "@foo" can be clicked to view a user's profile.
* Facebook posts where "Billy Jean" can be clicked to view a user.
* Slack messges where "#general" can be clicked to go to a different room.
## Usage
This utility assumes you have one or more `TextView` that are filled with text that you'd like to "spannify" based on different patterns. Suppose we have a `TextView` that contains the following totally unstyled text:
<img src="http://i.imgur.com/YarVGm9.png" width="500" />
### Linkify Pattern
Linkify all sub-strings within `TextView` that match a regular expression:
```java
new PatternEditableBuilder().
addPattern(Pattern.compile("\\@(\\w+)")).
into(textView);
```
This results in:
<img src="http://i.imgur.com/IX1M1Qt.png" width="500" />
### Linkify Pattern with Text Color
Linkify all sub-strings within `TextView` that match a regular expression and then set color:
```java
new PatternEditableBuilder().
addPattern(Pattern.compile("\\@(\\w+)"), Color.CYAN).
into(textView);
```
This results in:
<img src="http://i.imgur.com/w8tsGyS.png" width="500" />
### Linkify Pattern with Color and Click
Linkify all sub-strings within `TextView` that match a pattern and then set color, and click handler:
```java
new PatternEditableBuilder().
addPattern(Pattern.compile("\\@(\\w+)"), Color.BLUE,
new PatternEditableBuilder.SpannableClickedListener() {
@Override
public void onSpanClicked(String text) {
Toast.makeText(MainActivity.this, "Clicked username: " + text,
Toast.LENGTH_SHORT).show();
}
}).into(textView);
```
This results in:
<img src="http://i.imgur.com/OHFMMTc.gif" width="500" />
### Linkify with Custom Span Style
Linkify all sub-strings within `TextView` that match a pattern and then set custom styles:
```java
new PatternEditableBuilder().
addPattern(Pattern.compile("\\@(\\w+)"),
new PatternEditableBuilder.SpannableStyleListener() {
@Override
void onSpanStyled(TextPaint ds) {
// ds contains everything you need to style the span
ds.bgColor = Color.GRAY;
ds.linkColor = Color.MAGENTA;
}
}).into(textView);
```
and this results in:
<img src="http://i.imgur.com/xsec2zf.png" width="500" />
### Complete Example
This is a more complete example which matches both usernames and hashtags:
```java
new PatternEditableBuilder().
addPattern(Pattern.compile("\\@(\\w+)"), Color.GREEN,
new PatternEditableBuilder.SpannableClickedListener() {
@Override
public void onSpanClicked(String text) {
Toast.makeText(MainActivity.this, "Clicked username: " + text,
Toast.LENGTH_SHORT).show();
}
}).
addPattern(Pattern.compile("\\#(\\w+)"), Color.CYAN,
new PatternEditableBuilder.SpannableClickedListener() {
@Override
public void onSpanClicked(String text) {
Toast.makeText(MainActivity.this, "Clicked hashtag: " + text,
Toast.LENGTH_SHORT).show();
}
}).into(textView);
```
and this results in:
<img src="http://i.imgur.com/BwXtSCe.gif" width="500" />
## Attribution
Created by [Nathan Esquenazi](https://gist.github.com/nesquena) from CodePath in 2016.
## References
* <http://stackoverflow.com/questions/15851655/android-change-the-background-color-of-a-clickablespan-when-clicked>
* <http://stackoverflow.com/questions/20856105/change-the-text-color-of-a-single-clickablespan-when-pressed-without-affecting-o>
* <http://stackoverflow.com/questions/3282940/set-color-of-textview-span-in-android>
* <http://stackoverflow.com/questions/19750458/android-clickablespan-get-text-onclick>
* <http://stackoverflow.com/questions/5595785/highlight-on-clickablespan-click>
* <http://stackoverflow.com/questions/11903414/find-a-particular-regex-word-and-linkify-to-open-an-activity-in-android>
* <http://stackoverflow.com/questions/7570239/android-linkify-text-spannable-text-in-single-text-view-as-like-twitter-twee>
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.View;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
Create clickable spans within a TextView
made easy with pattern matching!
Created by: Nathan Esquenazi
Usage 1: Apply spannable strings to a TextView based on pattern
new PatternEditableBuilder().
addPattern(Pattern.compile("\\@(\\w+)")).
into(textView);
Usage 2: Apply clickable spans to a TextView
new PatternEditableBuilder().
addPattern(Pattern.compile("\\@(\\w+)"), Color.BLUE,
new PatternEditableBuilder.SpannableClickedListener() {
@Override
public void onSpanClicked(String text) {
// Do something here
}
}).into(textView);
See README for more details.
*/
public class PatternEditableBuilder {
// Records the pattern spans to apply to a TextView
ArrayList<SpannablePatternItem> patterns;
/* This stores a particular pattern item
complete with pattern, span styles, and click listener */
public class SpannablePatternItem {
public SpannablePatternItem(Pattern pattern, SpannableStyleListener styles, SpannableClickedListener listener) {
this.pattern = pattern;
this.styles = styles;
this.listener = listener;
}
public SpannableStyleListener styles;
public Pattern pattern;
public SpannableClickedListener listener;
}
/* This stores the style listener for a pattern item
Used to style a particular category of spans */
public static abstract class SpannableStyleListener {
public int spanTextColor;
public SpannableStyleListener() {
}
public SpannableStyleListener(int spanTextColor) {
this.spanTextColor = spanTextColor;
}
abstract void onSpanStyled(TextPaint ds);
}
/* This stores the click listener for a pattern item
Used to handle clicks to a particular category of spans */
public interface SpannableClickedListener {
void onSpanClicked(String text);
}
/* This is the custom clickable span class used
to handle user clicks to our pattern spans
applying the styles and invoking click listener.
*/
public class StyledClickableSpan extends ClickableSpan {
SpannablePatternItem item;
public StyledClickableSpan(SpannablePatternItem item) {
this.item = item;
}
@Override
public void updateDrawState(TextPaint ds) {
if (item.styles != null) {
item.styles.onSpanStyled(ds);
}
super.updateDrawState(ds);
}
@Override
public void onClick(View widget) {
if (item.listener != null) {
TextView tv = (TextView) widget;
Spanned span = (Spanned) tv.getText();
int start = span.getSpanStart(this);
int end = span.getSpanEnd(this);
CharSequence text = span.subSequence(start, end);
item.listener.onSpanClicked(text.toString());
}
widget.invalidate();
}
}
/* ----- Constructors ------- */
public PatternEditableBuilder() {
this.patterns = new ArrayList<>();
}
/* These are the `addPattern` overloaded signatures */
// Each allows us to add a span pattern with different arguments
public PatternEditableBuilder addPattern(Pattern pattern, SpannableStyleListener spanStyles, SpannableClickedListener listener) {
patterns.add(new SpannablePatternItem(pattern, spanStyles, listener));
return this;
}
public PatternEditableBuilder addPattern(Pattern pattern, SpannableStyleListener spanStyles) {
addPattern(pattern, spanStyles, null);
return this;
}
public PatternEditableBuilder addPattern(Pattern pattern) {
addPattern(pattern, null, null);
return this;
}
public PatternEditableBuilder addPattern(Pattern pattern, int textColor) {
addPattern(pattern, textColor, null);
return this;
}
public PatternEditableBuilder addPattern(Pattern pattern, int textColor, SpannableClickedListener listener) {
SpannableStyleListener styles = new SpannableStyleListener(textColor) {
@Override
public void onSpanStyled(TextPaint ds) {
ds.linkColor = this.spanTextColor;
}
};
addPattern(pattern, styles, listener);
return this;
}
public PatternEditableBuilder addPattern(Pattern pattern, SpannableClickedListener listener) {
addPattern(pattern, null, listener);
return this;
}
/* BUILDER METHODS */
// This builds the pattern span and applies to a TextView
public void into(TextView textView) {
SpannableStringBuilder result = build(textView.getText());
textView.setText(result);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
// This builds the pattern span into a `SpannableStringBuilder`
// Requires a CharSequence to be passed in to be applied to
public SpannableStringBuilder build(CharSequence editable) {
SpannableStringBuilder ssb = new SpannableStringBuilder(editable);
for (SpannablePatternItem item : patterns) {
Matcher matcher = item.pattern.matcher(ssb);
while (matcher.find()) {
int start = matcher.start();
int end = matcher.end();
StyledClickableSpan url = new StyledClickableSpan(item);
ssb.setSpan(url, start, end, 0);
}
}
return ssb;
}
}
以上是关于java PatternEditableBuilder - 在TextView中创建彩色可点击跨度的简便方法!的主要内容,如果未能解决你的问题,请参考以下文章