Android之Emoji表情開源庫

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

相關文章
相關標籤/搜索