`

在EditText中插入表情图片 (CharacterStyle&SpannableString)

阅读更多

EditText通常用于显示文字,但有时候也需要在文字中夹杂一些图片,比如QQ中就可以使用表情图片,又比如需要的文字高亮显示等等,如何在android中也做到这样呢?
记得android中有个android.text包,这里提供了对文本的强大的处理功能。
添加图片主要用SpannableString和ImageSpan类:

Java代码  收藏代码
  1. Drawable drawable = getResources().getDrawable(id);  
  2.         drawable.setBounds(0 0 , drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());  
  3.         //需要处理的文本,[smile]是需要被替代的文本   
  4.         SpannableString spannable = new  SpannableString(getText().toString()+ "[smile]" );  
  5.         //要让图片替代指定的文字就要用ImageSpan   
  6.         ImageSpan span = new  ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);  
  7.         //开始替换,注意第2和第3个参数表示从哪里开始替换到哪里替换结束(start和end)   
  8. //最后一个参数类似数学中的集合,[5,12)表示从5到12,包括5但不包括12   
  9.         spannable.setSpan(span, getText().length(),getText().length()+"[smile]" .length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);    
  10.         setText(spannable);  
Drawable drawable = getResources().getDrawable(id);
		drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
		//需要处理的文本,[smile]是需要被替代的文本
		SpannableString spannable = new SpannableString(getText().toString()+"[smile]");
		//要让图片替代指定的文字就要用ImageSpan
        ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
        //开始替换,注意第2和第3个参数表示从哪里开始替换到哪里替换结束(start和end)
//最后一个参数类似数学中的集合,[5,12)表示从5到12,包括5但不包括12
        spannable.setSpan(span, getText().length(),getText().length()+"[smile]".length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);  
        setText(spannable);



将需要的文字高亮显示:

Java代码  收藏代码
  1. public   void  highlight( int  start, int  end){  
  2.         SpannableStringBuilder spannable=new  SpannableStringBuilder(getText().toString()); //用于可变字符串   
  3.         ForegroundColorSpan span=new  ForegroundColorSpan(Color.RED);  
  4.         spannable.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  5.         setText(spannable);  
  6.     }  
public void highlight(int start,int end){
		SpannableStringBuilder spannable=new SpannableStringBuilder(getText().toString());//用于可变字符串
		ForegroundColorSpan span=new ForegroundColorSpan(Color.RED);
		spannable.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		setText(spannable);
	}


加下划线:

Java代码  收藏代码
  1. public   void  underline( int  start, int  end){  
  2.         SpannableStringBuilder spannable=new  SpannableStringBuilder(getText().toString());  
  3.         CharacterStyle span=new  UnderlineSpan();  
  4.         spannable.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  5.         setText(spannable);  
  6.     }  
public void underline(int start,int end){
		SpannableStringBuilder spannable=new SpannableStringBuilder(getText().toString());
		CharacterStyle span=new UnderlineSpan();
		spannable.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		setText(spannable);
	}


组合运用:

Java代码  收藏代码
  1. SpannableStringBuilder spannable= new  SpannableStringBuilder(getText().toString());  
  2.         CharacterStyle span_1=new  StyleSpan(android.graphics.Typeface.ITALIC);  
  3.         CharacterStyle span_2=new  ForegroundColorSpan(Color.RED);  
  4.         spannable.setSpan(span_1, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  5.         spannable.setSpan(span_2, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  6.         setText(spannable);  
SpannableStringBuilder spannable=new SpannableStringBuilder(getText().toString());
		CharacterStyle span_1=new StyleSpan(android.graphics.Typeface.ITALIC);
		CharacterStyle span_2=new ForegroundColorSpan(Color.RED);
		spannable.setSpan(span_1, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		spannable.setSpan(span_2, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		setText(spannable);

 

Java代码  收藏代码
  1. /**  
  2.      * 带有\n换行符的字符串都可以用此方法显示2种颜色  
  3.      * @param text  
  4.      * @param color1  
  5.      * @param color2  
  6.      * @return  
  7.      */   
  8.     public  SpannableStringBuilder highlight(String text, int  color1, int  color2, int  fontSize){  
  9.         SpannableStringBuilder spannable=new  SpannableStringBuilder(text); //用于可变字符串   
  10.         CharacterStyle span_0=null ,span_1= null ,span_2;  
  11.         int  end=text.indexOf( "\n" );  
  12.         if (end==- 1 ){ //如果没有换行符就使用第一种颜色显示   
  13.             span_0=new  ForegroundColorSpan(color1);  
  14.             spannable.setSpan(span_0, 0 , text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  15.         }else {  
  16.             span_0=new  ForegroundColorSpan(color1);  
  17.             span_1=new  ForegroundColorSpan(color2);  
  18.             spannable.setSpan(span_0, 0 , end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  19.             spannable.setSpan(span_1, end+1 , text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  20.               
  21.             span_2=new  AbsoluteSizeSpan(fontSize); //字体大小   
  22.             spannable.setSpan(span_2, end+1 , text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  23.         }  
  24.         return  spannable;  
  25.     }  
/**
	 * 带有\n换行符的字符串都可以用此方法显示2种颜色
	 * @param text
	 * @param color1
	 * @param color2
	 * @return
	 */
	public SpannableStringBuilder highlight(String text,int color1,int color2,int fontSize){
		SpannableStringBuilder spannable=new SpannableStringBuilder(text);//用于可变字符串
		CharacterStyle span_0=null,span_1=null,span_2;
		int end=text.indexOf("\n");
		if(end==-1){//如果没有换行符就使用第一种颜色显示
			span_0=new ForegroundColorSpan(color1);
			spannable.setSpan(span_0, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		}else{
			span_0=new ForegroundColorSpan(color1);
			span_1=new ForegroundColorSpan(color2);
			spannable.setSpan(span_0, 0, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
			spannable.setSpan(span_1, end+1, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
			
			span_2=new AbsoluteSizeSpan(fontSize);//字体大小
			spannable.setSpan(span_2, end+1, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		}
		return spannable;
	}




以上实际都是Html.fromHtml(html)的代码实现形式。

另外有个问题:如何让一个TextView中的关键字高亮显示?
http://www.eoeandroid.com/forum.php?mod=viewthread&tid=57880&page=1&extra=#pid558440
解决如下:

Java代码  收藏代码
  1. /**  
  2.      * 关键字高亮显示  
  3.      * @param target 需要高亮的关键字  
  4.      */   
  5.     public   void  highlight(String target){  
  6.         String temp=getText().toString();  
  7.         SpannableStringBuilder spannable = new  SpannableStringBuilder(temp);  
  8.         CharacterStyle span=null ;  
  9.           
  10.         Pattern p = Pattern.compile(target);  
  11.         Matcher m = p.matcher(temp);  
  12.         while  (m.find()) {  
  13.             span = new  ForegroundColorSpan(Color.RED); //需要重复!   
  14.             spannable.setSpan(span, m.start(), m.end(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  15.         }  
  16.         setText(spannable);  
  17.     }  
/**
	 * 关键字高亮显示
	 * @param target 需要高亮的关键字
	 */
	public void highlight(String target){
		String temp=getText().toString();
		SpannableStringBuilder spannable = new SpannableStringBuilder(temp);
		CharacterStyle span=null;
		
		Pattern p = Pattern.compile(target);
		Matcher m = p.matcher(temp);
		while (m.find()) {
			span = new ForegroundColorSpan(Color.RED);//需要重复!
			spannable.setSpan(span, m.start(), m.end(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		}
        setText(spannable);
	}


循环太慢,不知道有没有简单高效的方法?


付继承关系:







扩展学习:
android开发:TextView中显示HTML和图片
最近有人咨询我如何在TextView中显示<img src=""/> html标签内的图片,大家都知道,在TextView中显示HTML内容的方法如下所示:

Java代码  收藏代码
  1. TextView description=(TextView)findViewById(R.id.description);  
  2. description.setText(Html.fromHtml(item.getDescription()));  
TextView description=(TextView)findViewById(R.id.description);
description.setText(Html.fromHtml(item.getDescription()));


如果HTML中有图片的话,显示出来的图片会被一个小框取代,那么怎么样才能看到图片呢?查看了一下API,android.text.Html 还还有另一个方法:Html.fromHtml(String source,ImageGetter imageGetter,TagHandler tagHandler),这个方法使用如下所示:

Java代码  收藏代码
  1. ImageGetter imgGetter =  new  Html.ImageGetter() {  
  2.         public  Drawable getDrawable(String source) {  
  3.             Drawable drawable = null ;  
  4.             Log.d("Image Path" , source);  
  5.             URL url;  
  6.             try  {  
  7.                 url = new  URL(source);  
  8.                 drawable = Drawable.createFromStream(url.openStream(), "" );  
  9.             } catch  (Exception e) {  
  10.                 return   null ;  
  11.             }  
  12.             drawable.setBounds(0 0 , drawable.getIntrinsicWidth(), drawable  
  13.                     .getIntrinsicHeight());  
  14.             return  drawable;  
  15.         }  
  16.     };  
  17. .........  
  18. TextView description=(TextView)findViewById(R.id.description);  
  19. description.setText(Html.fromHtml(item.getDescription(),imgGetter,null ));  
ImageGetter imgGetter = new Html.ImageGetter() {
		public Drawable getDrawable(String source) {
			Drawable drawable = null;
			Log.d("Image Path", source);
			URL url;
			try {
				url = new URL(source);
				drawable = Drawable.createFromStream(url.openStream(), "");
			} catch (Exception e) {
				return null;
			}
			drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable
					.getIntrinsicHeight());
			return drawable;
		}
	};
.........
TextView description=(TextView)findViewById(R.id.description);
description.setText(Html.fromHtml(item.getDescription(),imgGetter,null));


怎么样?很简单,第二个参数TagHandler是干什么的呢?从名称我们就知道是处理HTML中的标签的,比如说遇到某个标签就把它替换为….之类的操 作都可以通过TagHandler来处理,呵呵,我可没试过哦,瞎猜的,程序员一定要发挥充分的想像力,自己去试一下吧!

最后我要说的是,如果你的图片是从网络上获取的,那么你一定不要用这种方法显示一张图片,因为这是最垃圾的办法,你的程序会经常被卡死。

那么有没有更好的方法呢?

也许不是最好,但我建议您可以使用WebView来显示HTML内容。

分享到:
评论
1 楼 final_ 2011-09-15  
其实Html.fromHtml(item.getDescription())这种方法很卡。例如采用html的方法给一段字加下划线,并且修改颜色等。如果把这段字放到listView中,发现listView就会拖动的很差劲,不知道spannableString会不会存在这个效率问题,楼主可否给个答案?

相关推荐

    Android输入Emoji表情的demo

    在Android中,EditText的`addTextChangedListener`可以监听文本变化,当检测到用户触发了表情选择,可以通过`SpannableStringBuilder`或`SpannableString`对文本进行格式化,添加`CharacterStyle`子类,如`ImageSpan...

    Android项目 匹配Text里面的Emoji 和 QQ表情

    在Android上展示QQ表情,通常需要将这些图片资源集成到项目中,并通过特定的解析和显示逻辑来插入到TextView或者EditText中。 接下来,我们将讨论如何在Android项目中处理Text中的Emoji和QQ表情。 1. **处理Emoji*...

    安卓开发-前面部分可以编辑后面部分不可编辑的EditText.zip.zip

    在Android开发中,EditText是用于用户输入文本的基本控件,它允许用户在界面上进行文本交互。然而,有时候我们可能需要实现一个特殊的EditText,它的功能是前面部分可编辑,后面部分不可编辑。这样的需求通常出现在...

    Android图文混排发帖

    当我们想要在`editText`中插入图片时,`ImageSpan`就是关键。我们需要先将图片转换为`Bitmap`,然后创建`ImageSpan`对象,最后将其添加到`SpannableString`中对应的位置。 `Spannable`和`Spanned`接口是Android处理...

    imageSpan图片替换

    在Android开发中,`ImageSpan` 是一个非常实用的组件,它允许我们在`EditText`或者`TextView`中插入图片,让文本与图像相结合,提升用户体验。这个“imageSpan图片替换”话题主要涉及到如何动态地在文本中插入从...

    Android 原生实现图文混排编辑器

    - **本地图片**:使用`Intent`调用系统图库或者自定义相机获取图片,然后通过`Bitmap`读取图片并转换为Base64字符串,插入到`EditText`中。可以使用`ImageSpan`将图片转换为可插入文本的格式。 - **网络图片**:...

    Android代码编辑器源码

    此外,可能会用到`SpannableString`或`SpannableStringBuilder`来存储和处理带有样式信息的文本,它们允许在文本中插入各种`CharacterStyle`子类,如`ForegroundColorSpan`和`BackgroundColorSpan`,分别用于设置...

    Android编写简单的聊天室应用

    `ImageSpan`则用于在`SpannableString`中插入图像,它继承自`CharacterStyle`,可以将图像作为字符插入到文本中。 核心代码中,开发者首先定义了一个名为`ExpressionUtil`的工具类,这个类中包含了两个关键方法:`...

    Android高级应用源码-Android富文本编辑器源码+服务端.zip

    富文本编辑器还支持图片插入,一般通过`ImageGetter`接口获取图片资源,并使用`SpannableString`将其插入文本中。同时,可能需要处理图片的上传和本地存储。 二、服务端实现 2.1 数据传输协议 在服务端,需要处理...

    textview填空题

    在Android开发中,创建一个`TextView`填空题的功能是一项常见的需求,特别是在教育或游戏应用中。这个功能允许用户在预设的文字中填写缺失的部分,然后显示他们输入的内容。下面我们将详细探讨如何实现这样一个功能...

    Android 富文本编辑,基于RecyclerView

    在Android应用开发中,富文本编辑是一个常见的需求,它允许用户在编辑框中插入格式化的文本,如加粗、斜体、下划线、不同颜色的字体等。本篇文章将详细探讨如何在Android环境中实现一个基于RecyclerView的富文本编辑...

    Multiple-select-edittext:多选编辑文本

    在Android开发中,"多选编辑文本"(Multiple-select-edittext)是一种常见的用户界面组件,它允许用户在文本框中选择多个条目,通常用于创建筛选条件、设置偏好或者进行多选项选择。这个主题主要涉及Java编程语言,...

Global site tag (gtag.js) - Google Analytics