最近做了一些东西,涉及到比较重要些的技术点有:TextView正则匹配、文本链接、点击链接页面跳转,外加一个链接文本去掉默认的下划线。其实大部分都是从技术文档上学到的,应用了一下。便于以后查看,特别总结一下。如有更好的方法意见,望指点。
一、重写ClickableSpan类,点击跳转,并去掉默认的下划线
If an object of this type is attached to the text of a TextView with a movement method of LinkMovementMethod, the affected spans of text can be selected. If clicked, the onClick(View) method will be called.
默认超链接都带下划线的,重写ClickableSpan 去掉下划线:
private class MyClickSpan extends ClickableSpan {
String text;
public NoLineClickSpan(String text) {
super();
this.text = text;
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ds.linkColor); //设置链接的文本颜色
ds.setUnderlineText(false); //去掉下划线
}
@Override
public void onClick(View widget) {
processHyperLinkClick(text); //点击超链接时调用
}
}
把超链接文本封装为MyClickSpan 对象,并添加到TextView中;
TextView tv = findViewById(R.id.tv_click);
SpannableString spStr = new SpannableString("试试看http://2711822222.163.com");
MyClickSpan clickSpan = new MyClickSpan (); //设置超链接
spStr.setSpan(clickSpan, 0, str.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
tv.append(spStr);
tv.setMovementMethod(LinkMovementMethod.getInstance());//设置超链接为可点击状态
参考:http://orgcent.com/android-textview-no-underline-hyperlink/
二、微博中匹配@ 和#xxx#为文本链接,点击链接至此人页面。
显示文本的activity:
TextView txt = (TextView) findViewById(R.id.txt);
extractMention2Link(txt);
public static void extractMention2Link(TextView v) {
v.setAutoLinkMask(0);
Pattern pattern = Pattern.compile("@(\\w+?)(?=\\W|$)");
String scheme = String.format("%s/?%s=", Defs.SCHEMA, Defs.PARAM_UID);
Linkify.addLinks(v, pattern, scheme, null, new TransformFilter() {
@Override
public String transformUrl(Matcher match, String url) {
Log.d(TAG, match.group(1));
return match.group(1); // 要传到到此人页面的东西
}
});
Pattern pattern1 = Pattern.compile("#(\\w+?)#");
String scheme1 = String.format("%s/?%s=", Defs.SCHEMA1, Defs.PARAM_UID);
Linkify.addLinks(v, pattern1, scheme1, null, new TransformFilter() {
@Override
public String transformUrl(Matcher match, String url) {
Log.d(TAG, match.group(1));
return match.group(1); // 要传到到此人页面的东西
}
});
}
Manifest.xml中,设置要跳转到的Activity
<activity android:name=".Profile" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="devdiv" android:host="sina_profile"/>
</intent-filter>
</activity>
<activity android:name=".Profile1" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="devdiv" android:host="sina_profile1"/>
</intent-filter>
</activity>
Defs.java
public class Defs {
public static final String SCHEMA = "devdiv://sina_profile";
public static final String SCHEMA1 = "devdiv://sina_profile1";
public static final String PARAM_UID = "uid";
}
Profile.java
public class Profile extends Activity {
private static final String TAG = "Profile";
private static final Uri PROFILE_URI = Uri.parse(Defs.SCHEMA);
private String uid;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
extractUidFromUri();
setTitle("Profile:Hello, " + uid);
}
private void extractUidFromUri() {
Uri uri = getIntent().getData();
if (uri != null && PROFILE_URI.getScheme().equals(uri.getScheme())) {
uid = uri.getQueryParameter(Defs.PARAM_UID);
Log.d(TAG, "uid from url: " + uid);
}
}
}
Profile1.java
public class Profile1 extends Activity {
private static final String TAG = "Profile";
private static final Uri PROFILE_URI = Uri.parse(Defs.SCHEMA);
private String uid;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
extractUidFromUri();
setTitle("Profile1:Hello, " + uid);
}
private void extractUidFromUri() {
Uri uri = getIntent().getData();
if (uri != null && PROFILE_URI.getScheme().equals(uri.getScheme())) {
uid = uri.getQueryParameter(Defs.PARAM_UID);
Log.d(TAG, "uid from url: " + uid);
}
}
}
参考自:http://www.devdiv.com/forum.php?mod=viewthread&tid=35696&extra=&ordertype=2&page=1
实例一:
Textview里匹配的文字有不同的颜色显示,可点击链接
SpannableString checkInSpanStr = new SpannableString("xxxxxxxxxx")
hilightAtUserName(checkInSpanStr);
tvContent.setText(checkInSpanStr);
tv.setMovementMethod(LinkMovementMethod.getInstance());//设置超链接为可点击状态
private void hilightAtUserName(SpannableString spannableStr) {
Pattern pattern = Pattern.compile(ConstantsConfig.AT_USER_NAME_REG_EXP);//正则匹配
Matcher matcher = pattern.matcher(spannableStr);
int start, end;
while (matcher.find()) {
start = matcher.start();
end = matcher.end();
spannableStr.setSpan(new ForegroundColorSpan(0xFF0099FA), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
实例二:
已知String参数为 :before<at username="aaa" name="a" id="25"> :第一个 </at>after<at username="bbb" name="b" id="26">: </at>over
最后显示:before @aaa 第一个 after @bbb over
点击 aaa 传递25 点击bbb传递26 到个人页
调用:
String strA=RevoPubAccess.getUsefulText(commentContent);
String strDisplay =RevoPubAccess.getDisplayText(strA);
SpannableString checkInSpanStr = new SpannableString(strDisplay);
RevoPubAccess.setTextLink(context, strA, checkInSpanStr);
listItemView.mCommenttext.setText(checkInSpanStr);
listItemView.mCommenttext.setMovementMethod(LinkMovementMethod.getInstance());
/**
* change <at </at> text to @ username id text
* @param ori before<at username="aaa" name="a" id="25"> :第一个 </at>after<at username="bbb" name="b" id="25">: </at>over
* @return before@aaa :25 第一个 after@bbb :25 over
*/
public static final String getUsefulText(String ori) {
StringBuilder rs = new StringBuilder();
int index = 0;
Pattern pattern = Pattern.compile("<at.+?</at>");
Matcher matcher = pattern.matcher(ori);
while (matcher.find()) {
rs.append(ori.substring(index, matcher.start()));
Pattern pattern1 = Pattern.compile("username=\".+?\"");
Matcher matcher1 = pattern1.matcher(matcher.group());
if (matcher1.find()) {
rs.append("@"+matcher1.group().replaceAll("username\\s*=\\s*", "").replaceAll("\"", ""));
} else {
// rs.append("没有username属性");
}
Pattern pattern2 = Pattern.compile("id=\".+?\"");
Matcher matcher2 = pattern2.matcher(matcher.group());
if (matcher2.find()) {
rs.append(":"+matcher2.group().replaceAll("id\\s*=\\s*", "").replaceAll("\"", "")+" ");
} else {
// rs.append("没有id属性");
}
Pattern pattern3 = Pattern.compile(":.*\\s");
Matcher matcher3 = pattern3.matcher(matcher.group());
if (matcher3.find()) {
// Log.e("3", matcher3.group());
rs.append(matcher3.group().replaceAll(":", ""));
} else {
// rs.append("没有texttent属性");
}
index = matcher.end();
}
rs.append(ori.substring(index, ori.length()));
Log.e("-----", ori);
Log.e("-----", rs.toString());
return rs.toString();
}
/**
* get the @username text for display
* @param usefulText before@aaa :25 第一个 after@bbb :25 over
* @return
*/
public static final String getDisplayText(String usefulText) {
StringBuilder rs = new StringBuilder();
int index = 0;
Pattern pattern = Pattern.compile("@.+?\\s");
Matcher matcher = pattern.matcher(usefulText);
while (matcher.find()) {
rs.append(usefulText.substring(index, matcher.start()));
Pattern pattern1 = Pattern.compile("username=\".+?\"");
Matcher matcher1 = pattern1.matcher(matcher.group());
// if (matcher1.find()) {
// rs.append("@"+matcher1.group().replaceAll("username\\s*=\\s*", "").replaceAll("\"", ""));
// } else {
// // rs.append("没有username属性");
// }
String[]aa=matcher.group().split(":");
rs.append(aa[0]+" ");
index = matcher.end();
}
rs.append(usefulText.substring(index, usefulText.length()));
return rs.toString();
}
public static final void setTextLink(Context con, String userfulText, SpannableString checkInSpanStr)
{
Log.e("checkInSpanStr", checkInSpanStr.toString());
Pattern pattern = Pattern.compile("@.+?\\s");
Matcher matcher = pattern.matcher(checkInSpanStr);
while (matcher.find()) {
String id = "" ;
// Log.e("3", matcher.group());
Pattern pattern1 = Pattern.compile(matcher.group().replaceAll("\\s", "")+":.+?\\s");
Matcher matcher1 = pattern1.matcher(userfulText);
if(matcher1.find())
{
id=matcher1.group().replaceAll("@.+?:", "");
Log.e("revoId", id);
}
final String revoId=id;
checkInSpanStr.setSpan(new RevoClickSpan(con, revoId) , matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);//Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
//
}
}
/**
* remove underline and jump to mypage
* @author Lyra
* 2012.4.20
*/
public class RevoClickSpan extends ClickableSpan {
Context mContext;
String mId;
@Override
public void onClick(View widget) {
Log.e("click", mId);
Intent i= new Intent (mContext,MyPage.class);
i.putExtra(Base.WHOSEID, mId);
mContext.startActivity(i);
}
public RevoClickSpan(Context con, String id) {
super();
this.mContext = con;
this.mId = id;
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.RED);//设置连接的文本颜色
ds.setUnderlineText(false); //去掉下划线
}
}
另外:以下的博文很不错,可以参考:
http://www.2cto.com/kf/201109/106431.html
http://zhangning290.iteye.com/blog/1134286
http://www.cnblogs.com/ryan1012/archive/2011/07/12/2104087.html
http://blog.csdn.net/tianqixin/article/details/6785457