最近做了一个仿新浪微博话题效果的功能,网上搜索了几个效果,都存在一定问题,最终借鉴别人的思路,完成这一套效果.

首先,我们拆分逻辑以及开发顺序.

1,实现话题变色效果
2,实现插入话题效果
3,实现话题选中删除效果
4,实现点击话题,光标在话题之后

下面我们就一步一步实现效果.


一,实现话题变色

实现逻辑主要是通过EditTextaddTextChangedListener()来进行监听文本变动,通过正则表达式来匹配出文本中的话题.

利用正则表达式获取全部话题:
//正则表达式,一定要和服务器以及 iOS 端统一
private static final String topicRegex = "#([^#]+?)#";
public static ArrayList<String> findTopic(String s) {Pattern p = Pattern.compile(topicRegex);Matcher m = p.matcher(s);ArrayList<String> list = new ArrayList<>();while (m.find()) {list.add(m.group());}return list;
}
通过正则表达式匹配出的话题集合,遍历出每个话题的 startIndex 位置(后来发现Matcher方法是有获取 index 的方法),并且通过EditText.getText()方法获取的Editable直接对文本进行操作:
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {Log.i("MainActivity", "onTextChanged");if (TextUtils.isEmpty(s)) return;//1,查找话题String content = s.toString();mTopicList.clear();mTopicList.addAll(findTopic(s.toString()));//2,为查找出的变色//首先要为editable,去除之前设置的colorSpanEditable editable = mEditText.getText();for (int i = 0; i < mColorSpans.size(); i++) {editable.removeSpan(mColorSpans.get(i));}mColorSpans.clear();//为editable,中的话题加入colorSpanint findPos = 0;int size = mTopicList.size();for (int i = 0; i < size; i++) {//便利话题String topic = mTopicList.get(i);findPos = content.indexOf(topic, findPos);if (findPos != -1) {ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.BLUE);editable.setSpan(colorSpan, findPos, findPos = findPos + topic.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);mColorSpans.add(colorSpan);}}
}

二,实现插入话题效果

新浪微博的插入话题效果,是开启一个新的页面,点击一个话题后,插入光标所在的位置.这里我用一个按钮模仿了这个动作.要注意的是,要记录插入之前光标的位置,并且在插入话题后,把光标放置在话题之后:

if (v.getId() == R.id.button) {//插入话题int selectionStart = mEditText.getSelectionStart();//下面这些操作也可以直接替换为操作 EditText 的Editable实现,下面的代码 review 后看起来由点蠢,直接调用 insert 方法比较巧妙String content = mEditText.getText().toString();String firstStr = content.substring(0, selectionStart);String secondStr = content.substring(selectionStart, content.length());String insertTopic = "#这是一个插入的话题#";mEditText.setText(firstStr + insertTopic + secondStr);mEditText.setSelection(selectionStart + insertTopic.length());
}

三,实现话题选中删除效果

这里也是要时时判断光标所在的位置,当光标出现在话题之后,再次点击删除,就截获为选中话题效果,实现起来也是很简单的.

但是要注意的是,我们不能利用 activity 里面的onKeyDown()onKeyUp()两个回调,通过 log 发现文本变动和按键点击的回调顺序为beforeTextChanged->onTextChanged->afterTextChanged->onKeyDown->onKeyUp.

这也说明了如果通过 拦截onKeyDown()onKeyUp()两个回调时,文本是已经删除之后的文本,并能有效的达到我们要实现的目的,那么有没有是文本改变之前就能截取到按键的方法呢?

其实我们可以通过监听EditTextsetOnKeyListener()方法来监听按键(onKey->beforeTextChanged->onTextChanged->afterTextChanged->onKeyDown->onKeyUp):

