Android UI【android 仿微信、QQ聊天,带表情,可翻页,带翻页拖动缓冲】



如题,这是公司项目的一个功能模块,先上个效果图:


其次大致说说原理:

1,首先判断输入的字符,是否包含表情的文字,比如   这个表情对应的文件名为 emoji_1.png,它对应的文字描述 : [可爱],如果我们在输出的是输出这么一句话:老婆,我想你了。  那么我们对应的根本文字就是:老婆,我想你了[可爱]


2,具体的转换过程就是用正则表达式比配文字中是否含有[xxx]这类的文字,如果有,那么我们就根据拿到的[xxx]找到它对应的资源文件id,当然这其中有一个关系表,看你怎么处理这个关系了。最后将其用SpannableString替换成文字,表面上显示有图片,其实TextView里的text依然是:老婆,我想你了[可爱]。这个过程明白么?


下面贴上DEMO工程的结构:


再贴上几个重要的类:

  1. package com.example.facedemo;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6. import java.util.regex.Matcher;  
  7. import java.util.regex.Pattern;  
  8.   
  9. import android.content.Context;  
  10. import android.graphics.Bitmap;  
  11. import android.graphics.BitmapFactory;  
  12. import android.text.Spannable;  
  13. import android.text.SpannableString;  
  14. import android.text.TextUtils;  
  15. import android.text.style.ImageSpan;  
  16. import android.util.Log;  
  17.   
  18. /** 
  19.  *  
  20.  ******************************************  
  21.  * @author 廖乃波 
  22.  * @文件名称 : FaceConversionUtil.java 
  23.  * @创建时间 : 2013-1-27 下午02:34:09 
  24.  * @文件描述 : 表情轉換工具 
  25.  ******************************************  
  26.  */  
  27. public class FaceConversionUtil {  
  28.   
  29.     /** 每一页表情的个数 */  
  30.     private int pageSize = 20;  
  31.   
  32.     private static FaceConversionUtil mFaceConversionUtil;  
  33.   
  34.     /** 保存于内存中的表情HashMap */  
  35.     private HashMap<String, String> emojiMap = new HashMap<String, String>();  
  36.   
  37.     /** 保存于内存中的表情集合 */  
  38.     private List<ChatEmoji> emojis = new ArrayList<ChatEmoji>();  
  39.   
  40.     /** 表情分页的结果集合 */  
  41.     public List<List<ChatEmoji>> emojiLists = new ArrayList<List<ChatEmoji>>();  
  42.   
  43.     private FaceConversionUtil() {  
  44.   
  45.     }  
  46.   
  47.     public static FaceConversionUtil getInstace() {  
  48.         if (mFaceConversionUtil == null) {  
  49.             mFaceConversionUtil = new FaceConversionUtil();  
  50.         }  
  51.         return mFaceConversionUtil;  
  52.     }  
  53.   
  54.     /** 
  55.      * 得到一个SpanableString对象,通过传入的字符串,并进行正则判断 
  56.      *  
  57.      * @param context 
  58.      * @param str 
  59.      * @return 
  60.      */  
  61.     public SpannableString getExpressionString(Context context, String str) {  
  62.         SpannableString spannableString = new SpannableString(str);  
  63.         // 正则表达式比配字符串里是否含有表情,如: 我好[开心]啊  
  64.         String zhengze = "\\[[^\\]]+\\]";  
  65.         // 通过传入的正则表达式来生成一个pattern  
  66.         Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE);  
  67.         try {  
  68.             dealExpression(context, spannableString, sinaPatten, 0);  
  69.         } catch (Exception e) {  
  70.             Log.e("dealExpression", e.getMessage());  
  71.         }  
  72.         return spannableString;  
  73.     }  
  74.   
  75.     /** 
  76.      * 添加表情 
  77.      *  
  78.      * @param context 
  79.      * @param imgId 
  80.      * @param spannableString 
  81.      * @return 
  82.      */  
  83.     public SpannableString addFace(Context context, int imgId,  
  84.             String spannableString) {  
  85.         if (TextUtils.isEmpty(spannableString)) {  
  86.             return null;  
  87.         }  
  88.         Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),  
  89.                 imgId);  
  90.         bitmap = Bitmap.createScaledBitmap(bitmap, 3535true);  
  91.         ImageSpan imageSpan = new ImageSpan(context, bitmap);  
  92.         SpannableString spannable = new SpannableString(spannableString);  
  93.         spannable.setSpan(imageSpan, 0, spannableString.length(),  
  94.                 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  95.         return spannable;  
  96.     }  
  97.   
  98.     /** 
  99.      * 对spanableString进行正则判断,如果符合要求,则以表情图片代替 
  100.      *  
  101.      * @param context 
  102.      * @param spannableString 
  103.      * @param patten 
  104.      * @param start 
  105.      * @throws Exception 
  106.      */  
  107.     private void dealExpression(Context context,  
  108.             SpannableString spannableString, Pattern patten, int start)  
  109.             throws Exception {  
  110.         Matcher matcher = patten.matcher(spannableString);  
  111.         while (matcher.find()) {  
  112.             String key = matcher.group();  
  113.             // 返回第一个字符的索引的文本匹配整个正则表达式,ture 则继续递归  
  114.             if (matcher.start() < start) {  
  115.                 continue;  
  116.             }  
  117.             String value = emojiMap.get(key);  
  118.             if (TextUtils.isEmpty(value)) {  
  119.                 continue;  
  120.             }  
  121.             int resId = context.getResources().getIdentifier(value, "drawable",  
  122.                     context.getPackageName());  
  123.             // 通过上面匹配得到的字符串来生成图片资源id,下边的方法可用,但是你工程混淆的时候就有事了,你懂的。不是我介绍的重点  
  124.             // Field field=R.drawable.class.getDeclaredField(value);  
  125.             // int resId=Integer.parseInt(field.get(null).toString());  
  126.             if (resId != 0) {  
  127.                 Bitmap bitmap = BitmapFactory.decodeResource(  
  128.                         context.getResources(), resId);  
  129.                 bitmap = Bitmap.createScaledBitmap(bitmap, 5050true);  
  130.                 // 通过图片资源id来得到bitmap,用一个ImageSpan来包装  
  131.                 ImageSpan imageSpan = new ImageSpan(bitmap);  
  132.                 // 计算该图片名字的长度,也就是要替换的字符串的长度  
  133.                 int end = matcher.start() + key.length();  
  134.                 // 将该图片替换字符串中规定的位置中  
  135.                 spannableString.setSpan(imageSpan, matcher.start(), end,  
  136.                         Spannable.SPAN_INCLUSIVE_EXCLUSIVE);  
  137.                 if (end < spannableString.length()) {  
  138.                     // 如果整个字符串还未验证完,则继续。。  
  139.                     dealExpression(context, spannableString, patten, end);  
  140.                 }  
  141.                 break;  
  142.             }  
  143.         }  
  144.     }  
  145.   
  146.     public void getFileText(Context context) {  
  147.         ParseData(FileUtils.getEmojiFile(context), context);  
  148.     }  
  149.   
  150.     /** 
  151.      * 解析字符 
  152.      *  
  153.      * @param data 
  154.      */  
  155.     private void ParseData(List<String> data, Context context) {  
  156.         if (data == null) {  
  157.             return;  
  158.         }  
  159.         ChatEmoji emojEentry;  
  160.         try {  
  161.             for (String str : data) {  
  162.                 String[] text = str.split(",");  
  163.                 String fileName = text[0]  
  164.                         .substring(0, text[0].lastIndexOf("."));  
  165.                 emojiMap.put(text[1], fileName);  
  166.                 int resID = context.getResources().getIdentifier(fileName,  
  167.                         "drawable", context.getPackageName());  
  168.   
  169.                 if (resID != 0) {  
  170.                     emojEentry = new ChatEmoji();  
  171.                     emojEentry.setId(resID);  
  172.                     emojEentry.setCharacter(text[1]);  
  173.                     emojEentry.setFaceName(fileName);  
  174.                     emojis.add(emojEentry);  
  175.                 }  
  176.             }  
  177.             int pageCount = (int) Math.ceil(emojis.size() / 20 + 0.1);  
  178.   
  179.             for (int i = 0; i < pageCount; i++) {  
  180.                 emojiLists.add(getData(i));  
  181.             }  
  182.         } catch (Exception e) {  
  183.             e.printStackTrace();  
  184.         }  
  185.     }  
  186.   
  187.     /** 
  188.      * 获取分页数据 
  189.      *  
  190.      * @param page 
  191.      * @return 
  192.      */  
  193.     private List<ChatEmoji> getData(int page) {  
  194.         int startIndex = page * pageSize;  
  195.         int endIndex = startIndex + pageSize;  
  196.   
  197.         if (endIndex > emojis.size()) {  
  198.             endIndex = emojis.size();  
  199.         }  
  200.         // 不这么写,会在viewpager加载中报集合操作异常,我也不知道为什么  
  201.         List<ChatEmoji> list = new ArrayList<ChatEmoji>();  
  202.         list.addAll(emojis.subList(startIndex, endIndex));  
  203.         if (list.size() < pageSize) {  
  204.             for (int i = list.size(); i < pageSize; i++) {  
  205.                 ChatEmoji object = new ChatEmoji();  
  206.                 list.add(object);  
  207.             }  
  208.         }  
  209.         if (list.size() == pageSize) {  
  210.             ChatEmoji object = new ChatEmoji();  
  211.             object.setId(R.drawable.face_del_icon);  
  212.             list.add(object);  
  213.         }  
  214.         return list;  
  215.     }  
  216. }  
