项目中IM即时消息有个需求要做群成员@提醒功能,参考了QQ群聊的类似功能,实现过程大致分为:首先在编辑框输入@字符,跳转到选择群成员界面,选择完毕填充到编辑框内,用spannable着色;对选中的群成员点击,让光标落在尾处,保证群成员作为个人整体删除;如果有超过一页消息且有未读@消息,右上角有悬浮按钮提醒,点击后定位到首个未读的@消息。现在重新整理成一个demo,与大家分享下。效果图如下:

首先是监听编辑框输入的文本内容。如果最后一位是“@”字符,并且此时用户没有进行删除操作,则跳转到选择群成员界面。实现代码是实现TextChangedListener的监听,在onTextChanged方法进行判断:

public void onTextChanged(CharSequence s, int start, int before, int count) {// str.endsWith("@")// 输入@跳转到选择要@的人界面// 自定义表情是/:smile@ 类似于这种String str = s.toString();if (!isDelete) {if (str.endsWith("@")) {int index = str.lastIndexOf("@");if (index >= 1 && checkCharSequence(str.substring(index - 1, str.length() - 1))) {return;}Intent groupIntent = new Intent(MainActivity.this, SelectGroupMemberActivity.class);groupIntent.putExtra(SelectGroupMemberActivity.GROUP_MEMBER, (Serializable)groupMemberList);startActivityForResult(groupIntent, SelectGroupMemberActivity.REQUEST_CODE);}}}

选择群成员界面包括:多选、全选、根据群成员手机号或者姓名搜索选择。选择完毕点击确定后,返回聊天页面,编辑框自动填充选中的群成员,并且用spannable进行着色。

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (data != null && data.getExtras() != null) {boolean isAllSelected = data.getBooleanExtra(SelectGroupMemberActivity.SELECTED_ALL,false);List<GroupMember> tempList=(ArrayList<GroupMember>)data.getSerializableExtra(SelectGroupMemberActivity.SELECTED_MEMBER);selectedList.addAll(tempList);isDelete = true;//锁住Text监听Editable text = mEditText.getText();int index = text.toString().length();text = text.delete(index - 1, index);//删掉'@'if(isAllSelected){//如果是全选SpannableString ss = new SpannableString("@全体成员 ");//要@的人ss.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.blue)), 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EX                CLUSIVE);text = text.append(ss);}else {for(GroupMember member:tempList){SpannableString ss = new SpannableString("@" + member.getName() + " ");//要@的人ss.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.blue)), 0, ss.length(), Spanned.SPAN_EXCLUSIV                    E_EXCLUSIVE);text = text.append(ss);}}mEditText.setText(text);mEditText.setSelection(text.toString().length());isDelete = false;//解开Text监听}}

当用户点击选中的群成员时,如果点击焦点落在spannable的start与end之间区间,那么设置光标落在end处。

//监听EditText点击事件,删除时如果点击位置处于span的start与end区间,让光标落在end后面mEditText.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Editable editable = mEditText.getEditableText();ForegroundColorSpan[] spans = editable.getSpans(0, editable.length(), ForegroundColorSpan.class);if(spans.length == 0)return;int selectionStart = mEditText.getSelectionStart();for (ForegroundColorSpan span : spans) {int start = editable.getSpanStart(span);int end = editable.getSpanEnd(span);if(selectionStart >= start && selectionStart <= end){mEditText.setSelection(end);return;}}}});

当用户按下删除键时,遍历整个编辑框的所有spannable数组。如果删除位置与某个spannable数组元素吻合,则执行删除操作。特殊情况是,“ @全体成员”,如果执行删除则所有选中状态被清空。

public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {Editable editable = mEditText.getText();ForegroundColorSpan[] spans = editable.getSpans(0, editable.length(), ForegroundColorSpan.class);String str = editable.toString();for (int i = 0; i < spans.length; i++) {int spanStart = editable.getSpanStart(spans[i]);int spanEnd = editable.getSpanEnd(spans[i]);//@全体成员if (str.substring(spanStart, spanEnd).equals("@全体成员")) {editable = editable.delete(spanStart, spanEnd);
//                      selectedList.clear();isDelete = true;mEditText.setText(editable);return true;}if (str.substring(spanStart, spanEnd).equals("@" + selectedList.get(i).getName())) {//@单独成员if (mEditText.getSelectionStart() == spanEnd) {editable = editable.delete(spanStart, spanEnd);selectedList.remove(i);isDelete = true;mEditText.setText(editable);mEditText.setSelection(spanStart);break;}}}}return super.onKeyDown(keyCode, event);}

接下来是实现未读@消息的定位。这里,有个前提条件:有未读@消息,并且该消息不在当前页面。我是在CursorAdapter里面的getItem方法里,遍历未读消息,判断是否有未读@消息(实际应该是从服务器数据库获取对应字段来进行判断),如果有则返回true同时记录它的position。

public Boolean getItem(int position) {Cursor cursor = getCursor();cursor.moveToPosition(position);String content = cursor.getString(cursor.getColumnIndex(Provider.MessageColumns._MESSAGE_CONTENT));boolean hasAtMessage = false;if(content.contains("@") && content.contains(" ")){//判断是否含有@群成员String[] mArray = content.split("@");for(int i=1; i<mArray.length; i++){if(mArray[i] != null) {if(mArray[i].contains(" "))mArray[i] = mArray[i].substring(0,mArray[i].indexOf(" "));//@群成员后面可能有其他文字if (CURRENT_ACCOUNT.equals(mArray[i].trim())//这里假如当前用户是"徐福记6"|| ALL_MEMBERS.equals(mArray[i].trim())) {//或者是全体成员hasAtMessage = true;//标记有@消息mAtPosition = position;//@消息在list的positionbreak;}}}}return hasAtMessage;}

判断出未读@消息position位置后,需要在listView实现OnScrollListener监听,在OnScroll方法判断未读@消息是否在当前页面。如果不在当前页面,则显示未读@消息的悬浮按钮进行提醒。点击该按钮可定位到首个未读@消息,并且隐藏提醒。

     @Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {if((totalItemCount > visibleItemCount) && !hasOtherPage){//item总数大于可见item数,说明listView的item超过一页hasOtherPage = true;if(hasAt && (mAtPosition < firstVisibleItem)){//有未读@消息且不在当前页面rl_at_notify.setVisibility(View.VISIBLE);}}}

好了,群成员@提醒实现过程已经分析完毕,希望对大家有所帮助。至于消息列表的“ 有人@我”实现比较简单,这里就不做分析。如果大家感兴趣可以动手写代码实践下,或者到我的博客下载demo可作参看。

群成员@提醒实现过程相关推荐

  1. 10行代码制作群聊提醒小助手,再也不怕漏掉消息了

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 胸中有誓深于海,肯使神州竟陆沉? ...

  2. Raft 集群成员变更、日志压缩、客户端交互

    Raft 集群成员变更.日志压缩.客户端交互 集群成员变更 在集群服务器发生变化时,不能一次性的把所有的服务器配置信息从老的替换为新的,因为,每台服务器的替换进度是不一样的,可能会导致出现双主的情况, ...

  3. 如何用python写个人专属群聊提醒小助手?

    前言 大家还记得教会父母玩微信是什么时候吗?父母学会后,我们的生活就发生了「质」的变化,父母也许会吐槽你的微信头像不好,要你换一个头像. 最近 pk哥 又被母后大人吐槽了,原因是亲戚微信群里某个亲戚生 ...

  4. python代码提示太弱了_10行Python代码制作群聊提醒小助手,再也不怕漏掉消息了...

    前言 大家还记得教会父母玩微信是什么时候吗?父母学会后,我们的生活就发生了「质」的变化,父母也许会 吐槽你的微信头像不好,要你换一个头像. 最近 pk哥 又被母后大人吐槽了,原因是亲戚微信群里某个亲戚 ...

  5. python小助手_如何用python写个人专属群聊提醒小助手?

    前言 大家还记得教会父母玩微信是什么时候吗?父母学会后,我们的生活就发生了「质」的变化,父母也许会吐槽你的微信头像不好,要你换一个头像. 最近 pk哥 又被母后大人吐槽了,原因是亲戚微信群里某个亲戚生 ...

  6. 精准营销、批量提取QQ群成员号码

    有时我们在做精准营销时,需要从社群里提取群成员的QQ号,群发邮件,常规的做法是手工一个个复制粘贴,这样的效率无疑是很低的,下面我来分享一个批量获取社群的QQ号方法. 需要具备以下工具: 1.大量精准Q ...

  7. python制作课程表提醒_10行Python代码制作群聊提醒小助手,再也不怕漏掉消息了...

    前言 大家还记得教会父母玩微信是什么时候吗?父母学会后,我们的生活就发生了「质」的变化,父母也许会吐槽你的微信头像不好,要你换一个头像. 最近 pk哥 又被母后大人吐槽了,原因是亲戚微信群里某个亲戚生 ...

  8. python 获取qq群成员信息_教你用python爬取自己加入的QQ群成员名单,它们竟然是这样的人...

    本次实验环境: 操作系统:Mac OS 开发语言:python 3.6 IDE:jupyter notebook(建议使用) 浏览器:Chrome(版本75.0.3770.100) 需要用到的库:se ...

  9. python爬取qq群成员_教你用python爬取自己加入的QQ群成员名单

    本次实验环境: 操作系统:Mac OS 开发语言:python 3.6 IDE:jupyter notebook(建议使用) 浏览器:Chrome(版本75.0.3770.100) 需要用到的库:se ...

最新文章

  1. java实现具有修饰的完美圣诞树
  2. 看eShopOnContainers学一个EventBus
  3. AUC 评价指标详解,准确率(ACC),敏感性(sensitivity),特异性(specificity)计算 Python3【TensorFlow2入门手册】
  4. nginx配置thinkphp5
  5. centos的mysql命令,Centos系统mysql相关命令
  6. 【AI视野·今日Robot 机器人论文速览 第十五期】Fri, 25 Jun 2021
  7. 解析云原生2.0架构设计的8大关键趋势
  8. mysql事务隔离级别详解_高性能MySQL-详解事务与隔离级别
  9. matplotlib 28原则
  10. 一个发人深省的经典理财故事
  11. CVPR 2018:阿里提出新零样本学习方法,有效解决偏置问题
  12. Python 绘图字体控制 + 文字在图片中的位置调整
  13. websocket报错:java.io.EOFException: null
  14. mysql字段命名_数据库表及字段命名规范
  15. 单号自动识别查询 支持一键复制导出
  16. 【3D建模制作技巧分享】Maya如何给模型上色与渲染
  17. FA(萤火虫算法)MATLAB源码详细中文注解
  18. Django账号登陆之退出登录(logout()方法介绍、logout()方法使用)
  19. 一款vista边栏Gadgets汉英翻译(翻译14种语言的边栏工具下载)
  20. Walle多渠道打包

热门文章

  1. Python:matplotlib绘制线条图
  2. 一眼看懂promise与async await的区别
  3. java wasm_Wasm介绍之2:指令集和栈
  4. adb连接夜神模拟器出现error: cannot connect to daemon无法连接到守护程序
  5. 墨者学院-二维码文件分析
  6. ILSVRC2012数据集(分类部分)简要介绍和初步处理
  7. Java - 保留小数点后两位
  8. 如何给redis设置密码
  9. 二十九、rsync+inotity实时监控同步工具
  10. Mysql中的共享锁和排他锁