上次作了一個表情的控件,不敢私藏,給你們分享
效果圖以下,圖片是新浪微博的,該有的功能應該都有了。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