package com.example.facedemo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.util.Log;

/**
 * 
 ****************************************** 
 * @author 廖乃波
 * @文件名称 : FaceConversionUtil.java
 * @创建时间 : 2013-1-27 下午02:34:09
 * @文件描述 : 表情轉換工具
 ****************************************** 
 */
public class FaceConversionUtil {

	/** 每一页表情的个数 */
	private int pageSize = 20;

	private static FaceConversionUtil mFaceConversionUtil;

	/** 保存于内存中的表情HashMap */
	private HashMap<String, String> emojiMap = new HashMap<String, String>();

	/** 保存于内存中的表情集合 */
	private List<ChatEmoji> emojis = new ArrayList<ChatEmoji>();

	/** 表情分页的结果集合 */
	public List<List<ChatEmoji>> emojiLists = new ArrayList<List<ChatEmoji>>();

	private FaceConversionUtil() {

	}

	public static FaceConversionUtil getInstace() {
		if (mFaceConversionUtil == null) {
			mFaceConversionUtil = new FaceConversionUtil();
		}
		return mFaceConversionUtil;
	}

	/**
	 * 得到一个SpanableString对象,通过传入的字符串,并进行正则判断
	 * 
	 * @param context
	 * @param str
	 * @return
	 */
	public SpannableString getExpressionString(Context context, String str) {
		SpannableString spannableString = new SpannableString(str);
		// 正则表达式比配字符串里是否含有表情,如: 我好[开心]啊
		String zhengze = "\\[[^\\]]+\\]";
		// 通过传入的正则表达式来生成一个pattern
		Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE);
		try {
			dealExpression(context, spannableString, sinaPatten, 0);
		} catch (Exception e) {
			Log.e("dealExpression", e.getMessage());
		}
		return spannableString;
	}

	/**
	 * 添加表情
	 * 
	 * @param context
	 * @param imgId
	 * @param spannableString
	 * @return
	 */
	public SpannableString addFace(Context context, int imgId,
			String spannableString) {
		if (TextUtils.isEmpty(spannableString)) {
			return null;
		}
		Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
				imgId);
		bitmap = Bitmap.createScaledBitmap(bitmap, 35, 35, true);
		ImageSpan imageSpan = new ImageSpan(context, bitmap);
		SpannableString spannable = new SpannableString(spannableString);
		spannable.setSpan(imageSpan, 0, spannableString.length(),
				Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		return spannable;
	}

	/**
	 * 对spanableString进行正则判断,如果符合要求,则以表情图片代替
	 * 
	 * @param context
	 * @param spannableString
	 * @param patten
	 * @param start
	 * @throws Exception
	 */
	private void dealExpression(Context context,
			SpannableString spannableString, Pattern patten, int start)
			throws Exception {
		Matcher matcher = patten.matcher(spannableString);
		while (matcher.find()) {
			String key = matcher.group();
			// 返回第一个字符的索引的文本匹配整个正则表达式,ture 则继续递归
			if (matcher.start() < start) {
				continue;
			}
			String value = emojiMap.get(key);
			if (TextUtils.isEmpty(value)) {
				continue;
			}
			int resId = context.getResources().getIdentifier(value, "drawable",
					context.getPackageName());
			// 通过上面匹配得到的字符串来生成图片资源id,下边的方法可用,但是你工程混淆的时候就有事了,你懂的。不是我介绍的重点
			// Field field=R.drawable.class.getDeclaredField(value);
			// int resId=Integer.parseInt(field.get(null).toString());
			if (resId != 0) {
				Bitmap bitmap = BitmapFactory.decodeResource(
						context.getResources(), resId);
				bitmap = Bitmap.createScaledBitmap(bitmap, 50, 50, true);
				// 通过图片资源id来得到bitmap,用一个ImageSpan来包装
				ImageSpan imageSpan = new ImageSpan(bitmap);
				// 计算该图片名字的长度,也就是要替换的字符串的长度
				int end = matcher.start() + key.length();
				// 将该图片替换字符串中规定的位置中
				spannableString.setSpan(imageSpan, matcher.start(), end,
						Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
				if (end < spannableString.length()) {
					// 如果整个字符串还未验证完,则继续。。
					dealExpression(context, spannableString, patten, end);
				}
				break;
			}
		}
	}

	public void getFileText(Context context) {
		ParseData(FileUtils.getEmojiFile(context), context);
	}

	/**
	 * 解析字符
	 * 
	 * @param data
	 */
	private void ParseData(List<String> data, Context context) {
		if (data == null) {
			return;
		}
		ChatEmoji emojEentry;
		try {
			for (String str : data) {
				String[] text = str.split(",");
				String fileName = text[0]
						.substring(0, text[0].lastIndexOf("."));
				emojiMap.put(text[1], fileName);
				int resID = context.getResources().getIdentifier(fileName,
						"drawable", context.getPackageName());

				if (resID != 0) {
					emojEentry = new ChatEmoji();
					emojEentry.setId(resID);
					emojEentry.setCharacter(text[1]);
					emojEentry.setFaceName(fileName);
					emojis.add(emojEentry);
				}
			}
			int pageCount = (int) Math.ceil(emojis.size() / 20 + 0.1);

			for (int i = 0; i < pageCount; i++) {
				emojiLists.add(getData(i));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取分页数据
	 * 
	 * @param page
	 * @return
	 */
	private List<ChatEmoji> getData(int page) {
		int startIndex = page * pageSize;
		int endIndex = startIndex + pageSize;

		if (endIndex > emojis.size()) {
			endIndex = emojis.size();
		}
		// 不这么写,会在viewpager加载中报集合操作异常,我也不知道为什么
		List<ChatEmoji> list = new ArrayList<ChatEmoji>();
		list.addAll(emojis.subList(startIndex, endIndex));
		if (list.size() < pageSize) {
			for (int i = list.size(); i < pageSize; i++) {
				ChatEmoji object = new ChatEmoji();
				list.add(object);
			}
		}
		if (list.size() == pageSize) {
			ChatEmoji object = new ChatEmoji();
			object.setId(R.drawable.face_del_icon);
			list.add(object);
		}
		return list;
	}
}

下边是表情布局,带输入框的,这样可以多个地方使用,就不不会使用太多多余代码。


  1. package com.example.facedemo;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.content.Context;  
  7. import android.graphics.Color;  
  8. import android.graphics.drawable.ColorDrawable;  
  9. import android.support.v4.view.ViewPager;  
  10. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  11. import android.text.SpannableString;  
  12. import android.text.TextUtils;  
  13. import android.util.AttributeSet;  
  14. import android.view.Gravity;  
  15. import android.view.View;  
  16. import android.view.View.OnClickListener;  
  17. import android.view.ViewGroup;  
  18. import android.widget.AdapterView;  
  19. import android.widget.AdapterView.OnItemClickListener;  
  20. import android.widget.EditText;  
  21. import android.widget.GridView;  
  22. import android.widget.ImageView;  
  23. import android.widget.LinearLayout;  
  24. import android.widget.RelativeLayout;  
  25.   
  26. /** 
  27.  *  
  28.  ****************************************** 
  29.  * @author 廖乃波 
  30.  * @文件名称    :  FaceRelativeLayout.java 
  31.  * @创建时间    : 2013-1-27 下午02:34:17 
  32.  * @文件描述    : 带表情的自定义输入框 
  33.  ****************************************** 
  34.  */  
  35. public class FaceRelativeLayout extends RelativeLayout implements  
  36.         OnItemClickListener, OnClickListener {  
  37.   
  38.     private Context context;  
  39.   
  40.     /** 表情页的监听事件 */  
  41.     private OnCorpusSelectedListener mListener;  
  42.   
  43.     /** 显示表情页的viewpager */  
  44.     private ViewPager vp_face;  
  45.   
  46.     /** 表情页界面集合 */  
  47.     private ArrayList<View> pageViews;  
  48.   
  49.     /** 游标显示布局 */  
  50.     private LinearLayout layout_point;  
  51.   
  52.     /** 游标点集合 */  
  53.     private ArrayList<ImageView> pointViews;  
  54.   
  55.     /** 表情集合 */  
  56.     private List<List<ChatEmoji>> emojis;  
  57.   
  58.     /** 表情区域 */  
  59.     private View view;  
  60.   
  61.     /** 输入框 */  
  62.     private EditText et_sendmessage;  
  63.   
  64.     /** 表情数据填充器 */  
  65.     private List<FaceAdapter> faceAdapters;  
  66.   
  67.     /** 当前表情页 */  
  68.     private int current = 0;  
  69.   
  70.     public FaceRelativeLayout(Context context) {  
  71.         super(context);  
  72.         this.context = context;  
  73.     }  
  74.   
  75.     public FaceRelativeLayout(Context context, AttributeSet attrs) {  
  76.         super(context, attrs);  
  77.         this.context = context;  
  78.     }  
  79.   
  80.     public FaceRelativeLayout(Context context, AttributeSet attrs, int defStyle) {  
  81.         super(context, attrs, defStyle);  
  82.         this.context = context;  
  83.     }  
  84.   
  85.     public void setOnCorpusSelectedListener(OnCorpusSelectedListener listener) {  
  86.         mListener = listener;  
  87.     }  
  88.   
  89.     /** 
  90.      * 表情选择监听 
  91.      *  
  92.      * @author naibo-liao 
  93.      * @时间: 2013-1-15下午04:32:54 
  94.      */  
  95.     public interface OnCorpusSelectedListener {  
  96.   
  97.         void onCorpusSelected(ChatEmoji emoji);  
  98.   
  99.         void onCorpusDeleted();  
  100.     }  
  101.   
  102.     @Override  
  103.     protected void onFinishInflate() {  
  104.         super.onFinishInflate();  
  105.         emojis = FaceConversionUtil.getInstace().emojiLists;  
  106.         onCreate();  
  107.     }  
  108.   
  109.     private void onCreate() {  
  110.         Init_View();  
  111.         Init_viewPager();  
  112.         Init_Point();  
  113.         Init_Data();  
  114.     }  
  115.   
  116.     @Override  
  117.     public void onClick(View v) {  
  118.         switch (v.getId()) {  
  119.         case R.id.btn_face:  
  120.             // 隐藏表情选择框  
  121.             if (view.getVisibility() == View.VISIBLE) {  
  122.                 view.setVisibility(View.GONE);  
  123.             } else {  
  124.                 view.setVisibility(View.VISIBLE);  
  125.             }  
  126.             break;  
  127.         case R.id.et_sendmessage:  
  128.             // 隐藏表情选择框  
  129.             if (view.getVisibility() == View.VISIBLE) {  
  130.                 view.setVisibility(View.GONE);  
  131.             }  
  132.             break;  
  133.   
  134.         }  
  135.     }  
  136.   
  137.     /** 
  138.      * 隐藏表情选择框 
  139.      */  
  140.     public boolean hideFaceView() {  
  141.         // 隐藏表情选择框  
  142.         if (view.getVisibility() == View.VISIBLE) {  
  143.             view.setVisibility(View.GONE);  
  144.             return true;  
  145.         }  
  146.         return false;  
  147.     }  
  148.   
  149.     /** 
  150.      * 初始化控件 
  151.      */  
  152.     private void Init_View() {  
  153.         vp_face = (ViewPager) findViewById(R.id.vp_contains);  
  154.         et_sendmessage = (EditText) findViewById(R.id.et_sendmessage);  
  155.         layout_point = (LinearLayout) findViewById(R.id.iv_image);  
  156.         et_sendmessage.setOnClickListener(this);  
  157.         findViewById(R.id.btn_face).setOnClickListener(this);  
  158.         view = findViewById(R.id.ll_facechoose);  
  159.   
  160.     }  
  161.   
  162.     /** 
  163.      * 初始化显示表情的viewpager 
  164.      */  
  165.     private void Init_viewPager() {  
  166.         pageViews = new ArrayList<View>();  
  167.         // 左侧添加空页  
  168.         View nullView1 = new View(context);  
  169.         // 设置透明背景  
  170.         nullView1.setBackgroundColor(Color.TRANSPARENT);  
  171.         pageViews.add(nullView1);  
  172.   
  173.         // 中间添加表情页  
  174.   
  175.         faceAdapters = new ArrayList<FaceAdapter>();  
  176.         for (int i = 0; i < emojis.size(); i++) {  
  177.             GridView view = new GridView(context);  
  178.             FaceAdapter adapter = new FaceAdapter(context, emojis.get(i));  
  179.             view.setAdapter(adapter);  
  180.             faceAdapters.add(adapter);  
  181.             view.setOnItemClickListener(this);  
  182.             view.setNumColumns(7);  
  183.             view.setBackgroundColor(Color.TRANSPARENT);  
  184.             view.setHorizontalSpacing(1);  
  185.             view.setVerticalSpacing(1);  
  186.             view.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);  
  187.             view.setCacheColorHint(0);  
  188.             view.setPadding(5050);  
  189.             view.setSelector(new ColorDrawable(Color.TRANSPARENT));  
  190.             view.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,  
  191.                     LayoutParams.WRAP_CONTENT));  
  192.             view.setGravity(Gravity.CENTER);  
  193.             pageViews.add(view);  
  194.         }  
  195.   
  196.         // 右侧添加空页面  
  197.         View nullView2 = new View(context);  
  198.         // 设置透明背景  
  199.         nullView2.setBackgroundColor(Color.TRANSPARENT);  
  200.         pageViews.add(nullView2);  
  201.     }  
  202.   
  203.     /** 
  204.      * 初始化游标 
  205.      */  
  206.     private void Init_Point() {  
  207.   
  208.         pointViews = new ArrayList<ImageView>();  
  209.         ImageView imageView;  
  210.         for (int i = 0; i < pageViews.size(); i++) {  
  211.             imageView = new ImageView(context);  
  212.             imageView.setBackgroundResource(R.drawable.d1);  
  213.             LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(  
  214.                     new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,  
  215.                             LayoutParams.WRAP_CONTENT));  
  216.             layoutParams.leftMargin = 10;  
  217.             layoutParams.rightMargin = 10;  
  218.             layoutParams.width = 8;  
  219.             layoutParams.height = 8;  
  220.             layout_point.addView(imageView, layoutParams);  
  221.             if (i == 0 || i == pageViews.size() - 1) {  
  222.                 imageView.setVisibility(View.GONE);  
  223.             }  
  224.             if (i == 1) {  
  225.                 imageView.setBackgroundResource(R.drawable.d2);  
  226.             }  
  227.             pointViews.add(imageView);  
  228.   
  229.         }  
  230.     }  
  231.   
  232.     /** 
  233.      * 填充数据 
  234.      */  
  235.     private void Init_Data() {  
  236.         vp_face.setAdapter(new ViewPagerAdapter(pageViews));  
  237.   
  238.         vp_face.setCurrentItem(1);  
  239.         current = 0;  
  240.         vp_face.setOnPageChangeListener(new OnPageChangeListener() {  
  241.   
  242.             @Override  
  243.             public void onPageSelected(int arg0) {  
  244.                 current = arg0 - 1;  
  245.                 // 描绘分页点  
  246.                 draw_Point(arg0);  
  247.                 // 如果是第一屏或者是最后一屏禁止滑动,其实这里实现的是如果滑动的是第一屏则跳转至第二屏,如果是最后一屏则跳转到倒数第二屏.  
  248.                 if (arg0 == pointViews.size() - 1 || arg0 == 0) {  
  249.                     if (arg0 == 0) {  
  250.                         vp_face.setCurrentItem(arg0 + 1);// 第二屏 会再次实现该回调方法实现跳转.  
  251.                         pointViews.get(1).setBackgroundResource(R.drawable.d2);  
  252.                     } else {  
  253.                         vp_face.setCurrentItem(arg0 - 1);// 倒数第二屏  
  254.                         pointViews.get(arg0 - 1).setBackgroundResource(  
  255.                                 R.drawable.d2);  
  256.                     }  
  257.                 }  
  258.             }  
  259.   
  260.             @Override  
  261.             public void onPageScrolled(int arg0, float arg1, int arg2) {  
  262.   
  263.             }  
  264.   
  265.             @Override  
  266.             public void onPageScrollStateChanged(int arg0) {  
  267.   
  268.             }  
  269.         });  
  270.   
  271.     }  
  272.   
  273.     /** 
  274.      * 绘制游标背景 
  275.      */  
  276.     public void draw_Point(int index) {  
  277.         for (int i = 1; i < pointViews.size(); i++) {  
  278.             if (index == i) {  
  279.                 pointViews.get(i).setBackgroundResource(R.drawable.d2);  
  280.             } else {  
  281.                 pointViews.get(i).setBackgroundResource(R.drawable.d1);  
  282.             }  
  283.         }  
  284.     }  
  285.   
  286.     @Override  
  287.     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {  
  288.         ChatEmoji emoji = (ChatEmoji) faceAdapters.get(current).getItem(arg2);  
  289.         if (emoji.getId() == R.drawable.face_del_icon) {  
  290.             int selection = et_sendmessage.getSelectionStart();  
  291.             String text = et_sendmessage.getText().toString();  
  292.             if (selection > 0) {  
  293.                 String text2 = text.substring(selection - 1);  
  294.                 if ("]".equals(text2)) {  
  295.                     int start = text.lastIndexOf("[");  
  296.                     int end = selection;  
  297.                     et_sendmessage.getText().delete(start, end);  
  298.                     return;  
  299.                 }  
  300.                 et_sendmessage.getText().delete(selection - 1, selection);  
  301.             }  
  302.         }  
  303.         if (!TextUtils.isEmpty(emoji.getCharacter())) {  
  304.             if (mListener != null)  
  305.                 mListener.onCorpusSelected(emoji);  
  306.             SpannableString spannableString = FaceConversionUtil.getInstace()  
  307.                     .addFace(getContext(), emoji.getId(), emoji.getCharacter());  
  308.             et_sendmessage.append(spannableString);  
  309.         }  
  310.   
  311.     }  
  312. }  
