解读(五):分析KeyboardFragment, 带文字和表情的评论发表面板
来源:互联网 发布:json转换java对象 编辑:程序博客网 时间:2024/04/30 18:23
解读(五):分析KeyboardFragment, 带文字和表情的评论发表面板
其实就是这个常见的功能
这个功能涉及到很多类, 我一个一个分析
KeyboardFragment类
/** * 底部带emotion面板的文字和表情的评论功能的Fragment **/public class KeyboardFragment extends BaseTabNavFragment { @Bind(R.id.et_input) EditText mInput; //输入框 @Bind(R.id.emotion_layout) LinearLayout mEmoLayout; //表情的布局 @Bind(R.id.iv_emotion) ImageView mIvEmotion; //发布评论的图片 // 回复的对象 private Comment mReplyCmm; //委托类对象,它管理着键盘, emotion按钮, 输入框, emotion面板之间的相互操作 private KeyboardActionDelegation mDelegatioin; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //加载底部emotion回复布局 return inflater.inflate(R.layout.fragment_keyboard, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ButterKnife.bind(this, view); //这个委托类对象很重要 mDelegatioin = new KeyboardActionDelegation(mContext, mInput, mIvEmotion, mEmoLayout); //初始化订阅者 initSubscribers(); //设置ViewPager第一页选中 mViewPager.setCurrentItem(0); } /** * 注册事件订阅者 */ private void initSubscribers() { // register a listener to receive a event that mean user selected a emotion // 注册一个监听器接收用户选择了一个emotion表情的事件 RxBus.with(this) .setEvent(Events.EventEnum.DELIVER_SELECT_EMOTION) //设置过滤接收选择一个emotion表情事件 .setEndEvent(FragmentEvent.DESTROY) //直到Fragment destroy为止 .onNext((events -> { EmotionRules emotion = events.<EmotionRules>getMessage(); mDelegatioin.onEmotionItemSelected(emotion); //设置所选的emotion })).create(); // 接受返回事件,如果显示表情面板,隐藏!如果显示软键盘,隐藏!如果显示回复某某某,隐藏! RxBus.with(this) .setEvent(Events.EventEnum.DELIVER_GO_BACK) //接收返回事件 .setEndEvent(FragmentEvent.DESTROY) //直到Fragment destroy为止 .onNext((events -> { if (mReplyCmm != null) { //如果回复评论不为空,重置回复评论对象 mInput.setHint(getResources().getString(R.string.please_say_something)); mReplyCmm = null; return; } if (!mDelegatioin.onTurnBack())//如果点击了返回按钮 return; RxBus.getInstance().send(Events.EventEnum.WE_HIDE_ALL, null); //发送一个隐藏全部的事件 })).create(); RxBus.with(this) .setEvent(Events.EventEnum.DELIVER_REPLY_SOMEONE) //接收一个回复某人的事件 .setEndEvent(FragmentEvent.DESTROY) //直到Fragment destroy为止 .onNext((events -> { mReplyCmm = events.getMessage(); //获得评论对象 mInput.setHint("回复 @" + mReplyCmm.getAuthor()); //设置hint为@某人 })).create(); RxBus.with(this) .setEvent(Events.EventEnum.DELIVER_CLEAR_IMPUT) //接收一个清空输入框事件 .setEndEvent(FragmentEvent.DESTROY)//直到Fragment destroy为止 .onNext((events -> { mInput.setHint(getResources().getString(R.string.please_say_something)); //重置输入框 mInput.setText(null); })).create(); } /** * 设置Tab item的View */ @Override public View setupTabItemView(String title) { //设置emoji笑脸图标的布局属性 ImageView view = new ImageView(mContext); view.setImageResource(R.mipmap.icon_emotion_color); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( 0, ViewGroup.LayoutParams.MATCH_PARENT ); params.weight = 1; view.setLayoutParams(params); return view; } /** * 设置tab,调用的是本类中的addTab()方法 */ @Override public void onSetupTabs() { addTab(getResources().getString(R.string.emotion_qq), EmotionPanelFragment.class); } /** * 总在前面添加元素,跟默认的基类做法相悖,所以我们复写它 */ @Override public void addTab(String title, Class<? extends Fragment> fragment) { mTabs.add(0, new ViewPageInfo(title, Fragment.instantiate(getActivity(), fragment.getName()))); View view = setupTabItemView(title); //创建Tab item的View mNavLayout.addView(view, 0); //每次都添加到前面 mTabs.get(0).view = view; } /** * 删除表情或字符 */ @OnClick(R.id.iv_backspace) public void removeEmotion() { InputHelper.backspace(mInput); //退格 } /** * 发送信息 */ @OnClick(R.id.iv_send) public void sendComment() { // 如果没有输入评论 if (Utilities.isEmpty(mInput.getText().toString())) { Toast.makeText(mContext, "别闹,写点东西再发╭∩╮(︶︿︶)╭∩╮", Toast.LENGTH_SHORT).show(); return; } // 判断是否登录 if (AppManager.LOCAL_LOGINED_USER == null) { UIManager.jump2login(mContext); //调到登录 return; } // 封装实体, 发送消息给相应的presenter Comment comment = new Comment(); if (mReplyCmm == null) { comment.setId(-1L); } else { comment.setId(mReplyCmm.getId()); comment.setAuthorId(mReplyCmm.getAuthorId()); } comment.setContent(mInput.getText().toString()); //创建评论的事件 Events<Comment> events = Events.just(comment); events.what = Events.EventEnum.DELIVER_SEND_COMMENT; //发送评论 RxBus.getInstance().send(events); //发送评论的事件 }}
这个类主要是创建了底部评论功能的布局(依靠强大的父类BaseTabNavFragment,只要重写setupItemView(),onSetupTabs()和addTab()即可), 使用RxBus注册了一系列的评论相关是事件接受者, 点击评论按钮时将评论内容封装成对象使用RxBus发送出去.
这个类精彩的地方是一连串的RxBus的使用. 从这里看出来RxJava真心的强大和好用.
代码中有一个委托类对象, 这个对象很重要, 管理了软键盘, emotion按钮, 输入框, emotion面板的关联操作
//这个委托类对象很重要mDelegatioin = new KeyboardActionDelegation(mContext, mInput, mIvEmotion, mEmoLayout);
KeyboardActionDelegation类
/** * 键盘, emotion按钮, 输入框, emotion面板之间的相互关系委派给这个类管理 */public class KeyboardActionDelegation { private ImageView mBtnEmotion; //Emotion按钮 private EditText mInput; //输入框 private Context mContext; private ViewGroup mEmotionPanel; //Emotion面板 private boolean isShowSoftInput; //是否显示输入法 public KeyboardActionDelegation(Context context, EditText input, ImageView button, ViewGroup view) { this.mBtnEmotion = button; this.mInput = input; this.mContext = context; this.mEmotionPanel = view; init(); } /** * 初始化, 绑定事件 */ private void init() { //输入框焦点改变的监听 mInput.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { hideEmotionPanel(); //隐藏Emotion面板 } else { hideSoftKeyboard(); //隐藏键盘 } } }); //输入框点击事件的监听 mInput.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!isEmotionPanelShowing())//如果Emotion面板没有显示则直接返回 return; hideEmotionPanel();//隐藏Emotion面板 } }); //Emotion表情按钮被点击的监听 mBtnEmotion.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isEmotionPanelShowing()) {//如果Emotion面板显示 hideEmotionPanel(); //隐藏Emotionm面板 } else { showEmotionPanel();//显示Emotion面板 } } }); } /** * 显示Emotion面板 */ public void showEmotionPanel() { mBtnEmotion.setSelected(true);//设置Emotion按钮被选中, 改变了Emotion按钮的显示表情 hideSoftKeyboard();//隐藏输入法 new Handler().postDelayed(new Runnable() { @Override public void run() { mEmotionPanel.setVisibility(View.VISIBLE); //设置可见 } }, 300); } /** * 判断Emotion面板是否显示 */ private boolean isEmotionPanelShowing() { return mEmotionPanel.getVisibility() == View.VISIBLE; } /** * 隐藏软键盘 */ private void hideSoftKeyboard() { DeviceManager.getSoftInputManager(mContext).hideSoftInputFromWindow(mInput.getWindowToken(), 0); isShowSoftInput = false; } /** * 隐藏表情面板 */ private void hideEmotionPanel() { mEmotionPanel.setVisibility(View.GONE);//设置不占位 mBtnEmotion.setSelected(false); } /** * 是否显示输入法 */ public boolean isShowSoftInput() { return isShowSoftInput; } /** * Emotion面板中item被选中 */ public void onEmotionItemSelected(EmotionRules emotion) { if (mInput == null || emotion == null) { return; } int start = mInput.getSelectionStart();//获取选中文本的起始位置 int end = mInput.getSelectionEnd(); //获取选中文本的结束位置 if (start == end) { //如果未选中文本 mInput.append(InputHelper.insertEtn(mContext, emotion)); //将Emotion表情直接追加到光标后 } else { //如果有选中文本 Spannable str = InputHelper.insertEtn(mContext, emotion);//获得需要插入的内容 mInput.getText().replace(Math.min(start, end), Math.max(start, end), str, 0, str.length());//用Emotion表情替换掉选中的文本 } } /** * 当使用回退键时, 让Emotion面板和输入法都隐藏 */ public boolean onTurnBack() { if (isEmotionPanelShowing()) { hideEmotionPanel(); return false; } if (isShowSoftInput()) { hideEmotionPanel(); return false; } return true; }}
这个类其实就是管理了不同的状态变化, 判断是否要显示隐藏输入法, Emotion面板等.
这里面比较重要的一个方法是onEmotionItemSelected(), 也就是Emotion面板中表情被选中后的操作.
/** * Emotion面板中item被选中 */public void onEmotionItemSelected(EmotionRules emotion) { if (mInput == null || emotion == null) { return; } int start = mInput.getSelectionStart();//获取选中文本的起始位置 int end = mInput.getSelectionEnd(); //获取选中文本的结束位置 if (start == end) { //如果未选中文本 mInput.append(InputHelper.insertEtn(mContext, emotion)); //将Emotion表情直接追加到光标后 } else { //如果有选中文本 Spannable str = InputHelper.insertEtn(mContext, emotion);//获得需要插入的内容 mInput.getText().replace(Math.min(start, end), Math.max(start, end), str, 0, str.length());//用Emotion表情替换掉选中的文本 }}
- 如果编辑框中有选中的文本,则用表情直接替换文本, 如果没有, 则直接添加到光标后面. 这个方法在上面的KeyboardFragment中被调用.
// 注册一个监听器接收用户选择了一个emotion表情的事件RxBus.with(this) .setEvent(Events.EventEnum.DELIVER_SELECT_EMOTION) //设置过滤接收选择一个emotion表情事件 .setEndEvent(FragmentEvent.DESTROY) //直到Fragment destroy为止 .onNext((events -> { EmotionRules emotion = events.<EmotionRules>getMessage(); mDelegatioin.onEmotionItemSelected(emotion); //设置所选的emotion })).create();
- KeyboardActionDelegation#onEmotionItemSelected()中使用了InputHelper#insertEtn()实现了在文字中插入Emotion表情. 这里涉及到了图文混排.
InputHelper类
/** * 输入帮助类 */public class InputHelper { /** * 退格 */ public static void backspace(EditText input) { if (input == null) { return; } KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL); input.dispatchKeyEvent(event); } /** * 插入表情到文字中, 这里使用到了SpannableString和ImageSpan实现图文混排 */ @SuppressWarnings("all") public static Spannable insertEtn(Context context, EmotionRules emotion) { String remote = emotion.getRemote(); //获得表情的序号 Spannable spannable = new SpannableString(remote); //创建文本样式 Drawable d = context.getResources().getDrawable(emotion.getMResId()); //获得emotion的drawable d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); //设置边界为drawable的真实宽高 ImageSpan iSpan = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);//获得图片样式 //Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 前后输入的字符都不应用这种Spannable spannable.setSpan(iSpan, 0, remote.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); return spannable; } public static void encode(TextView view, String content) { view.setText(""); StringBuilder mNormalBuilder = new StringBuilder(); StringBuilder mEtnBuilder = new StringBuilder(); boolean isCut = false; //是否截断 for (int i = 0; i < content.length(); i++) { char unit = content.charAt(i); // 截断,保存在etnBuilder容器 if (isCut) { // 截断期间发现新的[,将之前的缓存存入view,刷新容器 if (unit == '[') { mNormalBuilder.append(mEtnBuilder.toString()); mEtnBuilder.delete(0, mEtnBuilder.length()); mEtnBuilder.append(unit); continue; } if (unit == ']') { mEtnBuilder.append(unit); EmotionRules rule = EmotionRules.containOf(mEtnBuilder.toString()); view.append(mNormalBuilder.toString()); if (rule != null) { view.append(insertEtn(view.getContext(), rule)); } else { view.append(mEtnBuilder.toString()); } mNormalBuilder.delete(0, mNormalBuilder.length()); mEtnBuilder.delete(0, mEtnBuilder.length()); isCut = false; continue; } mEtnBuilder.append(unit); } else { // --> 非截断 if (unit == '[') { mEtnBuilder.append(unit); isCut = true; continue; } mNormalBuilder.append(unit); } } view.append(mNormalBuilder.toString()); //追加到TextView的显示缓冲区 view.append(mEtnBuilder.toString()); }}
//TODO: encode()还没看的太懂, 留个TODO占坑吧.
这个类最重要的方法是InputHelper#insertEtn(). 实现了图文混排效果.
/** * 插入表情到文字中, 这里使用到了SpannableString和ImageSpan实现图文混排 */@SuppressWarnings("all")public static Spannable insertEtn(Context context, EmotionRules emotion) { String remote = emotion.getRemote(); //获得表情的序号 Spannable spannable = new SpannableString(remote); //创建文本样式 Drawable d = context.getResources().getDrawable(emotion.getMResId()); //获得emotion的drawable d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); //设置边界为drawable的真实宽高 ImageSpan iSpan = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);//获得图片样式 //Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 前后输入的字符都不应用这种Spannable spannable.setSpan(iSpan, 0, remote.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); return spannable;}
- 这里讲解下setSpan()方法. ImageSpan 可以使用图片替换文字达到图文混排的效果,例如在一般聊天工具当中在文字和表情一起发的状态。
public void setSpan(Object what, int start, int end, int flags);
- what传入各种Span类型的实例,start和end标记要替代的文字内容的范围,flags是用来标识在 Span 范围内的文本前后输入新的字符时是否把它们也应用这个效果,可以传入Spanned.SPAN_EXCLUSIVE_EXCLUSIVE、Spanned.SPAN_INCLUSIVE_EXCLUSIVE、Spanned.SPAN_EXCLUSIVE_INCLUSIVE、Spanned.SPAN_INCLUSIVE_INCLUSIVE几个参数,INCLUSIVE表示应用该效果,EXCLUSIVE表示不应用该效果,如Spanned.SPAN_INCLUSIVE_EXCLUSIVE表示对前面的文字应用该效果,而对后面的文字不应用该效果。
下面这个也可以算是一个模板代码了.
Drawabledrawable=mContext.getResources().getDrawable(R.drawable.new_topic_drawable);drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);spanString.setSpan(imageSpan,spanString.length()-1,spanString.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
- 以上部分摘自: Android中实现不同文字颜色和图文混排的Span总结
EmotionPanelFragment类
这个类从名字上就可以看出是Emotion面板的Fragment.
/** * Emotion面板的Fragment **/public class EmotionPanelFragment extends BaseTabNavFragment { public static final int COLUMN = 7; //7列 public static final int ROW = 3; //3行 @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); setCurrentItem(0); //设置当前选中的item } /** * 设置Emotion面板中的每个View, 也就是每个Emotion表情 */ @Override public View setupTabItemView(String title) { //每个Emotion表情就是一个带圆形背景的TextView TextView view = new TextView(mContext); int m4 = UIHelper.dip2px(mContext, 4); LinearLayout.LayoutParams layout = new LinearLayout.LayoutParams(m4, m4); int m5 = UIHelper.dip2px(mContext, 5); layout.setMargins(m5, m5, m5, m5); //外边距 view.setLayoutParams(layout); view.setBackgroundResource(R.drawable.selector_dot_nav); //设置圆形背景 return view; } /** * 填充tab中的表情, 这里使用了分页填充 */ @Override public void onSetupTabs() { EmotionRules[] rules = EmotionRules.values(); //获得EmotionRules预定义的枚举项 //一页显示几条 int page_size = COLUMN * ROW; //总共多少页 int page_count = (rules.length + page_size - 1) / page_size; int i; //分页 for (i = 0; i < page_count - 1; i++) { //如果是前page-1页,直接添加满即可 addTab("", initView(i * page_size, (i + 1) * page_size - 1)); } //最后一页添加到表情结束 addTab("", initView(i * page_size, rules.length - 1)); } /** * 用持有GridView的ViewFragment,填充到tab中去 */ public void addTab(String title, View view) { addTab(title, new ViewFragment(view)); } /** * 初始化Emotion表情展示的GridView */ private View initView(int start, int end) { final EmotionRules[] rules = Arrays.copyOfRange(EmotionRules.values(), start, end + 1);//得到一份EmotionRules的拷贝 GridView view = new GridView(mContext); //创建一个GridView展示Emotion表情 GridView.LayoutParams params = new GridView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ); view.setLayoutParams(params); view.setNumColumns(COLUMN); //设置列数 view.setAdapter(new EmotionAdapter(rules)); //设置适配器,实现在下面 view.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Events<EmotionRules> events = Events.just(rules[position]); //封装事件实体,发送Emotion表情被选中的事件 events.what = Events.EventEnum.DELIVER_SELECT_EMOTION; RxBus.getInstance().send(events); //又见RxBus,真是神器啊 } }); return view; } @Override public FragmentManager getGenuineFragmentManager() { return getChildFragmentManager(); } /** * 一个典型的适配器 */ public static class EmotionAdapter extends BaseAdapter { private EmotionRules[] rules; public EmotionAdapter(EmotionRules[] rules) { this.rules = rules; } @Override public int getCount() { return rules.length; } @Override public Object getItem(int position) { return rules[position]; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHandler handler; if (convertView == null) { convertView = new ImageView(parent.getContext()); int m3 = UIHelper.dip2px(parent.getContext(), 3f); convertView.setPadding(m3, m3, m3, m3); handler = new ViewHandler(); handler.iView = (ImageView) convertView; convertView.setTag(handler); } else { handler = (ViewHandler) convertView.getTag(); } handler.iView.setImageResource(rules[position].getMResId()); //将Emotion表情设置到ImageView return convertView; } class ViewHandler { public ImageView iView; } }}
- 这段代码比较简单, 就是将Emotion表情填充到面板中,每个页面都是一个ViewFragment.
ViewFragment类
/** * 一个简单的Fragment,专门显示一个View,特别服务于轮番、ViewPager */@SuppressLint("ValidFragment")public class ViewFragment extends BaseFragment { private View view; public ViewFragment(View view) { this.view = view; } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return view; }}
ViewFragment内部持有了一个View对象. 可以简单的理解为将View转化为一个Fragment.
在Emotion面板中, Emotion表情是使用一个EmotionRules管理的. EmotionRules枚举类制定了Emotion表情的规则. 这个命名真不错.
EmotionRules类
/** * 定义了emotion规则: 类型,图表,文字含义,序号 */public enum EmotionRules { EMOTION0(0, R.mipmap.smiley_0, "[微笑]", "[0]"), EMOTION1(0, R.mipmap.smiley_1, "[撇嘴]", "[1]"), EMOTION2(0, R.mipmap.smiley_2, "[色]", "[2]"), EMOTION3(0, R.mipmap.smiley_3, "[发呆]", "[3]"), EMOTION4(0, R.mipmap.smiley_4, "[得意]", "[4]"), EMOTION5(0, R.mipmap.smiley_5, "[流泪]", "[5]"), EMOTION6(0, R.mipmap.smiley_6, "[害羞]", "[6]"), EMOTION7(0, R.mipmap.smiley_7, "[闭嘴]", "[7]"), EMOTION8(0, R.mipmap.smiley_8, "[睡]", "[8]"), EMOTION9(0, R.mipmap.smiley_9, "[大哭]", "[9]"), EMOTION10(0, R.mipmap.smiley_10, "[尴尬]", "[10]"), EMOTION11(0, R.mipmap.smiley_11, "[发怒]", "[11]"), EMOTION12(0, R.mipmap.smiley_12, "[调皮]", "[12]"), EMOTION13(0, R.mipmap.smiley_13, "[呲牙]", "[13]"), EMOTION14(0, R.mipmap.smiley_14, "[惊讶]", "[14]"), EMOTION15(0, R.mipmap.smiley_15, "[难过]", "[15]"), EMOTION16(0, R.mipmap.smiley_16, "[酷]", "[16]"), EMOTION17(0, R.mipmap.smiley_17, "[冷汗]", "[17]"), EMOTION18(0, R.mipmap.smiley_18, "[抓狂]", "[18]"), EMOTION19(0, R.mipmap.smiley_19, "[吐]", "[19]"), EMOTION20(0, R.mipmap.smiley_20, "[偷笑]", "[20]"), EMOTION21(0, R.mipmap.smiley_21, "[可爱]", "[21]"), EMOTION22(0, R.mipmap.smiley_22, "[白眼]", "[22]"), EMOTION23(0, R.mipmap.smiley_23, "[傲慢]", "[23]"), EMOTION24(0, R.mipmap.smiley_24, "[饥饿]", "[24]"), EMOTION25(0, R.mipmap.smiley_25, "[困]", "[25]"), EMOTION26(0, R.mipmap.smiley_26, "[惊恐]", "[26]"), EMOTION27(0, R.mipmap.smiley_27, "[流汗]", "[27]"), EMOTION28(0, R.mipmap.smiley_28, "[憨笑]", "[28]"), EMOTION29(0, R.mipmap.smiley_29, "[大兵]", "[29]"), EMOTION30(0, R.mipmap.smiley_30, "[奋斗]", "[30]"), EMOTION31(0, R.mipmap.smiley_31, "[咒骂]", "[31]"), EMOTION32(0, R.mipmap.smiley_32, "[疑问]", "[32]"), EMOTION33(0, R.mipmap.smiley_33, "[嘘]", "[33]"), EMOTION34(0, R.mipmap.smiley_34, "[晕]", "[34]"), EMOTION35(0, R.mipmap.smiley_35, "[折磨]", "[35]"), EMOTION36(0, R.mipmap.smiley_36, "[衰]", "[36]"), EMOTION37(0, R.mipmap.smiley_37, "[骷髅]", "[37]"), EMOTION38(0, R.mipmap.smiley_38, "[敲打]", "[38]"), EMOTION39(0, R.mipmap.smiley_39, "[再见]", "[39]"), EMOTION40(0, R.mipmap.smiley_40, "[擦汗]", "[40]"), EMOTION41(0, R.mipmap.smiley_41, "[抠鼻]", "[41]"), EMOTION42(0, R.mipmap.smiley_42, "[鼓掌]", "[42]"), EMOTION43(0, R.mipmap.smiley_43, "[糗大了]", "[43]"), EMOTION44(0, R.mipmap.smiley_44, "[坏笑]", "[44]"), EMOTION45(0, R.mipmap.smiley_45, "[左哼哼]", "[45]"), EMOTION46(0, R.mipmap.smiley_46, "[右哼哼]", "[46]"), EMOTION47(0, R.mipmap.smiley_47, "[哈欠]", "[47]"), EMOTION48(0, R.mipmap.smiley_48, "[鄙视]", "[48]"), EMOTION49(0, R.mipmap.smiley_49, "[委屈]", "[49]"), EMOTION50(0, R.mipmap.smiley_50, "[快哭了]", "[50]"), EMOTION51(0, R.mipmap.smiley_51, "[阴险]", "[51]"), EMOTION52(0, R.mipmap.smiley_52, "[亲亲]", "[52]"), EMOTION53(0, R.mipmap.smiley_53, "[吓]", "[53]"), EMOTION54(0, R.mipmap.smiley_54, "[可怜]", "[54]"); private int type; private int mResId; private String name; private String remote; EmotionRules(int type, int mResId, String name, String remote) { this.type = type; this.mResId = mResId; this.name = name; this.remote = remote; } public int getType() { return type; } public void setType(int type) { this.type = type; } public int getMResId() { return mResId; } public void setMResId(int mResId) { this.mResId = mResId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRemote() { return remote; } public void setRemote(String remote) { this.remote = remote; } /** * 判断emotion的中文含义和序号中是否包含指定的字符串 */ public static EmotionRules containOf(String s) { EmotionRules[] rules = EmotionRules.values(); for (EmotionRules item : rules) { if (item.getName().equals(s) || item.getRemote().equals(s)) return item; } return null; }}
这个类中, 将图片表情和文字都一一对应起来. 至于里面的remote字段是什么意思, 我也只能猜测是序号相关的东西了.
至此, 这个可以发送Emotion表情的评论面板功能已经分析完毕. to be continue …
- 解读(五):分析KeyboardFragment, 带文字和表情的评论发表面板
- 带表情的评论
- android textview 显示表情和文字 表情带超链接
- Android 表情面板的展示和表情的显示
- 表情面板的实现
- 支持跟踪和发表评论的Feed阅读器 -- PIMShell 2009.0903
- 发表评论的界面代码
- c++ builder 实现表情和文字的混合发送
- 支持表情插入的评论框
- 请求评论中表情包的方法
- Android 解决表情面板和软键盘切换时跳闪的问题
- 带流布局和按钮的内容分割面板
- 运用spinner和正则表达式pattern来实现文字中表情文字的替换
- 使用jQuery结合PHP和MySQL读取和发表评论
- 实现带图片和文字的imagebutton
- iOS 带文字和图片的button
- iOS 带文字和图片的button
- 自定义带图片和文字的ImageTextButton
- 北京林业大学“计蒜客”杯程序设计竞赛 网络赛 A-喝酒【模拟】
- 单例模式
- Echarts的使用和学习心得体会
- PAT-B 1013. 数素数
- CSS3三维相册
- 解读(五):分析KeyboardFragment, 带文字和表情的评论发表面板
- 命令行修改root密码
- 科学美国人60秒:熊狸的气味闻起来就像奶油爆米花 科学家或揭开其中奥秘
- maven的setting配置
- 如何正确卸载parallels desktop11
- 啊哈!算法—模拟链表
- GraphicsMagick在centos环境的安装
- 北京林业大学“计蒜客”杯程序设计竞赛 网络赛 B-大钉骑马走江湖【bfs】
- com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field 异常