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
- android如果重写onDraw实现一个类似TextView可以显示表情和链接的控件(一)
- android如果重写onDraw实现一个类似TextView可以显示表情和链接的控件(二)
- Android TextView重写onMeasure和onDraw显示无拉伸图片(含实现代码链接)
- 在EditText和TextView显示表情图片(类似QQ表情)
- android textview 显示表情和文字 表情带超链接
- 1、重写TextView的onDraw方法
- android如果给TextView或EditText的email链接加下划线,并在点击在email连接上可以弹框显示
- richTextBox如何实现输入指定的字符显示一个表情图标?类似QQ那样?
- android 自己实现的一个类似expandablelistview的一个控件
- android 实现类似qq表情
- Android开发(16)-TextView显示表情图像和文字
- Android开发(16)-TextView显示表情图像和文字
- Android开发(16)-TextView显示表情图像和文字
- Android开发 TextView显示表情图像和文字
- Android 自定义View(一) 介绍和一个简单TextView显示
- android 显示表情 (一)
- iOS swift 实现图文混排 emoji小表情和文字都显示在一个textview中
- Android: 实现类似QQ、微信的表情输入键盘
- 云计算读书笔记(一)之Google云计算技术GFS
- 问题描述: Android SDK Manager 无法下载更新,或者更新速度超慢,或者待安装包列表不显示 解决方法: 第一步:修改hosts文件 修改后的hosts 文件内容为
- 【BFS&&优先队列】HDU 1180 诡异的楼梯
- "app_name" is not translated in af, am, ar, bg, ca, cs, da, de, el, en-rGB,
- 3种消费者生产者实现方式 {signal, blockingQueue, synchronized }
- android如果重写onDraw实现一个类似TextView可以显示表情和链接的控件(一)
- 快速获取联系人数据
- 机房重构总结
- 游戏玩到这种程度,酱紫真的好吗?
- const
- poj 2942&&uva 3523 Knights of the Round Table(图的连通性)
- 我读C++ Primer - 基本类型与变量
- Clojure笔记——apply
- web开发设计--JS的innerHTML/display属性