package com.example.facedemo;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.SpannableString;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

/**
 * 
 ******************************************
 * @author 廖乃波
 * @文件名称	:  FaceRelativeLayout.java
 * @创建时间	: 2013-1-27 下午02:34:17
 * @文件描述	: 带表情的自定义输入框
 ******************************************
 */
public class FaceRelativeLayout extends RelativeLayout implements
		OnItemClickListener, OnClickListener {

	private Context context;

	/** 表情页的监听事件 */
	private OnCorpusSelectedListener mListener;

	/** 显示表情页的viewpager */
	private ViewPager vp_face;

	/** 表情页界面集合 */
	private ArrayList<View> pageViews;

	/** 游标显示布局 */
	private LinearLayout layout_point;

	/** 游标点集合 */
	private ArrayList<ImageView> pointViews;

	/** 表情集合 */
	private List<List<ChatEmoji>> emojis;

	/** 表情区域 */
	private View view;

	/** 输入框 */
	private EditText et_sendmessage;

	/** 表情数据填充器 */
	private List<FaceAdapter> faceAdapters;

	/** 当前表情页 */
	private int current = 0;

	public FaceRelativeLayout(Context context) {
		super(context);
		this.context = context;
	}

	public FaceRelativeLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
	}

	public FaceRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.context = context;
	}

	public void setOnCorpusSelectedListener(OnCorpusSelectedListener listener) {
		mListener = listener;
	}

	/**
	 * 表情选择监听
	 * 
	 * @author naibo-liao
	 * @时间: 2013-1-15下午04:32:54
	 */
	public interface OnCorpusSelectedListener {

		void onCorpusSelected(ChatEmoji emoji);

		void onCorpusDeleted();
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		emojis = FaceConversionUtil.getInstace().emojiLists;
		onCreate();
	}

	private void onCreate() {
		Init_View();
		Init_viewPager();
		Init_Point();
		Init_Data();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_face:
			// 隐藏表情选择框
			if (view.getVisibility() == View.VISIBLE) {
				view.setVisibility(View.GONE);
			} else {
				view.setVisibility(View.VISIBLE);
			}
			break;
		case R.id.et_sendmessage:
			// 隐藏表情选择框
			if (view.getVisibility() == View.VISIBLE) {
				view.setVisibility(View.GONE);
			}
			break;

		}
	}

	/**
	 * 隐藏表情选择框
	 */
	public boolean hideFaceView() {
		// 隐藏表情选择框
		if (view.getVisibility() == View.VISIBLE) {
			view.setVisibility(View.GONE);
			return true;
		}
		return false;
	}

	/**
	 * 初始化控件
	 */
	private void Init_View() {
		vp_face = (ViewPager) findViewById(R.id.vp_contains);
		et_sendmessage = (EditText) findViewById(R.id.et_sendmessage);
		layout_point = (LinearLayout) findViewById(R.id.iv_image);
		et_sendmessage.setOnClickListener(this);
		findViewById(R.id.btn_face).setOnClickListener(this);
		view = findViewById(R.id.ll_facechoose);

	}

	/**
	 * 初始化显示表情的viewpager
	 */
	private void Init_viewPager() {
		pageViews = new ArrayList<View>();
		// 左侧添加空页
		View nullView1 = new View(context);
		// 设置透明背景
		nullView1.setBackgroundColor(Color.TRANSPARENT);
		pageViews.add(nullView1);

		// 中间添加表情页

		faceAdapters = new ArrayList<FaceAdapter>();
		for (int i = 0; i < emojis.size(); i++) {
			GridView view = new GridView(context);
			FaceAdapter adapter = new FaceAdapter(context, emojis.get(i));
			view.setAdapter(adapter);
			faceAdapters.add(adapter);
			view.setOnItemClickListener(this);
			view.setNumColumns(7);
			view.setBackgroundColor(Color.TRANSPARENT);
			view.setHorizontalSpacing(1);
			view.setVerticalSpacing(1);
			view.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
			view.setCacheColorHint(0);
			view.setPadding(5, 0, 5, 0);
			view.setSelector(new ColorDrawable(Color.TRANSPARENT));
			view.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
					LayoutParams.WRAP_CONTENT));
			view.setGravity(Gravity.CENTER);
			pageViews.add(view);
		}

		// 右侧添加空页面
		View nullView2 = new View(context);
		// 设置透明背景
		nullView2.setBackgroundColor(Color.TRANSPARENT);
		pageViews.add(nullView2);
	}

	/**
	 * 初始化游标
	 */
	private void Init_Point() {

		pointViews = new ArrayList<ImageView>();
		ImageView imageView;
		for (int i = 0; i < pageViews.size(); i++) {
			imageView = new ImageView(context);
			imageView.setBackgroundResource(R.drawable.d1);
			LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
					new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,
							LayoutParams.WRAP_CONTENT));
			layoutParams.leftMargin = 10;
			layoutParams.rightMargin = 10;
			layoutParams.width = 8;
			layoutParams.height = 8;
			layout_point.addView(imageView, layoutParams);
			if (i == 0 || i == pageViews.size() - 1) {
				imageView.setVisibility(View.GONE);
			}
			if (i == 1) {
				imageView.setBackgroundResource(R.drawable.d2);
			}
			pointViews.add(imageView);

		}
	}

	/**
	 * 填充数据
	 */
	private void Init_Data() {
		vp_face.setAdapter(new ViewPagerAdapter(pageViews));

		vp_face.setCurrentItem(1);
		current = 0;
		vp_face.setOnPageChangeListener(new OnPageChangeListener() {

			@Override
			public void onPageSelected(int arg0) {
				current = arg0 - 1;
				// 描绘分页点
				draw_Point(arg0);
				// 如果是第一屏或者是最后一屏禁止滑动,其实这里实现的是如果滑动的是第一屏则跳转至第二屏,如果是最后一屏则跳转到倒数第二屏.
				if (arg0 == pointViews.size() - 1 || arg0 == 0) {
					if (arg0 == 0) {
						vp_face.setCurrentItem(arg0 + 1);// 第二屏 会再次实现该回调方法实现跳转.
						pointViews.get(1).setBackgroundResource(R.drawable.d2);
					} else {
						vp_face.setCurrentItem(arg0 - 1);// 倒数第二屏
						pointViews.get(arg0 - 1).setBackgroundResource(
								R.drawable.d2);
					}
				}
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {

			}

			@Override
			public void onPageScrollStateChanged(int arg0) {

			}
		});

	}

	/**
	 * 绘制游标背景
	 */
	public void draw_Point(int index) {
		for (int i = 1; i < pointViews.size(); i++) {
			if (index == i) {
				pointViews.get(i).setBackgroundResource(R.drawable.d2);
			} else {
				pointViews.get(i).setBackgroundResource(R.drawable.d1);
			}
		}
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
		ChatEmoji emoji = (ChatEmoji) faceAdapters.get(current).getItem(arg2);
		if (emoji.getId() == R.drawable.face_del_icon) {
			int selection = et_sendmessage.getSelectionStart();
			String text = et_sendmessage.getText().toString();
			if (selection > 0) {
				String text2 = text.substring(selection - 1);
				if ("]".equals(text2)) {
					int start = text.lastIndexOf("[");
					int end = selection;
					et_sendmessage.getText().delete(start, end);
					return;
				}
				et_sendmessage.getText().delete(selection - 1, selection);
			}
		}
		if (!TextUtils.isEmpty(emoji.getCharacter())) {
			if (mListener != null)
				mListener.onCorpusSelected(emoji);
			SpannableString spannableString = FaceConversionUtil.getInstace()
					.addFace(getContext(), emoji.getId(), emoji.getCharacter());
			et_sendmessage.append(spannableString);
		}

	}
}

