zoukankan      html  css  js  c++  java
  • android假设重写onDraw实现一个相似TextView能够显示表情和链接的控件(一)

    先看效果图:


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

    /**作为超连接显示的对象*/
    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);
    //不支持字符串里有
    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("
    ", " "); //由于该控件不支持
    ,所以把这个换成空格
                        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>
    
    

  • 相关阅读:
    Cesium视角
    Cesium删除特定的实体
    cesium之CLAMPED
    JavaScript:使用setAttribute()改变网页中标签的onclick属性
    atoi()函数及其实现
    寻找数组中的第二大数
    字符串函数之strcpy
    互换两个变量(不使用中间变量)
    寻找兄弟单词(2012.5.6百度实习)
    大数据量的存储分表常见算法(转)
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5302739.html
Copyright © 2011-2022 走看看