(转)Android实用视图动画及工具系列之六:通用表情栏,仿QQ微信聊天弹出表情选框

原地址:http://blog.csdn.net/jaikydota163/article/details/52098873?locationNum=10&fps=1


实现效果



功能说明

仿QQ微信聊天表情库框,这个目前市面上已经很多类似的功能了,我就不做多的累赘,本表情栏的优势在于便于集成,而且适用于多种环境,可转换为html标签和转义表情标签等,由于总体代码和资源较少,集成方便,就未上传jcenter或Maven central上了,需要用到类似功能的自行下载源码集成到项目中即可。
适用于新手及新学习Android的码友们,老玩家当然也可以看看,这个还是挺简单挺实用的,在后面会简略介绍实现方法及源代码,同时博客的最后还提供源代码和图片等资源github下载地址。

本部分内容主要讲解表情栏实现,不讲解底部弹出框的实现,需要查看底部弹出框部分实现的请查看这篇文章:
--------------------------------------------------------------------------------------------------------------------
Android实用视图动画及工具系列之五:底部回复对话框,仿QQ空间微信朋友圈回复对话框:
--------------------------------------------------------------------------------------------------------------------

功能讲解

一:项目结构和外观样式

既然是表情库就需要表情,可以是本地的,也可以是从网络加载的,看需求更改,本例子提供了一些本地表情包:(其他图片资源在源代码内,需要的自行下载):
微笑
吐舌头
偷笑
大笑

项目结构如下,总共5个类,一些表情和两个布局文件,还是很简约的:



二:部分代码详解