接下来是聊天数据填充器的


  1. package com.example.facedemo;  
  2.   
  3. import android.content.Context;  
  4.   
  5. import android.text.SpannableString;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9.   
  10. import android.widget.BaseAdapter;  
  11. import android.widget.TextView;  
  12.   
  13. import java.util.List;  
  14.   
  15. /** 
  16.  *  
  17.  ****************************************** 
  18.  * @author 廖乃波 
  19.  * @文件名称    :  ChatMsgAdapter.java 
  20.  * @创建时间    : 2013-1-27 下午02:33:16 
  21.  * @文件描述    : 消息数据填充起 
  22.  ****************************************** 
  23.  */  
  24. public class ChatMsgAdapter extends BaseAdapter {  
  25.   
  26.     public static interface IMsgViewType {  
  27.         int IMVT_COM_MSG = 0;  
  28.         int IMVT_TO_MSG = 1;  
  29.     }  
  30.   
  31.     private List<ChatMsgEntity> coll;  
  32.     private LayoutInflater mInflater;  
  33.     private Context context;  
  34.     public ChatMsgAdapter(Context context, List<ChatMsgEntity> coll) {  
  35.         this.coll = coll;  
  36.         mInflater = LayoutInflater.from(context);  
  37.         this.context = context;  
  38.     }  
  39.   
  40.     public int getCount() {  
  41.         return coll.size();  
  42.     }  
  43.   
  44.     public Object getItem(int position) {  
  45.         return coll.get(position);  
  46.     }  
  47.   
  48.     public long getItemId(int position) {  
  49.         return position;  
  50.     }  
  51.   
  52.     public int getItemViewType(int position) {  
  53.         ChatMsgEntity entity = coll.get(position);  
  54.   
  55.         if (entity.getMsgType()) {  
  56.             return IMsgViewType.IMVT_COM_MSG;  
  57.         } else {  
  58.             return IMsgViewType.IMVT_TO_MSG;  
  59.         }  
  60.   
  61.     }  
  62.   
  63.     public int getViewTypeCount() {  
  64.         return 2;  
  65.     }  
  66.   
  67.     public View getView(int position, View convertView, ViewGroup parent) {  
  68.   
  69.         ChatMsgEntity entity = coll.get(position);  
  70.         boolean isComMsg = entity.getMsgType();  
  71.   
  72.         ViewHolder viewHolder = null;  
  73.         if (convertView == null) {  
  74.             if (isComMsg) {  
  75.                 convertView = mInflater.inflate(  
  76.                         R.layout.chatting_item_msg_text_left, null);  
  77.             } else {  
  78.                 convertView = mInflater.inflate(  
  79.                         R.layout.chatting_item_msg_text_right, null);  
  80.             }  
  81.   
  82.             viewHolder = new ViewHolder();  
  83.             viewHolder.tvSendTime = (TextView) convertView  
  84.                     .findViewById(R.id.tv_sendtime);  
  85.             viewHolder.tvContent = (TextView) convertView  
  86.                     .findViewById(R.id.tv_chatcontent);  
  87.             viewHolder.isComMsg = isComMsg;  
  88.   
  89.             convertView.setTag(viewHolder);  
  90.         } else {  
  91.             viewHolder = (ViewHolder) convertView.getTag();  
  92.         }  
  93.   
  94.         viewHolder.tvSendTime.setText(entity.getDate());  
  95.         SpannableString spannableString = FaceConversionUtil.getInstace().getExpressionString(context, entity.getText());  
  96.         viewHolder.tvContent.setText(spannableString);  
  97.   
  98.         return convertView;  
  99.     }  
  100.   
  101.     class ViewHolder {  
  102.         public TextView tvSendTime;  
  103.         public TextView tvContent;  
  104.         public boolean isComMsg = true;  
  105.     }  
  106.   
  107. }  
