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


    http://blog.csdn.net/lnb333666/article/details/8546497

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


    其次大致说说原理:

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


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


    下面贴上DEMO工程的结构:


    再贴上几个重要的类:

    [java] view plaincopy
    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. }  

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


    [java] view plaincopy
    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. }  

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


    [java] view plaincopy
    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. }  


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


    [java] view plaincopy
    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. }  

    下边这个是表情翻页的数据填充,用的是viewpager,每一页填充的是一个gridview
    [java] view plaincopy
    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. }  

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


    [java] view plaincopy
    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,[好的]  


    忘了布局文件,哇哈哈


    [html] view plaincopy
    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>  

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 源码 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


    免费下载

  • 相关阅读:
    数据库设计准则(第一、第二、第三范式说明)
    Linux之chmod使用
    数据备份——PHP
    PHP语言性能优化——少使用魔术方法
    PHP性能之语言性能优化:安装VLD扩展——检测性能
    PHP性能之语言性能优化:安装VLD扩展——检测性能
    PHP性能之语言性能优化:安装VLD扩展——检测性能
    socket、fsockopen、curl、stream 区别
    iOS 下 Podfile 使用方法
    使用 NVM 管理不同的 Node.js 版本
  • 原文地址:https://www.cnblogs.com/lbangel/p/4335887.html
Copyright © 2020-2023  润新知