高仿SinaWeibo新浪微博发布页面话题效果
来源:互联网 发布:网页页面设计软件 编辑:程序博客网 时间:2024/04/19 14:13
最近做了一个仿新浪微博话题效果的功能,网上搜索了几个效果,都存在一定问题,最终借鉴别人的思路,完成这一套效果.
首先,我们拆分逻辑以及开发顺序.
1,实现话题变色效果
2,实现插入话题效果
3,实现话题选中删除效果
4,实现点击话题,光标在话题之后
下面我们就一步一步实现效果.
一,实现话题变色
实现逻辑主要是通过EditText
的addTextChangedListener()
来进行监听文本变动,通过正则表达式来匹配出文本中的话题.
利用正则表达式获取全部话题:
//正则表达式,一定要和服务器以及 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
直接对文本进行操作:
@Overridepublic 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,去除之前设置的colorSpan Editable editable = mEditText.getText(); for (int i = 0; i < mColorSpans.size(); i++) { editable.removeSpan(mColorSpans.get(i)); } mColorSpans.clear(); //为editable,中的话题加入colorSpan int 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()
两个回调时,文本是已经删除之后的文本,并能有效的达到我们要实现的目的,那么有没有是文本改变之前就能截取到按键的方法呢?
其实我们可以通过监听EditText
的setOnKeyListener()
方法来监听按键(onKey->beforeTextChanged->onTextChanged->afterTextChanged->onKeyDown->onKeyUp
):
@Override public 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新浪微博发布页面话题效果
- 仿新浪微博的插入#话题#
- 高仿新浪微博
- Android 自定义view-仿新浪微博#话题#插入EditText
- 新浪微博发布效果
- 模仿新浪微博@某人/#话题的效果
- 模仿新浪微博@某人/#话题的效果
- 仿新浪微博-发布新微博
- 仿新浪微博“返回顶部”效果
- Android仿新浪微博ListView效果
- 新浪微博话题墙
- 公开课发布《微博话题高性能降级设计》
- 仿新浪微博消息发布功能js代码
- js仿新浪微博消息发布功能
- Android 高仿新浪微博底部导航栏,实现双击首页Tab,页面的ListView滚动、刷新
- jQuery 写的仿新浪微博 向下滚动效果
- jQuery 写的仿新浪微博 向下滚动效果
- 仿新浪微博登陆邮箱提示效果!
- Grep用法
- hdu 3593
- C++ class与内存
- LeetCode(141)(142) Linked List Cycle I II
- Linux - 有效群组(effective group)与初始群组(initial group),groups,newgrp
- 高仿SinaWeibo新浪微博发布页面话题效果
- 分享在MVC3.0中使用jQuery DataTable 插件
- FileOutputStream/FileInputStream--FileWriter/FileReader
- 相似图片搜索
- 提示磁盘被写保护怎么办?
- Python中re(正则表达式)模块详解
- 项目开发中用到的一些MySQL语句
- hdu 4547 lca-tarjan离线算法
- 属性名前两个字母要么都是大写的要么都是小写的(当然数字与_、$算小写)