@Overridepublic boolean onKey(View v, int keyCode, KeyEvent event) {Log.i("MainActivity", "onKey");if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN && mCheckBox2.isChecked()) {int selectionStart = mEditText.getSelectionStart();int selectionEnd = mEditText.getSelectionEnd();//如果光标起始和结束在同一位置,说明是选中效果,直接返回 false 交给系统执行删除动作if (selectionStart != selectionEnd) {return false;}Editable editable = mEditText.getText();String content = editable.toString();int lastPos = 0;int size = mTopicList.size();//遍历判断光标的位置for (int i = 0; i < size; i++) {String topic = mTopicList.get(i);lastPos = content.indexOf(topic, lastPos);if (lastPos != -1) {if (selectionStart != 0 && selectionStart >= lastPos && selectionStart <= (lastPos + topic.length())) {//选中话题mEditText.setSelection(lastPos, lastPos + topic.length());return true;}}lastPos += topic.length();}}return false;}

四,实现点击话题,光标在话题之后

逻辑处理就是监听EditText的点击事件,处理光标所在位置,如果在位置在话题内,立即放置在话题的后面,逻辑比较简单,直接上代码:

if (v.getId() == R.id.editText && mCheckBox1.isChecked()) {int selectionStart = mEditText.getSelectionStart();int lastPos = 0;int size = mTopicList.size();for (int i = 0; i < size; i++) {String topic = mTopicList.get(i);lastPos = mEditText.getText().toString().indexOf(topic, lastPos);if (lastPos != -1) {if (selectionStart >= lastPos && selectionStart <= (lastPos + topic.length())) {//在这position 区间就移动光标mEditText.setSelection(lastPos + topic.length());}}lastPos = lastPos + topic.length();}}

最终还是有点小遗憾没有完成.当拷贝一段已经变色的话题,再粘贴到文本后,无法删除掉拷贝进来文本的变色效果,尝试调用Editable.clearSpans()去除全部 span 也无法实现,并且这个方法会导致直接卡死.后来直接使用EditText.setText()控制文本,确实达到了效果,但是当输入法是类似 mx4默认输入法效果时(效果大概是,输入的拼音直接显示在 EditText 里面,点击被选汉字,替换掉拼音),会把输入的拼音放入到文本里,所以上面的代码,我一般是直接操作 Editable.

如果有更好的方法或者修复了上面的小遗憾,请留言指教.

Demo 地址:https://github.com/KennethYo/SinaTopic

转载请注明出处:http://www.kennethyo.me

高仿SinaWeibo新浪微博发布页面话题效果相关推荐

  1. android高仿微信聊天页面,Android 高仿微信语音聊天页面高斯模糊(毛玻璃效果)

    目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果. 先看下效果图: 仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高 ...

  2. 高仿小红书引导页实现效果

    代码地址如下: http://www.demodashi.com/demo/11739.html 演示效果 !暂时先借用小红帽图片素材的app效果来演示 [暂时先借用小红帽图片素材的app效果来演示] ...

  3. 高仿凤凰新闻的加载效果

    高仿凤凰新闻的加载效果 介绍: 模仿凤凰新闻的加载.两个圆球旋转缩放.使用Animator属性动画. 本例子主要来自:http://www.itlanbao.com/code/20151208/100 ...

  4. 自定义view高仿稀土掘金loading闪动字体效果

    注:该文章同步发布到稀土掘金:链接 前言 由于通勤时间较长,在路上总会有时间刷刷文章.稀土掘金就是常用的一个app(这里非广告,哈哈哈).前段时间,发表了篇文章:# 使用CollapsingToolb ...

  5. 高仿探探首页波纹扫描效果

    闲着也是闲着的时候,打开探探划一划,挺多男同胞会这样吧.这不,我也是这样,看到首页探探的效果还是挺吸引人的.之前仿照实现了一个,效果还差一点,正好今天没事完善一下,写下来,希望看到能有收获. 实现的效 ...

  6. Andoid - 开发实例(8):高仿Fuubo新浪微博客户端

    能完成这个实例,感谢Github上的开源的UI组件,本项目所用到的开源组件: UI组件:ActionBarSherlock,SlidingMenu,PullToRefresh 其他框架:Afinal ...

  7. 网红 AI 高仿坎爷发布说唱情歌,歌迷:堪比真人原声

    来源 | Hyper超神经 头图 | 下载于视觉中国 近日,一个基于 Tacotron2 和 Transformer 实现文字转声音的 AI 应用--Uberduck.AI 破圈了,不少 TikTok ...

  8. 高仿微信对话列表滑动删除效果

    前言 用过微信的都知道.微信对话列表滑动删除效果是非常不错的,这个效果我们也能够有. 思路事实上非常easy,弄个ListView.然后里面的每一个item做成一个能够滑动的自己定义控件就可以.由于L ...

  9. 可用!三行代码高仿高德地图三段式抽屉效果

    三行代码 废话不在前面说,直接上代码! 将 XML 根布局设置为 CoordinatorLayout <android.support.design.widget.CoordinatorLayo ...

最新文章

  1. python编程可视化小程序_人人都可以写的可视化Python小程序第二篇:旋转的烟花...
  2. c#扩展方法奇思妙用高级篇四:对扩展进行分组管理
  3. php设置cookie 域名,php如何设置cookie对整个域名有效?
  4. 关于ssd-tensorlow如何训练自己的数据集合
  5. facebook快捷登录 pc_华为发布首款商用台式机,商用PC布局更进一步
  6. c语言从指定窗口截图,c++ 屏幕截图指定窗口句柄后台截图返回位图句柄
  7. html5 aria,html - What is HTML5 ARIA? - Stack Overflow
  8. iOS - 数组字典模型根据模型属性key排序
  9. JavaScript模拟终端输出
  10. 自动驾驶 6-1: 横向车辆控制介绍 Lesson 1: Introduction to Lateral Vehicle Control
  11. 一文读完C语言基础语法
  12. QT调用OpenCV
  13. 常见物理性能测试仪器设备档案
  14. 微型计算机接口技术论文,微机原理与接口技术课程论文
  15. Arduino超声波模块原理
  16. SpringBoot+Vue实现前后端分离的财务管理系统
  17. 考研高数 专题7:方程根的存在性及个数(零点定理-罗尔定理;单调性-罗尔定理推论)
  18. 虚拟化高级应用、Win快捷键操作 、 Win+R快速调用
  19. 有哪些好用的抠图网站?这种方法超好用
  20. SpringCloud 网关 Gateway

热门文章

  1. react生命周期写法
  2. 一个友好的扫雷程序————C初学者都能会的简单扫雷(一)
  3. Cesium实现雷达扫描效果
  4. 使用Ceph作为OpenStack的统一存储解决方案
  5. 美团校招-2023.3.18.10点-第四题-商店-困难
  6. 勒索病毒场景模拟及原理
  7. 画各种思维导图的软件
  8. java后端接收前端传来的String数组
  9. Mybatis代码生成器Mybatis-Generator使用及配置详解
  10. 批量采集多个淘宝商品的洋淘买家秀图片并统一保存