上次做了一个表情的控件,不敢私藏,给大家分享
效果图如下,图片是新浪微博的,该有的功能应该都有了。
这其实就是一个Fragment,所以用起来很方便,只要
FaceFragment faceFragment = FaceFragment.Instance();
getSupportFragmentManager().beginTransaction().add(R.id.Container,faceFragment).commit();
就可以显示效果图上的效果了。
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大小。
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);
}
}
具体操作方法:
GitHub地址:https://github.com/shiqikai/y...
或者直接
compile'com.tb.emoji:yykEmoji:1.0.0'
谨此纪念那9月,一起开发的我们--谢遥,唐荣意,史琪锴。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。