上次作了一个表情的控件,不敢私藏,给你们分享
效果图以下,图片是新浪微博的,该有的功能应该都有了。git
这其实就是一个Fragment,因此用起来很方便,只要github
FaceFragment faceFragment = FaceFragment.Instance(); getSupportFragmentManager().beginTransaction().add(R.id.Container,faceFragment).commit();
就能够显示效果图上的效果了。ide
FaceFragment源码以下:布局
public class FaceFragment extends Fragment implements View.OnClickListener { public static FaceFragment Instance() { FaceFragment instance = new FaceFragment(); Bundle bundle = new Bundle(); instance.setArguments(bundle); return instance; } ViewPager faceViewPager; EmojiIndicatorView faceIndicator; TextView faceRecentTv; TextView faceFirstSetTv; ArrayList<View> ViewPagerItems = new ArrayList<>(); ArrayList<Emoji> emojiList; ArrayList<Emoji> recentlyEmojiList; private int columns = 7; //每一行的表情数量 private int rows = 3; //设置总共有几行 private OnEmojiClickListener listener; private RecentEmojiManager recentManager; public void setListener(OnEmojiClickListener listener) { this.listener = listener; } @Override public void onAttach(Activity activity) { if (activity instanceof OnEmojiClickListener) { this.listener = (OnEmojiClickListener) activity; } recentManager = RecentEmojiManager.make(activity); super.onAttach(activity); } @Override public void onCreate(Bundle savedInstanceState) { emojiList = EmojiUtil.getEmojiList(); try { //用SharedPerference来保存咱们最近使用的表情 if (recentManager.getCollection(RecentEmojiManager.PREFERENCE_NAME) != null) { recentlyEmojiList = (ArrayList<Emoji>) recentManager.getCollection(RecentEmojiManager.PREFERENCE_NAME); } else { recentlyEmojiList = new ArrayList<>(); } } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_face, container, false); faceViewPager = (ViewPager) view.findViewById(R.id.face_viewPager); faceIndicator = (EmojiIndicatorView) view.findViewById(R.id.face_indicator); faceRecentTv = (TextView) view.findViewById(R.id.face_recent); faceFirstSetTv = (TextView) view.findViewById(R.id.face_first_set); initViews(); return view; } private void initViews() { initViewPager(emojiList); faceFirstSetTv.setSelected(true); faceFirstSetTv.setOnClickListener(this); faceRecentTv.setOnClickListener(this); } private void initViewPager(ArrayList<Emoji> list) { intiIndicator(list); ViewPagerItems.clear(); for (int i = 0; i < getPagerCount(list); i++) { ViewPagerItems.add(getViewPagerItem(i, list)); } FaceVPAdapter mVpAdapter = new FaceVPAdapter(ViewPagerItems); faceViewPager.setAdapter(mVpAdapter); faceViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { int oldPosition = 0; @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { faceIndicator.playBy(oldPosition, position); oldPosition = position; } @Override public void onPageScrollStateChanged(int state) { } }); } private void intiIndicator(ArrayList<Emoji> list) { faceIndicator.init(getPagerCount(list)); } @Override public void onClick(View v) { if(v.getId() == R.id.face_first_set){ if (faceIndicator.getVisibility() == View.GONE) { faceIndicator.setVisibility(View.VISIBLE); } if (!faceFirstSetTv.isSelected()) { faceFirstSetTv.setSelected(true); initViewPager(emojiList); } faceRecentTv.setSelected(false); }else if (v.getId() == R.id.face_recent){ if (faceIndicator.getVisibility() == View.VISIBLE) { faceIndicator.setVisibility(View.GONE); } if (!faceRecentTv.isSelected()) { faceRecentTv.setSelected(true); initViewPager(recentlyEmojiList); } faceFirstSetTv.setSelected(false); } } /** * 根据表情数量以及GridView设置的行数和列数计算Pager数量 * * @return */ private int getPagerCount(ArrayList<Emoji> list) { int count = list.size(); return count % (columns * rows - 1) == 0 ? count / (columns * rows - 1) : count / (columns * rows - 1) + 1; } private View getViewPagerItem(int position, ArrayList<Emoji> list) { LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View layout = inflater.inflate(R.layout.layout_face_grid, null);//表情布局 GridView gridview = (GridView) layout.findViewById(R.id.chart_face_gv); /** * 注:由于每一页末尾都有一个删除图标,因此每一页的实际表情columns * rows - 1; 空出最后一个位置给删除图标 * */ final List<Emoji> subList = new ArrayList<>(); subList.addAll(list.subList(position * (columns * rows - 1), (columns * rows - 1) * (position + 1) > list .size() ? list.size() : (columns * rows - 1) * (position + 1))); /** * 末尾添加删除图标 * */ if (subList.size() < (columns * rows - 1)) { for (int i = subList.size(); i < (columns * rows - 1); i++) { subList.add(null); } } Emoji deleteEmoji = new Emoji(); deleteEmoji.setImageUri(R.drawable.face_delete); subList.add(deleteEmoji); FaceGVAdapter mGvAdapter = new FaceGVAdapter(subList, getActivity()); gridview.setAdapter(mGvAdapter); gridview.setNumColumns(columns); // 单击表情执行的操做 gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (position == columns * rows - 1) { if(listener != null){ listener.onEmojiDelete(); } return; } if(listener != null){ listener.onEmojiClick(subList.get(position)); } insertToRecentList(subList.get(position)); } }); return gridview; } private void insertToRecentList(Emoji emoji) { if (emoji != null) { if (recentlyEmojiList.contains(emoji)) { //若是已经有该表情,就把该表情放到第一个位置 int index = recentlyEmojiList.indexOf(emoji); Emoji emoji0 = recentlyEmojiList.get(0); recentlyEmojiList.set(index, emoji0); recentlyEmojiList.set(0, emoji); return; } if (recentlyEmojiList.size() == (rows * columns - 1)) { //去掉最后一个 recentlyEmojiList.remove(rows * columns - 2); } recentlyEmojiList.add(0, emoji); } } @Override public void onDestroyView() { super.onDestroyView(); try { recentManager.putCollection(RecentEmojiManager.PREFERENCE_NAME, recentlyEmojiList); } catch (IOException e) { e.printStackTrace(); } } class FaceGVAdapter extends BaseAdapter { private List<Emoji> list; private Context mContext; public FaceGVAdapter(List<Emoji> list, Context mContext) { super(); this.list = list; this.mContext = mContext; } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return list.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = LayoutInflater.from(mContext).inflate(R.layout.item_face, null); holder.iv = (ImageView) convertView.findViewById(R.id.face_image); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } if (list.get(position) != null) { holder.iv.setImageBitmap(EmojiUtil.decodeSampledBitmapFromResource(getActivity().getResources(), list.get(position).getImageUri(), EmojiUtil.dip2px(getActivity(), 32), EmojiUtil.dip2px(getActivity(), 32))); } return convertView; } class ViewHolder { ImageView iv; } } class FaceVPAdapter extends PagerAdapter { // 界面列表 private List<View> views; public FaceVPAdapter(List<View> views) { this.views = views; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { ((ViewPager) arg0).removeView((View) (arg2)); } @Override public int getCount() { return views.size(); } // 初始化arg1位置的界面 @Override public Object instantiateItem(View arg0, int arg1) { ((ViewPager) arg0).addView(views.get(arg1)); return views.get(arg1); } // 判断是否由对象生成界 @Override public boolean isViewFromObject(View arg0, Object arg1) { return (arg0 == arg1); } } 让你的Activity实现(Fragment中set接口)这个接口来处理emoji的点击事件 public interface OnEmojiClickListener { void onEmojiDelete(); void onEmojiClick(Emoji emoji); } }
你能够在EmojiUtil这个类中定义你的emoji编码去符合你的项目需求以及你须要在TextView中显示的Span大小。ui
public class EmojiUtil { private static ArrayList<Emoji> emojiList; public static ArrayList<Emoji> getEmojiList() { if (emojiList == null) { emojiList = generateEmojis(); } return emojiList; } private static ArrayList<Emoji> generateEmojis() { ArrayList<Emoji> list = new ArrayList<>(); for (int i = 0; i < EmojiResArray.length; i++) { Emoji emoji = new Emoji(); emoji.setImageUri(EmojiResArray[i]); emoji.setContent(EmojiTextArray[i]); list.add(emoji); } return list; } public static final int[] EmojiResArray = { R.drawable.d_aini, R.drawable.d_aoteman, R.drawable.d_baibai, R.drawable.d_beishang, R.drawable.d_bishi, R.drawable.d_bizui, R.drawable.d_chanzui, R.drawable.d_chijing, R.drawable.d_dahaqi, R.drawable.d_dalian, R.drawable.d_ding, R.drawable.d_doge, R.drawable.d_feizao, R.drawable.d_ganmao, R.drawable.d_guzhang, R.drawable.d_haha, R.drawable.d_haixiu, R.drawable.d_han, R.drawable.d_hehe, R.drawable.d_heixian, R.drawable.d_heng, R.drawable.d_huaxin, R.drawable.d_jiyan, R.drawable.d_keai, R.drawable.d_kelian, R.drawable.d_ku, R.drawable.d_kun, R.drawable.d_landelini, R.drawable.d_lei, R.drawable.d_madaochenggong, R.drawable.d_miao, R.drawable.d_nanhaier, R.drawable.d_nu, R.drawable.d_numa, R.drawable.d_numa, R.drawable.d_qian, R.drawable.d_qinqin, R.drawable.d_shayan, R.drawable.d_shengbing, R.drawable.d_shenshou, R.drawable.d_shiwang, R.drawable.d_shuai, R.drawable.d_shuijiao, R.drawable.d_sikao, R.drawable.d_taikaixin, R.drawable.d_touxiao, R.drawable.d_tu, R.drawable.d_tuzi, R.drawable.d_wabishi, R.drawable.d_weiqu, R.drawable.d_xiaoku, R.drawable.d_xiongmao, R.drawable.d_xixi, R.drawable.d_xu, R.drawable.d_yinxian, R.drawable.d_yiwen, R.drawable.d_youhengheng, R.drawable.d_yun, R.drawable.d_zhajipijiu, R.drawable.d_zhuakuang, R.drawable.d_zhutou, R.drawable.d_zuiyou, R.drawable.d_zuohengheng, R.drawable.f_geili, R.drawable.f_hufen, R.drawable.f_jiong, R.drawable.f_meng, R.drawable.f_shenma, R.drawable.f_v5, R.drawable.f_xi, R.drawable.f_zhi, R.drawable.h_buyao, R.drawable.h_good, R.drawable.h_haha, R.drawable.h_lai, R.drawable.h_ok, R.drawable.h_quantou, R.drawable.h_ruo, R.drawable.h_woshou, R.drawable.h_ye, R.drawable.h_zan, R.drawable.h_zuoyi, R.drawable.l_shangxin, R.drawable.l_xin, R.drawable.o_dangao, R.drawable.o_feiji, R.drawable.o_ganbei, R.drawable.o_huatong, R.drawable.o_lazhu, R.drawable.o_liwu, R.drawable.o_lvsidai, R.drawable.o_weibo, R.drawable.o_weiguan, R.drawable.o_yinyue, R.drawable.o_zhaoxiangji, R.drawable.o_zhong, R.drawable.w_fuyun, R.drawable.w_shachenbao, R.drawable.w_taiyang, R.drawable.w_weifeng, R.drawable.w_xianhua, R.drawable.w_xiayu, R.drawable.w_yueliang, }; public static final String[] EmojiTextArray = { "[爱你]", "[奥特曼]", "[拜拜]", "[悲伤]", "[鄙视]", "[闭嘴]", "[馋嘴]", "[吃惊]", "[哈欠]", "[打脸]", "[顶]", "[doge]", "[肥皂]", "[感冒]", "[鼓掌]", "[哈哈]", "[害羞]", "[汗]", "[微笑]", "[黑线]", "[哼]", "[色]", "[挤眼]", "[可爱]", "[可怜]", "[酷]", "[困]", "[白眼]", "[泪]", "[马到成功]", "[喵喵]", "[男孩儿]", "[怒]", "[怒骂]", "[女孩儿]", "[钱]", "[亲亲]", "[傻眼]", "[生病]", "[草泥马]", "[失望]", "[衰]", "[睡]", "[思考]", "[太开心]", "[偷笑]", "[吐]", "[兔子]", "[挖鼻]", "[委屈]", "[笑cry]", "[熊猫]", "[嘻嘻]", "[嘘]", "[阴险]", "[疑问]", "[右哼哼]", "[晕]", "[炸鸡啤酒]", "[抓狂]", "[猪头]", "[最右]", "[左哼哼]", "[给力]", "[互粉]", "[囧]", "[萌]", "[神马]", "[威武]", "[喜]", "[织]", "[NO]", "[good]", "[haha]", "[来]", "[OK]", "[拳头]", "[弱]", "[握手]", "[耶]", "[赞]", "[做揖]", "[伤心]", "[心]", "[蛋糕]", "[飞机]", "[干杯]", "[话筒]", "[蜡烛]", "[礼物]", "[绿丝带]", "[围脖]", "[围观]", "[音乐]", "[照相机]", "[钟]", "[浮云]", "[沙尘暴]", "[太阳]", "[微风]", "[鲜花]", "[下雨]", "[月亮]", }; static { emojiList = generateEmojis(); } public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // 源图片的高度和宽度 final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // 计算出实际宽高和目标宽高的比率 final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // 选择宽和高中最小的比率做为inSampleSize的值,这样能够保证最终图片的宽和高 // 必定都会大于等于目标的宽和高。 inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小 final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // 调用上面定义的方法计算inSampleSize值 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 使用获取到的inSampleSize值再次解析图片 options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } public static int dip2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } //传递进来你所须要显示emoji的TextView便可 public static void handlerEmojiText(TextView comment, String content, Context context) throws IOException { SpannableStringBuilder sb = new SpannableStringBuilder(content); String regex = "\\[(\\S+?)\\]"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(content); Iterator<Emoji> iterator; Emoji emoji = null; while (m.find()) { iterator = emojiList.iterator(); String tempText = m.group(); while (iterator.hasNext()) { emoji = iterator.next(); if (tempText.equals(emoji.getContent())) { //转换为Span并设置Span的大小 sb.setSpan(new ImageSpan(context, decodeSampledBitmapFromResource(context.getResources(), emoji.getImageUri() , dip2px(context, 18), dip2px(context, 18))), m.start(), m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); break; } } } comment.setText(sb); } }
具体操做方法:this
GitHub地址:https://github.com/shiqikai/y...编码
或者直接spa
compile'com.tb.emoji:yykEmoji:1.0.0'
谨此记念那9月,一块儿开发的咱们--谢遥,唐荣意,史琪锴。code