先看效果图:
写一个超连接支持的对象:
/**作为超连接显示的对象*/
public class LinkInfo implements Comparable<LinkInfo>{
private String content;
private String type;
private String id;
private boolean bIsFace = false;
private boolean bSelected = false;
public static final String EMAIL = "Email";
public static final String WEBURL = "WebUrl";
public static final String PHONENUMBER = "PhoneNumber";
private int startIndex;
private int endIndex;
}
对于以下的字符串做这样的解析:
String s = "(#大笑)%$%$%3434343434343$%$%youjiancau@163.com$dfsfsfsdffds^15959224872)dfsfdsafsaf@153.cn&&fefrewafrewfjwio(fsfsfsd@tre.com.cn()()()www.baidu.com3242343243www.sohu.com@afjiofjfjaof";
private static Pattern EMAIL_PATTERN = Patterns.EMAIL_ADDRESS;
private static Pattern PHONE_PATTERN = Patterns.PHONE;
private static Pattern WEBURL_PATTERN = Patterns.WEB_URL;
public static ArrayList<LinkInfo> parseStr(String strLink) {
if(TextUtils.isEmpty(strLink)){
return null;
}
ArrayList<LinkInfo> resultList = new ArrayList<LinkInfo>();
ArrayList<LinkInfo> infoList = null;
try{
infoList = new ArrayList<LinkInfo>();
<span style="white-space:pre"> </span><strong> Matcher matcher = EMAIL_PATTERN.matcher(strLink); //寻找字符串里的email的位置</strong>
int begin = 0;
while(matcher.find()) {
int start = matcher.start();
int end = matcher.end();
LinkInfo info = new LinkInfo();
info.setStartIndex(start);
info.setEndIndex(end);
info.setContent(matcher.group());
info.setType(LinkInfo.EMAIL);
infoList.add(info);
}
<strong>Matcher matcher1 = PHONE_PATTERN.matcher(strLink);//寻找字符串里的号码的位置</strong>
while(matcher1.find()) {
int start = matcher1.start();
int end = matcher1.end();
LinkInfo info = new LinkInfo();
info.setStartIndex(start);
info.setEndIndex(end);
info.setContent(matcher1.group());
info.setType(LinkInfo.PHONENUMBER);
infoList.add(info);
}
//(#大笑)
Pattern pattern = Pattern.compile("(\\(#\\S{1,2}\\))");
Matcher matcher2 = pattern.matcher(strLink);
while(matcher2.find()) {
int start = matcher2.start();
int end = matcher2.end();
System.out.println("====start="+start+"end="+end+"match group="+matcher2.group());
LinkInfo info = new LinkInfo();
info.setStartIndex(start);
info.setEndIndex(end);
info.setContent(matcher2.group());
info.setFace(true);
infoList.add(info);
}
Collections.sort(infoList);
int last = 0;
for(int i=0;i<infoList.size();i++) {
LinkInfo info = infoList.get(i);
if(begin != info.getStartIndex()){
LinkInfo infoBefore = new LinkInfo();
infoBefore.setContent(strLink.substring(begin,info.getStartIndex()));
resultList.add(infoBefore);
}
resultList.add(info);
begin = info.getEndIndex();
last = info.getEndIndex();
}
if(last < strLink.length()) {
LinkInfo info = new LinkInfo();
info.setContent(strLink.substring(last,strLink.length()));
resultList.add(info);
}
}catch(Exception ex){
ex.printStackTrace();
}
return resultList;
}
activity的Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/white" >
<include
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:id="@+id/header"
layout="@layout/news_header" />
<RelativeLayout
android:id="@+id/title"
android:layout_above="@id/header"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:background="@drawable/white"
android:gravity="center_horizontal" >
<com.kaixin001.view.IntroView
android:id="@+id/news_item_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="20dp"
android:enabled="true"
android:textColor="@drawable/black"
android:textSize="16sp"
android:textStyle="bold" />
</RelativeLayout>
</RelativeLayout>
IntroView有这样一个方法来加载字符串:
<pre name="code" class="java">public class IntroView extends TextView {
private ArrayList<LinkInfo> titleList;
private int displayWidth = 0;
private float displayHeight = 0;
private float curLen = 0;
private Bitmap starBmp;
private Bitmap selectedBmp;
private float posX = 0;
private float posY = 0;
private LinkInfo curInfo;//当前点击的Link对象
private OnClickLinkListener Listener;
private String mFaceType = MSG_FACE_TYPE;
public static final String MSG_FACE_TYPE = "msgtype";
public static final String STATUS_FACE_TYPE = "statustype";
public IntroView(Context context) {
super(context);
}
public IntroView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public IntroView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setTitleList(ArrayList<LinkInfo> titleList){
this.titleList = titleList;
displayHeight = 0;
requestLayout();
}
}<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family:Arial, Helvetica, sans-serif;">activity里这样来调用:</span>
<span style="font-family:Arial, Helvetica, sans-serif;"></span>
IntroView news_item_text = (IntroView)findViewById(R.id.news_item_text);
//不支持字符串里有\n
String s = "(#大笑)%$%$%3434343434343$%$%youjiancau@163.com$dfsfsfsdffds^15959224872)dfsfdsafsaf@153.cn&&fefrewafrewfjwio(fsfsfsd@tre.com.cn()()()www.baidu.com3242343243www.sohu.com@afjiofjfjaof";
news_item_text.setTitleList(ParseNewsInfoUtil.parseStr(s));
news_item_text.setOnClickLinkListener(this);
<span style="font-family:Arial, Helvetica, sans-serif;">
</span>
</pre><pre code_snippet_id="447070" snippet_file_name="blog_20140810_12_4943450" name="code" class="java"><span style="font-family: Arial, Helvetica, sans-serif;">IntroView的主题思想是在onMeasure里的measureWidth和measureHeight时来获取ArrayList<LinkInfo> titleList每个LinkInfo的位置信息,并获取这个IntroView的高度和宽度,</span>
然后onDraw的时候通过循环来绘制titleList的每个LinkInfo
</pre><pre code_snippet_id="447070" snippet_file_name="blog_20140810_15_8956611" name="code" class="java"><strong><span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
<span style="white-space:pre"> </span>super.onMeasure(widthMeasureSpec, heightMeasureSpec);
<span style="white-space:pre"> </span>try{
<span style="white-space:pre"> </span>int width = measureWidth(widthMeasureSpec);
<span style="white-space:pre"> </span>int height = measureHeight(heightMeasureSpec);
<span style="white-space:pre"> </span>setMeasuredDimension(width, height);
<span style="white-space:pre"> </span>}catch(Exception ex){
<span style="white-space:pre"> </span>ex.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}</strong>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;"> <span style="white-space:pre"> </span></span><pre name="code" class="java"> private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int initialWidth = getPaddingLeft() + getPaddingRight();
int width = initialWidth;
int maxWidth = 0;
TextPaint tempPaint = null;
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
if (tempPaint == null) {
tempPaint = new TextPaint();
tempPaint.setStyle(Style.FILL);
tempPaint.setAntiAlias(true);
tempPaint.setTextSize(getTextSize());
}
if (titleList != null && titleList.size() > 0) {
maxWidth = specSize;
int size = titleList.size();
forLable:
for (int i = 0; i < size; i++) {
LinkInfo info = titleList.get(i);
if (info.isFace()) {
Bitmap faceBmp = null;
if(mFaceType == MSG_FACE_TYPE) {
faceBmp = MessageFaceModel.getInstance().getFaceIcon(info.getContent());
}
if (faceBmp != null) {
int wSize = faceBmp.getWidth() + 4;
<strong> if (width + wSize >= maxWidth)</strong> { //这里表示已经计算的宽度大于控件的宽度,那就返回maxWidth就可以了
width = maxWidth;
break forLable;
}
width += wSize;
}
continue;
}
String text = info.getContent();
text = text.replaceAll("\n", " "); //因为该控件不支持\n,所以把这个换成空格
if (!TextUtils.isEmpty(text)) {
float wSize = tempPaint.measureText(text);
if (width + wSize >= maxWidth) {
width = maxWidth;
break forLable;
}
width += wSize;
}
}
}
result = width;
}
displayWidth = result;
return result;
}
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;"> </span>