package com.example.facedemo;

import android.content.Context;

import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

/**
 * 
 ******************************************
 * @author 廖乃波
 * @文件名称	:  ChatMsgAdapter.java
 * @创建时间	: 2013-1-27 下午02:33:16
 * @文件描述	: 消息数据填充起
 ******************************************
 */
public class ChatMsgAdapter extends BaseAdapter {

	public static interface IMsgViewType {
		int IMVT_COM_MSG = 0;
		int IMVT_TO_MSG = 1;
	}

	private List<ChatMsgEntity> coll;
	private LayoutInflater mInflater;
	private Context context;
	public ChatMsgAdapter(Context context, List<ChatMsgEntity> coll) {
		this.coll = coll;
		mInflater = LayoutInflater.from(context);
		this.context = context;
	}

	public int getCount() {
		return coll.size();
	}

	public Object getItem(int position) {
		return coll.get(position);
	}

	public long getItemId(int position) {
		return position;
	}

	public int getItemViewType(int position) {
		ChatMsgEntity entity = coll.get(position);

		if (entity.getMsgType()) {
			return IMsgViewType.IMVT_COM_MSG;
		} else {
			return IMsgViewType.IMVT_TO_MSG;
		}

	}

	public int getViewTypeCount() {
		return 2;
	}