主类为FaceView.class,主要完成了表情的布局,适配,和转义功能,提供了两种模式:
转义为<img>标签或转义为表情标签,如“/e002”,约定一个转义规则。
转义为表情标签的方法为getImgTag();
转换为<img>标签修改imgTag即可。
private static String imgTag = "<img src=\"http://www.host.com/images/-1.png\" border=\"0\" alt=\"\"/>";
//mode , html tag or escape tag
public static int TAG_MODE_IMG = 1;
public static int TAG_MODE_EMOJI = 2;
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.jaiky.test.faceview;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.BitmapFactory;  
  6. import android.graphics.Color;  
  7. import android.graphics.drawable.BitmapDrawable;  
  8. import android.graphics.drawable.ColorDrawable;  
  9. import android.graphics.drawable.Drawable;  
  10. import android.support.v4.view.ViewPager;  
  11. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  12. import android.text.Spannable;  
  13. import android.text.SpannableString;  
  14. import android.text.style.ImageSpan;  
  15. import android.util.AttributeSet;  
  16. import android.util.DisplayMetrics;  
  17. import android.util.TypedValue;  
  18. import android.view.Gravity;  
  19. import android.view.LayoutInflater;  
  20. import android.view.MotionEvent;  
  21. import android.view.View;  
  22. import android.view.View.OnClickListener;  
  23. import android.view.ViewGroup;  
  24. import android.view.inputmethod.InputMethodManager;  
  25. import android.widget.AdapterView;  
  26. import android.widget.AdapterView.OnItemClickListener;  
  27. import android.widget.EditText;  
  28. import android.widget.GridView;  
  29. import android.widget.ImageView;  
  30. import android.widget.LinearLayout;  
  31.   
  32.   
  33. import java.util.ArrayList;  
  34. import java.util.List;  
  35.   
  36. public class FaceView extends LinearLayout implements OnPageChangeListener,  
  37.         OnItemClickListener, OnClickListener {  
  38.     /**  
  39.      * Convert to Html Tag, using for webPage  
  40.      */  
  41.     private static String imgTag = "<img src=\"http://www.host.com/images/-1.png\" border=\"0\" alt=\"\"/>";  
  42.   
  43.     /**  
  44.      * Face size  
  45.      */  
  46.     private int faceDefaultSize = 17;  
  47.   
  48.     private List<View> m_arrFacePageView;  
  49.     private ViewPager m_vpFace;  
  50.     private List<ImageView> m_arrDotView;  
  51.     private LinearLayout m_dotBar;  
  52.     private Context m_context;  
  53.     private OnFaceSelectedListener m_listener;  
  54.     private EditText m_edit;  
  55.     private View m_btnView;  
  56.   
  57.     private int m_tagMode;  
  58.   
  59.     //mode , html tag or escape tag  
  60.     public static int TAG_MODE_IMG = 1;  
  61.     public static int TAG_MODE_EMOJI = 2;  
  62.   
  63.     private int faceStyleResource;  
  64.     private int textStyleResource;  
  65.   
  66.     /**  
  67.      * 实例化方法  
  68.      *  
  69.      * @param context  
  70.      * @param attrs  
  71.      */  
  72.     public FaceView(Context context, AttributeSet attrs) {  
  73.         super(context, attrs);  
  74.   
  75.         m_context = context;  
  76.         m_tagMode = TAG_MODE_IMG;  
  77.         LayoutInflater.from(context).inflate(R.layout.global_face_view, this, true);  
  78.         initView();  
  79.     }  
  80.   
  81.     // 设置标签模式  
  82.     public void setTagMode(int tagMode) {  
  83.         m_tagMode = tagMode;  
  84.     }  
  85.   
  86.     /**  
  87.      * set the button of show or hide the faceview  
  88.      *  
  89.      * @param btnView  
  90.      * @author saderos  
  91.      *  
  92.      */  
  93.     public void setBtnView(View btnView) {  
  94.         m_btnView = btnView;  
  95.         m_btnView.setOnClickListener(this);  
  96.     }  
  97.   
  98.     public void setFaceAndTextStyle(int faceStyle, int textStyle){  
  99.         this.faceStyleResource = faceStyle;  
  100.         this.textStyleResource = textStyle;  
  101.     }  
  102.   
  103.   
  104.     /**  
  105.      * if you just need to set the editText, and them ,you don't have to append  
  106.      * text to the editText yourself  
  107.      *  
  108.      * @author saderos  
  109.      * @param editText  
  110.      */  
  111.     public void setEdit(EditText editText) {  
  112.         m_edit = editText;  
  113.         m_edit.setOnTouchListener(new OnTouchListener() {  
  114.   
  115.             @Override  
  116.             public boolean onTouch(View v, MotionEvent event) {  
  117.                 if (event.getAction() == MotionEvent.ACTION_DOWN) {  
  118.                     FaceView.this.setVisibility(View.GONE);  
  119.                     setShowImageResource();  
  120.                 }  
  121.                 return false;  
  122.             }  
  123.         });  
  124.     }  
  125.   
  126.     public void setHideToggle(View v) {  
  127.         v.setOnTouchListener(new OnTouchListener() {  
  128.   
  129.             @Override  
  130.             public boolean onTouch(View v, MotionEvent event) {  
  131.                 if (event.getAction() == MotionEvent.ACTION_DOWN) {  
  132.                     FaceView.this.setVisibility(View.GONE);  
  133.                     setShowImageResource();  
  134.                 }  
  135.                 return false;  
  136.             }  
  137.         });  
  138.     }  
  139.   
  140.     public void setOnFaceSelectedListener(OnFaceSelectedListener listener) {  
  141.         m_listener = listener;  
  142.     }  
  143.   
  144.     /**  
  145.      * 初始化视图  
  146.      */  
  147.     private void initView() {  
  148.         if (isInEditMode()) {  
  149.             return;  
  150.         }  
  151.         m_vpFace = (ViewPager) findViewById(R.id.chat_vpFace);  
  152.         m_dotBar = (LinearLayout) findViewById(R.id.chat_dotbar);  
  153.         initFaceBar();  
  154.     }  
  155.   
  156.     private void initFaceBar() {  
  157.         m_arrFacePageView = new ArrayList<View>();  
  158.         for (int i = 0; i < 9; i++) {  
  159.             GridView view = new GridView(m_context);  
  160.             FaceAdapter adapter = new FaceAdapter(m_context, i);  
  161.             view.setOnItemClickListener(this);  
  162.             view.setAdapter(adapter);  
  163.             view.setNumColumns(7);  
  164.             view.setBackgroundColor(Color.TRANSPARENT);  
  165.             view.setHorizontalSpacing(1);  
  166.             view.setVerticalSpacing(1);  
  167.             view.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);  
  168.             view.setCacheColorHint(0);  
  169.             view.setSelector(new ColorDrawable(Color.TRANSPARENT));  
  170.             view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,  
  171.                     LayoutParams.WRAP_CONTENT));  
  172.             view.setGravity(Gravity.CENTER);  
  173.             m_arrFacePageView.add(view);  
  174.         }  
  175.   
  176.         ViewPagerAdapter adapter = new ViewPagerAdapter(m_arrFacePageView);  
  177.         if (!isInEditMode()) {  
  178.             m_vpFace.setAdapter(adapter);  
  179.             m_vpFace.setCurrentItem(1);  
  180.         }  
  181.         m_vpFace.setOnPageChangeListener(this);  
  182.         initDotBar();  
  183.   
  184.     }  
  185.   
  186.     private void initDotBar() {  
  187.         m_arrDotView = new ArrayList<ImageView>();  
  188.   
  189.         if (m_arrFacePageView.size() <= 3)  
  190.             return;  
  191.   
  192.         for (int i = 0; i < m_arrFacePageView.size() - 2; i++) {  
  193.             ImageView imgView = new ImageView(m_context);  
  194.             imgView.setBackgroundResource(R.drawable.common_indicator_nor);  
  195.             LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(  
  196.                     new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,  
  197.                             LayoutParams.WRAP_CONTENT));  
  198.             DisplayMetrics dm = getResources().getDisplayMetrics();  
  199.             params.leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, dm);  
  200.             params.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, dm);  
  201.             // params.width = 7;  
  202.             // params.height = 7;  
  203.             m_dotBar.addView(imgView, params);  
  204.             m_arrDotView.add(imgView);  
  205.         }  
  206.         setSelDot(0);  
  207.     }  
  208.   
  209.     private void setSelDot(int nSelIndex) {  
  210.         for (int i = 0; i < m_arrDotView.size(); i++) {  
  211.             if (nSelIndex == i) {  
  212.                 m_arrDotView.get(i).setBackgroundResource(  
  213.                         R.drawable.common_indicator_checked);  
  214.             } else {  
  215.                 m_arrDotView.get(i).setBackgroundResource(  
  216.                         R.drawable.common_indicator_nor);  
  217.             }  
  218.         }  
  219.     }  
  220.   
  221.     @Override  
  222.     public void onPageSelected(int arg0) {  
  223.   
  224.         if (0 == arg0) {  
  225.             m_vpFace.setCurrentItem(arg0 + 1);  
  226.         } else if (arg0 == m_arrFacePageView.size() - 1) {  
  227.             m_vpFace.setCurrentItem(arg0 - 1);  
  228.         } else {  
  229.             setSelDot(arg0 - 1);  
  230.         }  
  231.     }  
  232.   
  233.     @Override  
  234.     public void onItemClick(AdapterView<?> arg0, View v, int arg2, long arg3) {  
  235.         View img = v.findViewById(R.id.facelistitem_imgFace);  
  236.         String selImgTag = "";  
  237.         int id = Integer.parseInt(img.getTag().toString());  
  238.         if (m_tagMode == TAG_MODE_IMG) {  
  239.             selImgTag = imgTag.replace("-1", id + "");  
  240.         } else {  
  241.             selImgTag = getImgTag(id);  
  242.         }  
  243.         Bitmap bitmap = BitmapFactory.decodeResource(getResources(),  
  244.                 FaceManager.getInstance().getFace(id));  
  245.         if (m_listener != null) {  
  246.             m_listener.OnFaceSelected(selImgTag, bitmap);  
  247.         }  
  248.         if (m_edit != null) {  
  249.             Drawable drawable=new BitmapDrawable(m_context.getResources(),bitmap);  
  250.             int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, faceDefaultSize, getResources().getDisplayMetrics());  
  251.             drawable.setBounds(0, 0, size, size);  
  252.             ImageSpan imgSpan = new ImageSpan(drawable);  
  253.   
  254.             SpannableString spanString = new SpannableString(selImgTag);  
  255.             spanString.setSpan(imgSpan, 0, spanString.length(),  
  256.                     Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  257.             m_edit.append(spanString);  
  258.         }  
  259.     }  
  260.   
  261.     public interface OnFaceSelectedListener {  
  262.         public void OnFaceSelected(String imgTag, Bitmap face);  
  263.     }  
  264.   
  265.     @Override  
  266.     public void onPageScrollStateChanged(int arg0) {  
  267.   
  268.     }  
  269.   
  270.     @Override  
  271.     public void onPageScrolled(int arg0, float arg1, int arg2) {  
  272.   
  273.     }  
  274.   
  275.   
  276.     @Override  
  277.     public void onClick(View v) {  
  278.         // 点击输入框,则隐藏表情  
  279.         if (v == m_btnView) {  
  280.             InputMethodManager imm = (InputMethodManager) m_context  
  281.                     .getSystemService(Context.INPUT_METHOD_SERVICE);  
  282.   
  283.             if (this.getVisibility() == View.GONE) {  
  284.                 imm.hideSoftInputFromWindow(getApplicationWindowToken(),  
  285.                         InputMethodManager.HIDE_NOT_ALWAYS);  
  286.                 try {  
  287.                     Thread.sleep(100);  
  288.                 } catch (InterruptedException e) {  
  289.                     e.printStackTrace();  
  290.                 }  
  291.                 this.setVisibility(View.VISIBLE);  
  292.             } else {  
  293.                 imm.showSoftInput(m_edit, InputMethodManager.SHOW_IMPLICIT);  
  294.                 this.setVisibility(View.GONE);  
  295.             }  
  296.             setShowImageResource();  
  297.         }  
  298.   
  299.     }  
  300.   
  301.   
  302.     private void setShowImageResource() {  
  303.         if (textStyleResource == 0 || faceStyleResource == 0) {  
  304.             //设置默认显示  
  305.             if (m_btnView instanceof ImageView) {  
  306.                 if (getVisibility() == View.GONE)  
  307.                     ((ImageView)m_btnView).setImageResource(R.drawable.chatform_face_selector);  
  308.                 else  
  309.                     ((ImageView)m_btnView).setImageResource(R.drawable.chatform_setmodetext_selector);  
  310.             }  
  311.         }  
  312.         else {  
  313.             if (getVisibility() == View.GONE)  
  314.                 m_btnView.setBackgroundResource(faceStyleResource);  
  315.             else  
  316.                 m_btnView.setBackgroundResource(textStyleResource);  
  317.         }  
  318.     }  
  319.   
  320.     private String getImgTag(int position) {  
  321.         String imgTag = "";  
  322.   
  323.         // the number of total image is 134,so when the image number larger than  
  324.         // 134 ,them return null  
  325.         if (position > 134)  
  326.             return null;  
  327.         imgTag = position + "";  
  328.         switch (imgTag.length()) {  
  329.             case 1:  
  330.                 imgTag = "/e00" + imgTag;  
  331.                 break;  
  332.             case 2:  
  333.                 imgTag = "/e0" + imgTag;  
  334.                 break;  
  335.             case 3:  
  336.                 imgTag = "/e" + imgTag;  
  337.                 break;  
  338.             default:  
  339.                 break;  
  340.         }  
  341.         return imgTag;  
  342.     }  
  343.   
  344. }  

二:使用表情库

使用比较简单,在布局文件中添加:
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <com.jaiky.test.faceview.FaceView  
  2.     android:id="@+id/face_view"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content"  
  5.     android:visibility="gone" >  
  6. </com.jaiky.test.faceview.FaceView>  

在代码中添加:
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //此处绑定表情栏  
  2. FaceView faceView = (FaceView) findViewById(R.id.face_view);  
  3. //表情的编辑框EditText  
  4. faceView.setEdit(etContent);  
  5. //弹出表情库的按钮  
  6. faceView.setBtnView(ivFace);  

设置显示的TextView:
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. TextView.setText(Html.fromHtml(replyDialog.getContent(), new FaceImageGetter(context), null));  


--------------------------------------------------------------------------------------------------------------------
获取源代码及资源文件:
--------------------------------------------------------------------------------------------------------------------

声明

欢迎转载,但请保留文章原始出处
作者:Jaiky_杰哥 
出处:http://blog.csdn.net/jaikydota163/article/details/52098873


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值