package com.netease.nim.uikit.session.emoji; import android.content.Context; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.text.TextUtils; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import com.netease.nim.uikit.R; import com.netease.nim.uikit.common.util.log.LogUtil; import java.util.ArrayList; import java.util.List; /** * 贴图显示viewpager */ public class EmoticonView { private ViewPager emotPager; private LinearLayout pageNumberLayout; /** * 总页数. */ private int pageCount; /** * 每页显示的数量,Adapter保持一致. */ public static final int EMOJI_PER_PAGE = 27; // 最后一个是删除键 public static final int STICKER_PER_PAGE = 8; private Context context; private IEmoticonSelectedListener listener; private EmoticonViewPaperAdapter pagerAdapter = new EmoticonViewPaperAdapter(); /** * 所有表情贴图支持横向滑动切换 */ private int categoryIndex; // 当套贴图的在picker中的索引 private boolean isDataInitialized = false; // 数据源只需要初始化一次,变更时再初始化 private List<StickerCategory> categoryDataList; // 表情贴图数据源 private List<Integer> categoryPageNumberList; // 每套表情贴图对应的页数 private int[] pagerIndexInfo = new int[2]; // 0:category index;1:pager index in category private IEmoticonCategoryChanged categoryChangedCallback; // 横向滑动切换时回调picker public EmoticonView(Context context, IEmoticonSelectedListener mlistener, ViewPager mCurPage, LinearLayout pageNumberLayout) { this.context = context.getApplicationContext(); this.listener = mlistener; this.pageNumberLayout = pageNumberLayout; this.emotPager = mCurPage; emotPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { if (categoryDataList != null) { // 显示所有贴图表情 setCurStickerPage(position); if (categoryChangedCallback != null) { int currentCategoryChecked = pagerIndexInfo[0];// 当前那种类别被选中 categoryChangedCallback.onCategoryChanged(currentCategoryChecked); } } else { // 只显示表情 setCurEmotionPage(position); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageScrollStateChanged(int state) { } }); emotPager.setAdapter(pagerAdapter); emotPager.setOffscreenPageLimit(1); } public void setCategoryDataReloadFlag() { isDataInitialized = false; } public void showStickers(int index) { // 判断是否需要变化 if (isDataInitialized && getPagerInfo(emotPager.getCurrentItem()) != null && pagerIndexInfo[0] == index && pagerIndexInfo[1] == 0) { return; } this.categoryIndex = index; showStickerGridView(); } public void showEmojis() { showEmojiGridView(); } private int getCategoryPageCount(StickerCategory category) { if (category == null) { return (int) Math.ceil(EmojiManager.getDisplayCount() / (float) EMOJI_PER_PAGE); } else { if (category.hasStickers()) { List<StickerItem> stickers = category.getStickers(); return (int) Math.ceil(stickers.size() / (float) STICKER_PER_PAGE); } else { return 1; } } } private void setCurPage(int page, int pageCount) { int hasCount = pageNumberLayout.getChildCount(); int forMax = Math.max(hasCount, pageCount); ImageView imgCur = null; for (int i = 0; i < forMax; i++) { if (pageCount <= hasCount) { if (i >= pageCount) { pageNumberLayout.getChildAt(i).setVisibility(View.GONE); continue; } else { imgCur = (ImageView) pageNumberLayout.getChildAt(i); } } else { if (i < hasCount) { imgCur = (ImageView) pageNumberLayout.getChildAt(i); } else { imgCur = new ImageView(context); imgCur.setBackgroundResource(R.drawable.nim_view_pager_indicator_selector); pageNumberLayout.addView(imgCur); } } imgCur.setId(i); imgCur.setSelected(i == page); // 判断当前页码来更新 imgCur.setVisibility(View.VISIBLE); } } /** * ******************************** 表情 ******************************* */ private void showEmojiGridView() { pageCount = (int) Math.ceil(EmojiManager.getDisplayCount() / (float) EMOJI_PER_PAGE); pagerAdapter.notifyDataSetChanged(); resetEmotionPager(); } private void resetEmotionPager() { setCurEmotionPage(0); emotPager.setCurrentItem(0, false); } private void setCurEmotionPage(int position) { setCurPage(position, pageCount); } public OnItemClickListener emojiListener = new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { int position = emotPager.getCurrentItem(); int pos = position; // 如果只有表情,那么用默认方式计算 if (categoryDataList != null && categoryPageNumberList != null) { // 包含贴图 getPagerInfo(position); pos = pagerIndexInfo[1]; } int index = arg2 + pos * EMOJI_PER_PAGE; if (listener != null) { int count = EmojiManager.getDisplayCount(); if (arg2 == EMOJI_PER_PAGE || index >= count) { listener.onEmojiSelected("/DEL"); } else { String text = EmojiManager.getDisplayText((int) arg3); if (!TextUtils.isEmpty(text)) { listener.onEmojiSelected(text); } } } } }; /** * ******************************** 贴图 ******************************* */ private void showStickerGridView() { initData(); pagerAdapter.notifyDataSetChanged(); // 计算起始的pager index int position = 0; for (int i = 0; i < categoryPageNumberList.size(); i++) { if (i == categoryIndex) { break; } position += categoryPageNumberList.get(i); } setCurStickerPage(position); emotPager.setCurrentItem(position, false); } private void initData() { if (isDataInitialized) {//数据已经初始化,未变动不重新加载数据 return; } if (categoryDataList == null) { categoryDataList = new ArrayList<>(); } if (categoryPageNumberList == null) { categoryPageNumberList = new ArrayList<>(); } categoryDataList.clear(); categoryPageNumberList.clear(); final StickerManager manager = StickerManager.getInstance(); categoryDataList.add(null); // 表情 categoryPageNumberList.add(getCategoryPageCount(null)); List<StickerCategory> categories = manager.getCategories(); categoryDataList.addAll(categories); // 贴图 for (StickerCategory c : categories) { categoryPageNumberList.add(getCategoryPageCount(c)); } pageCount = 0;//总页数 for (Integer count : categoryPageNumberList) { pageCount += count; } isDataInitialized = true; } // 给定pager中的索引,返回categoryIndex和positionInCategory private int[] getPagerInfo(int position) { if (categoryDataList == null || categoryPageNumberList == null) { return pagerIndexInfo; } int cIndex = categoryIndex; int startIndex = 0; int pageNumberPerCategory = 0; for (int i = 0; i < categoryPageNumberList.size(); i++) { pageNumberPerCategory = categoryPageNumberList.get(i); if (position < startIndex + pageNumberPerCategory) { cIndex = i; break; } startIndex += pageNumberPerCategory; } this.pagerIndexInfo[0] = cIndex; this.pagerIndexInfo[1] = position - startIndex; return pagerIndexInfo; } private void setCurStickerPage(int position) { getPagerInfo(position); int categoryIndex = pagerIndexInfo[0]; int pageIndexInCategory = pagerIndexInfo[1]; int categoryPageCount = categoryPageNumberList.get(categoryIndex); setCurPage(pageIndexInCategory, categoryPageCount); } public void setCategoryChangCheckedCallback(IEmoticonCategoryChanged callback) { this.categoryChangedCallback = callback; } private OnItemClickListener stickerListener = new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { int position = emotPager.getCurrentItem(); getPagerInfo(position); int cIndex = pagerIndexInfo[0]; int pos = pagerIndexInfo[1]; StickerCategory c = categoryDataList.get(cIndex); int index = arg2 + pos * STICKER_PER_PAGE; // 在category中贴图的index if (index >= c.getStickers().size()) { LogUtil.i("sticker", "index " + index + " larger than size " + c.getStickers().size()); return; } if (listener != null) { StickerManager manager = StickerManager.getInstance(); List<StickerItem> stickers = c.getStickers(); StickerItem sticker = stickers.get(index); StickerCategory real = manager.getCategory(sticker.getCategory()); if (real == null) { return; } listener.onStickerSelected(sticker.getCategory(), sticker.getName()); } } }; /** * ***************************** PagerAdapter **************************** */ private class EmoticonViewPaperAdapter extends PagerAdapter { @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public int getCount() { return pageCount == 0 ? 1 : pageCount; } @Override public Object instantiateItem(ViewGroup container, int position) { StickerCategory category; int pos; if (categoryDataList != null && categoryDataList.size() > 0 && categoryPageNumberList != null && categoryPageNumberList.size() > 0) { // 显示所有贴图&表情 getPagerInfo(position); int cIndex = pagerIndexInfo[0]; category = categoryDataList.get(cIndex); pos = pagerIndexInfo[1]; } else { // 只显示表情 category = null; pos = position; } if (category == null) { pageNumberLayout.setVisibility(View.VISIBLE); GridView gridView = new GridView(context); gridView.setOnItemClickListener(emojiListener); gridView.setAdapter(new EmojiAdapter(context, pos * EMOJI_PER_PAGE)); gridView.setNumColumns(7); gridView.setHorizontalSpacing(5); gridView.setVerticalSpacing(5); gridView.setGravity(Gravity.CENTER); gridView.setSelector(R.drawable.nim_emoji_item_selector); container.addView(gridView); return gridView; } else { pageNumberLayout.setVisibility(View.VISIBLE); GridView gridView = new GridView(context); gridView.setPadding(10, 0, 10, 0); gridView.setOnItemClickListener(stickerListener); gridView.setAdapter(new StickerAdapter(context, category, pos * STICKER_PER_PAGE)); gridView.setNumColumns(4); gridView.setHorizontalSpacing(5); gridView.setGravity(Gravity.CENTER); gridView.setSelector(R.drawable.nim_emoji_item_selector); container.addView(gridView); return gridView; } } @Override public void destroyItem(ViewGroup container, int position, Object object) { View layout = (View) object; container.removeView(layout); } public int getItemPosition(Object object) { return POSITION_NONE; } } }