	public View getView(int position, View convertView, ViewGroup parent) {

		ChatMsgEntity entity = coll.get(position);
		boolean isComMsg = entity.getMsgType();

		ViewHolder viewHolder = null;
		if (convertView == null) {
			if (isComMsg) {
				convertView = mInflater.inflate(
						R.layout.chatting_item_msg_text_left, null);
			} else {
				convertView = mInflater.inflate(
						R.layout.chatting_item_msg_text_right, null);
			}

			viewHolder = new ViewHolder();
			viewHolder.tvSendTime = (TextView) convertView
					.findViewById(R.id.tv_sendtime);
			viewHolder.tvContent = (TextView) convertView
					.findViewById(R.id.tv_chatcontent);
			viewHolder.isComMsg = isComMsg;

			convertView.setTag(viewHolder);
		} else {
			viewHolder = (ViewHolder) convertView.getTag();
		}

		viewHolder.tvSendTime.setText(entity.getDate());
		SpannableString spannableString = FaceConversionUtil.getInstace().getExpressionString(context, entity.getText());
		viewHolder.tvContent.setText(spannableString);

		return convertView;
	}

	class ViewHolder {
		public TextView tvSendTime;
		public TextView tvContent;
		public boolean isComMsg = true;
	}

}


最开始要读取的表情配置文件


  1. package com.example.facedemo;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9.   
  10. import android.content.Context;  
  11.   
  12. /** 
  13.  *  
  14.  ****************************************** 
  15.  * @author 廖乃波 
  16.  * @文件名称    :  FileUtils.java 
  17.  * @创建时间    : 2013-1-27 下午02:35:09 
  18.  * @文件描述    : 文件工具类 
  19.  ****************************************** 
  20.  */  
  21. public class FileUtils {  
  22.     /** 
  23.      * 读取表情配置文件 
  24.      *  
  25.      * @param context 
  26.      * @return 
  27.      */  
  28.     public static List<String> getEmojiFile(Context context) {  
  29.         try {  
  30.             List<String> list = new ArrayList<String>();  
  31.             InputStream in = context.getResources().getAssets().open("emoji");  
  32.             BufferedReader br = new BufferedReader(new InputStreamReader(in,  
  33.                     "UTF-8"));  
  34.             String str = null;  
  35.             while ((str = br.readLine()) != null) {  
  36.                 list.add(str);  
  37.             }  
  38.   
  39.             return list;  
  40.         } catch (IOException e) {  
  41.             e.printStackTrace();  
  42.         }  
  43.         return null;  
  44.     }  
  45. }  
package com.example.facedemo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;

/**
 * 
 ******************************************
 * @author 廖乃波
 * @文件名称	:  FileUtils.java
 * @创建时间	: 2013-1-27 下午02:35:09
 * @文件描述	: 文件工具类
 ******************************************
 */
