解读(五):分析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 …
时间: 2024-10-27 09:28:26