android如果重写onDraw实现一个类似TextView可以显示表情和链接的控件(一)

来源:互联网 发布:linux自启动脚本编写 编辑:程序博客网 时间:2024/05/01 13:57

先看效果图:


写一个超连接支持的对象:

/**作为超连接显示的对象*/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>

0 0