public class FileUtils {
	/**
	 * 读取表情配置文件
	 * 
	 * @param context
	 * @return
	 */
	public static List<String> getEmojiFile(Context context) {
		try {
			List<String> list = new ArrayList<String>();
			InputStream in = context.getResources().getAssets().open("emoji");
			BufferedReader br = new BufferedReader(new InputStreamReader(in,
					"UTF-8"));
			String str = null;
			while ((str = br.readLine()) != null) {
				list.add(str);
			}

			return list;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

下边这个是表情翻页的数据填充,用的是viewpager,每一页填充的是一个gridview

  1. package com.example.facedemo;  
  2.   
  3. import java.util.List;  
  4.   
  5. import android.support.v4.view.PagerAdapter;  
  6. import android.support.v4.view.ViewPager;  
  7. import android.view.View;  
  8. /** 
  9.  *  
  10.  ****************************************** 
  11.  * @author 廖乃波 
  12.  * @文件名称    :  ViewPagerAdapter.java 
  13.  * @创建时间    : 2013-1-27 下午02:35:27 
  14.  * @文件描述    : ViewPager 数据填充器,切记做其他操作!!!只填充View!!!! 
  15.  ****************************************** 
  16.  */  
  17. public class ViewPagerAdapter extends PagerAdapter {  
  18.   
  19.     private List<View> pageViews;  
  20.   
  21.     public ViewPagerAdapter(List<View> pageViews) {  
  22.         super();  
  23.         this.pageViews=pageViews;  
  24.     }  
  25.   
  26.     // 显示数目  
  27.     @Override  
  28.     public int getCount() {  
  29.         return pageViews.size();  
  30.     }  
  31.   
  32.     @Override  
  33.     public boolean isViewFromObject(View arg0, Object arg1) {  
  34.         return arg0 == arg1;  
  35.     }  
  36.   
  37.     @Override  
  38.     public int getItemPosition(Object object) {  
  39.         return super.getItemPosition(object);  
  40.     }  
  41.   
  42.     @Override  
  43.     public void destroyItem(View arg0, int arg1, Object arg2) {  
  44.         ((ViewPager)arg0).removeView(pageViews.get(arg1));  
  45.     }  
  46.   
  47.     /*** 
  48.      * 获取每一个item�?类于listview中的getview 
  49.      */  
  50.     @Override  
  51.     public Object instantiateItem(View arg0, int arg1) {  
  52.         ((ViewPager)arg0).addView(pageViews.get(arg1));  
  53.         return pageViews.get(arg1);  
  54.     }  
  55. }  
package com.example.facedemo;

import java.util.List;

import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
/**
 * 
 ******************************************
 * @author 廖乃波
 * @文件名称	:  ViewPagerAdapter.java
 * @创建时间	: 2013-1-27 下午02:35:27
 * @文件描述	: ViewPager 数据填充器,切记做其他操作!!!只填充View!!!!
 ******************************************
 */
public class ViewPagerAdapter extends PagerAdapter {

    private List<View> pageViews;

    public ViewPagerAdapter(List<View> pageViews) {
        super();
        this.pageViews=pageViews;
    }

    // 显示数目
    @Override
    public int getCount() {
        return pageViews.size();
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }

    @Override
    public int getItemPosition(Object object) {
        return super.getItemPosition(object);
    }

    @Override
    public void destroyItem(View arg0, int arg1, Object arg2) {
        ((ViewPager)arg0).removeView(pageViews.get(arg1));
    }

    /***
     * 获取每一个item�?类于listview中的getview
     */
    @Override
    public Object instantiateItem(View arg0, int arg1) {
        ((ViewPager)arg0).addView(pageViews.get(arg1));
        return pageViews.get(arg1);
    }
}

 最后呢,是表情的配置文件,你想怎么搞都行,我就这么搞的


  1. emoji_1.png,[可爱]  
  2. emoji_2.png,[笑脸]  
  3. emoji_3.png,[囧]  
  4. emoji_4.png,[生气]  
  5. emoji_5.png,[鬼脸]  
  6. emoji_6.png,[花心]  
  7. emoji_7.png,[害怕]  
  8. emoji_8.png,[我汗]  
  9. emoji_9.png,[尴尬]  
  10. emoji_10.png,[哼哼]  
  11. emoji_11.png,[忧郁]  
  12. emoji_12.png,[呲牙]  
  13. emoji_13.png,[媚眼]  
  14. emoji_14.png,[累]  
  15. emoji_15.png,[苦逼]  
  16. emoji_16.png,[瞌睡]  
  17. emoji_17.png,[哎呀]  
  18. emoji_18.png,[刺瞎]  
  19. emoji_19.png,[哭]  
  20. emoji_20.png,[激动]  
  21. emoji_21.png,[难过]  
  22. emoji_22.png,[害羞]  
  23. emoji_23.png,[高兴]  
  24. emoji_24.png,[愤怒]  
  25. emoji_25.png,[亲]  
  26. emoji_26.png,[飞吻]  
  27. emoji_27.png,[得意]  
  28. emoji_28.png,[惊恐]  
  29. emoji_29.png,[口罩]  
  30. emoji_30.png,[惊讶]  
  31. emoji_31.png,[委屈]  
  32. emoji_32.png,[生病]  
  33. emoji_33.png,[红心]  
  34. emoji_34.png,[心碎]  
  35. emoji_35.png,[玫瑰]  
  36. emoji_36.png,[花]  
  37. emoji_37.png,[外星人]  
  38. emoji_38.png,[金牛座]  
  39. emoji_39.png,[双子座]  
  40. emoji_40.png,[巨蟹座]  
  41. emoji_41.png,[狮子座]  
  42. emoji_42.png,[处女座]  
  43. emoji_43.png,[天平座]  
  44. emoji_44.png,[天蝎座]  
  45. emoji_45.png,[射手座]  
  46. emoji_46.png,[摩羯座]  
  47. emoji_47.png,[水瓶座]  
  48. emoji_48.png,[白羊座]  
  49. emoji_49.png,[双鱼座]  
  50. emoji_50.png,[星座]  
  51. emoji_51.png,[男孩]  
  52. emoji_52.png,[女孩]  
  53. emoji_53.png,[嘴唇]  
  54. emoji_54.png,[爸爸]  
  55. emoji_55.png,[妈妈]  
  56. emoji_56.png,[衣服]  
  57. emoji_57.png,[皮鞋]  
  58. emoji_58.png,[照相]  
  59. emoji_59.png,[电话]  
  60. emoji_60.png,[石头]  
  61. emoji_61.png,[胜利]  
  62. emoji_62.png,[禁止]  
  63. emoji_63.png,[滑雪]  
  64. emoji_64.png,[高尔夫]  
  65. emoji_65.png,[网球]  
  66. emoji_66.png,[棒球]  
  67. emoji_67.png,[冲浪]  
  68. emoji_68.png,[足球]  
  69. emoji_69.png,[小鱼]  
  70. emoji_70.png,[问号]  
  71. emoji_71.png,[叹号]  
  72. emoji_179.png,[顶]  
  73. emoji_180.png,[写字]  
  74. emoji_181.png,[衬衫]  
  75. emoji_182.png,[小花]  
  76. emoji_183.png,[郁金香]  
  77. emoji_184.png,[向日葵]  
  78. emoji_185.png,[鲜花]  
  79. emoji_186.png,[椰树]  
  80. emoji_187.png,[仙人掌]  
  81. emoji_188.png,[气球]  
  82. emoji_189.png,[炸弹]  
  83. emoji_190.png,[喝彩]  
  84. emoji_191.png,[剪子]  
  85. emoji_192.png,[蝴蝶结]  
  86. emoji_193.png,[机密]  
  87. emoji_194.png,[铃声]  
  88. emoji_195.png,[女帽]  
  89. emoji_196.png,[裙子]  
  90. emoji_197.png,[理发店]  
  91. emoji_198.png,[和服]  
  92. emoji_199.png,[比基尼]  
  93. emoji_200.png,[拎包]  
  94. emoji_201.png,[拍摄]  
  95. emoji_202.png,[铃铛]  
  96. emoji_203.png,[音乐]  
  97. emoji_204.png,[心星]  
  98. emoji_205.png,[粉心]  
  99. emoji_206.png,[丘比特]  
  100. emoji_207.png,[吹气]  
  101. emoji_208.png,[口水]  
  102. emoji_209.png,[对]  
  103. emoji_210.png,[错]  
  104. emoji_211.png,[绿茶]  
  105. emoji_212.png,[面包]  
  106. emoji_213.png,[面条]  
  107. emoji_214.png,[咖喱饭]  
  108. emoji_215.png,[饭团]  
  109. emoji_216.png,[麻辣烫]  
  110. emoji_217.png,[寿司]  
  111. emoji_218.png,[苹果]  
  112. emoji_219.png,[橙子]  
  113. emoji_220.png,[草莓]  
  114. emoji_221.png,[西瓜]  
  115. emoji_222.png,[柿子]  
  116. emoji_223.png,[眼睛]  
  117. emoji_224.png,[好的]  
emoji_1.png,[可爱]
emoji_2.png,[笑脸]
emoji_3.png,[囧]
emoji_4.png,[生气]
emoji_5.png,[鬼脸]
emoji_6.png,[花心]
emoji_7.png,[害怕]
emoji_8.png,[我汗]
emoji_9.png,[尴尬]
emoji_10.png,[哼哼]
emoji_11.png,[忧郁]
emoji_12.png,[呲牙]
emoji_13.png,[媚眼]
emoji_14.png,[累]
emoji_15.png,[苦逼]
emoji_16.png,[瞌睡]
emoji_17.png,[哎呀]
emoji_18.png,[刺瞎]
emoji_19.png,[哭]
emoji_20.png,[激动]
emoji_21.png,[难过]
emoji_22.png,[害羞]
emoji_23.png,[高兴]
emoji_24.png,[愤怒]
emoji_25.png,[亲]
emoji_26.png,[飞吻]
emoji_27.png,[得意]
emoji_28.png,[惊恐]
emoji_29.png,[口罩]
emoji_30.png,[惊讶]
emoji_31.png,[委屈]
emoji_32.png,[生病]
emoji_33.png,[红心]
emoji_34.png,[心碎]
emoji_35.png,[玫瑰]
emoji_36.png,[花]
emoji_37.png,[外星人]
emoji_38.png,[金牛座]
emoji_39.png,[双子座]
emoji_40.png,[巨蟹座]
emoji_41.png,[狮子座]
emoji_42.png,[处女座]
emoji_43.png,[天平座]
emoji_44.png,[天蝎座]
emoji_45.png,[射手座]
emoji_46.png,[摩羯座]
emoji_47.png,[水瓶座]
emoji_48.png,[白羊座]
emoji_49.png,[双鱼座]
emoji_50.png,[星座]
emoji_51.png,[男孩]
emoji_52.png,[女孩]
emoji_53.png,[嘴唇]
emoji_54.png,[爸爸]
emoji_55.png,[妈妈]
emoji_56.png,[衣服]
emoji_57.png,[皮鞋]
emoji_58.png,[照相]
emoji_59.png,[电话]
emoji_60.png,[石头]
emoji_61.png,[胜利]
emoji_62.png,[禁止]
emoji_63.png,[滑雪]
emoji_64.png,[高尔夫]
emoji_65.png,[网球]
emoji_66.png,[棒球]
emoji_67.png,[冲浪]
emoji_68.png,[足球]
emoji_69.png,[小鱼]
emoji_70.png,[问号]
emoji_71.png,[叹号]
emoji_179.png,[顶]
emoji_180.png,[写字]
emoji_181.png,[衬衫]
emoji_182.png,[小花]
emoji_183.png,[郁金香]
emoji_184.png,[向日葵]
emoji_185.png,[鲜花]
emoji_186.png,[椰树]
emoji_187.png,[仙人掌]
emoji_188.png,[气球]
emoji_189.png,[炸弹]
emoji_190.png,[喝彩]
emoji_191.png,[剪子]
emoji_192.png,[蝴蝶结]
emoji_193.png,[机密]
emoji_194.png,[铃声]
emoji_195.png,[女帽]
emoji_196.png,[裙子]
emoji_197.png,[理发店]
emoji_198.png,[和服]
emoji_199.png,[比基尼]
emoji_200.png,[拎包]
emoji_201.png,[拍摄]
emoji_202.png,[铃铛]
emoji_203.png,[音乐]
emoji_204.png,[心星]
emoji_205.png,[粉心]
emoji_206.png,[丘比特]
emoji_207.png,[吹气]
emoji_208.png,[口水]
emoji_209.png,[对]
emoji_210.png,[错]
emoji_211.png,[绿茶]
emoji_212.png,[面包]
emoji_213.png,[面条]
emoji_214.png,[咖喱饭]
emoji_215.png,[饭团]
emoji_216.png,[麻辣烫]
emoji_217.png,[寿司]
emoji_218.png,[苹果]
emoji_219.png,[橙子]
emoji_220.png,[草莓]
emoji_221.png,[西瓜]
emoji_222.png,[柿子]
emoji_223.png,[眼睛]
emoji_224.png,[好的]


忘了布局文件,哇哈哈


  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <com.example.facedemo.FaceRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/FaceRelativeLayout"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="wrap_content" >  
  6.   
  7.     <RelativeLayout  
  8.         android:id="@+id/rl_input"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:background="@drawable/chat_footer_bg" >  
  12.   
  13.         <ImageButton  
  14.             android:id="@+id/btn_face"  
  15.             android:layout_width="40dip"  
  16.             android:layout_height="40dip"  
  17.             android:layout_alignParentLeft="true"  
  18.             android:layout_centerVertical="true"  
  19.             android:layout_marginLeft="8dip"  
  20.             android:background="@drawable/chat_send_btn"  
  21.             android:src="@drawable/ib_face" />  
  22.   
  23.         <Button  
  24.             android:id="@+id/btn_send"  
  25.             android:layout_width="60dp"  
  26.             android:layout_height="40dp"  
  27.             android:layout_alignParentRight="true"  
  28.             android:layout_centerVertical="true"  
  29.             android:layout_marginRight="10dp"  
  30.             android:background="@drawable/chat_send_btn"  
  31.             android:text="发送" />  
  32.   
  33.         <EditText  
  34.             android:id="@+id/et_sendmessage"  
  35.             android:layout_width="fill_parent"  
  36.             android:layout_height="40dp"  
  37.             android:layout_centerVertical="true"  
  38.             android:layout_marginLeft="8dp"  
  39.             android:layout_marginRight="10dp"  
  40.             android:layout_toLeftOf="@id/btn_send"  
  41.             android:layout_toRightOf="@id/btn_face"  
  42.             android:background="@drawable/login_edit_normal"  
  43.             android:singleLine="true"  
  44.             android:textSize="18sp" />  
  45.     </RelativeLayout>  
  46.   
  47.     <RelativeLayout  
  48.         android:id="@+id/ll_facechoose"  
  49.         android:layout_width="fill_parent"  
  50.         android:layout_height="124dip"  
  51.         android:layout_below="@id/rl_input"  
  52.         android:background="#f6f5f5"  
  53.         android:visibility="gone" >  
  54.   
  55.         <android.support.v4.view.ViewPager  
  56.             android:id="@+id/vp_contains"  
  57.             android:layout_width="match_parent"  
  58.             android:layout_height="match_parent" >  
  59.         </android.support.v4.view.ViewPager>  
  60.   
  61.         <LinearLayout  
  62.             android:id="@+id/iv_image"  
  63.             android:layout_width="match_parent"  
  64.             android:layout_height="wrap_content"  
  65.             android:layout_alignParentBottom="true"  
  66.             android:layout_marginBottom="6dip"  
  67.             android:gravity="center"  
  68.             android:orientation="horizontal" >  
  69.         </LinearLayout>  
  70.     </RelativeLayout>  
  71.   
  72. </com.example.facedemo.FaceRelativeLayout>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值