最近在做聊天功能的时候,有一个需求是仿照微信做@好友的功能,本来以为挺简单,但是做到这块的时候,发现和想象的有点不一样,什么整块删除,块可编辑,总之,加个@的功能很简单,但是要做和微信的一样还是费了一些功夫,下面是一个demo仅供参考,防止遗忘
先上个效果图
就是这么个功能
1. 分析需求
输入@跳转到联系人界面,选中一个或者多个好友返回到当前界面
按退格键删除整块内容
块内的内容可编辑,编辑完了之后将不附带@功能,只是单纯的文字
2. 开始编码
既然是文本输入首先继承EditText自定义一个控件
public class MsgEditText extends AppCompatEditText { public MsgEditText(Context context) { super(context); } public MsgEditText(Context context, AttributeSet attrs) { super(context, attrs); } public MsgEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
到底从哪里开始入手呢,首先完成变成块的需求,
无意中看到这个项目https://github.com/g707175425/CloudEditText ,他是这么写的
private void generateOneSpan(Spannable spannableString, UnSpanText unSpanText) { //生成一个TextView View spanView = getSpanView(getContext(), unSpanText.showText.toString(), getMeasuredWidth()); //再将TextView转换为一个图片 BitmapDrawable bitmpaDrawable = (BitmapDrawable) UIUtils.convertViewToDrawable(spanView); bitmpaDrawable.setBounds(0, 0, bitmpaDrawable.getIntrinsicWidth(), bitmpaDrawable.getIntrinsicHeight()); //最后将这个图片放到Span里, MyImageSpan what = new MyImageSpan(bitmpaDrawable, unSpanText.showText.toString(),unSpanText.returnText); final int start = unSpanText.start; final int end = unSpanText.end; spannableString.setSpan(what, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //设置一个Span spannableString.setSpan(touchableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); }
看到这里我们就记得了一个关于SpanableString的用法,它可以设置图片,可以随意的设置文字的背景的前景,等等一系列比较酷炫的效果,而且只需要一个TextView,如果需要深入了解Span,可自行百度和Google,关于Span的进阶用法,于是就有了下面的实现
//这个是需要成块删除的内容 private class MyTextSpan extends MetricAffectingSpan { private String showText; private long userId; //userId是为了适应需求,如果不需要请自行去掉 public MyTextSpan(String showText, long userId) { this.showText = showText; this.userId = userId; } public String getShowText() { return showText; } public long getUserId() { return userId; } @Override public void updateMeasureState(TextPaint p) { } @Override public void updateDrawState(TextPaint tp) { } } //这个是非整块删除的内容,当然你如果想也是可以删除的 private class UnSpanText { int start; int end; String returnText; UnSpanText(int start, int end, String returnText) { this.start = start; this.end = end; this.returnText = returnText; } }
刚开始我是这么写的
//外部调用一个增加Span的方法 public void addSpan(String showText, String returnText, long userId) { getText().append(showText); SpannableString spannableString = new SpannableString(getText()); makeSpan(spannableString, new UnSpanText(spannableString.length() - showText.length(), spannableString.length(), showText, returnText), userId); setText(spannableString); setSelection(spannableString.length()); } //生成一个需要整体删除的Span private void makeSpan(Spannable sps, UnSpanText unSpanText, long userId) { MyTextSpan what = new MyTextSpan(unSpanText.returnText, userId); int start = unSpanText.start; int end = unSpanText.end; sps.setSpan(what, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); }
写到现在这个整块添加已经做好了,下面开始做整块删除,刚开始的时候我是模仿上面的CloudEditText写的,但我发现好像会用各种问题,于是想了一种方法
@Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); //向前删除一个字符,@后的内容必须大于一个字符,可以在后面加一个空格 if (lengthBefore == 1 && lengthAfter == 0) { MyTextSpan[] spans = getText().getSpans(0, getText().length(), MyTextSpan.class); for (MyTextSpan myImageSpan : spans) { if (getText().getSpanEnd(myImageSpan) == start && !text.toString().endsWith(myImageSpan.getShowText())) { getText().delete(getText().getSpanStart(myImageSpan), getText().getSpanEnd(myImageSpan)); break; } } } }
上面的意思就是,如果你在EditText中执行删除一个字符的时候,判断前面一个是否是一个Span,如果是自定义的Span就把Span一同删除,关于这个,我可是测试可各种操作才定为这样的
最后是获取需要@的人员名单
//获取用户Id列表,这只是个参考,可根据需求修改 public String getUserIdString() { MyTextSpan[] spans = getText().getSpans(0, getText().length(), MyTextSpan.class); StringBuilder builder = new StringBuilder(); for (MyTextSpan myTextSpan : spans) { String realText = getText().toString().substring(getText().getSpanStart(myTextSpan), getText().getSpanEnd(myTextSpan)); String showText = myTextSpan.getShowText(); if (realText.equals(showText)) { builder.append(myTextSpan.getUserId()).append(","); } } if (!TextUtils.isEmpty(builder.toString())) { builder.deleteCharAt(builder.length() - 1); } return builder.toString(); }
最后我就大方的放个地址你们自己看吧
https://github.com/ddssingsong/AtFriend
总结
以上所述是小编给大家介绍的Android仿微信@好友功能 输入@跳转、删除整块,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
本文向大家介绍Android仿微信语音聊天功能,包括了Android仿微信语音聊天功能的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android仿微信语音聊天功能代码。分享给大家供大家参考。具体如下: 项目效果如下: 具体代码如下: AudioManager.java AudioRecorderButton.java DialogManager.java MainActivity.ja
本文向大家介绍Android仿微信朋友圈点击加号添加图片功能,包括了Android仿微信朋友圈点击加号添加图片功能的使用技巧和注意事项,需要的朋友参考一下 本文为大家分享了类似微信朋友圈,点击+号图片,可以加图片功能,供大家参考,具体内容如下 xml: NinePhotoView.java Measure 我们的子View三个一排,而且都是正方形,所以我们上面通过循环很好去得到所有子View的
本文向大家介绍Android仿微信、QQ附近好友雷达扫描效果,包括了Android仿微信、QQ附近好友雷达扫描效果的使用技巧和注意事项,需要的朋友参考一下 1.概述 最近一直到在带实习生,因为人比较多,所以很长一段时间没有更新博客了,今天更新一篇雷达扫描附近好友效果,以后尽量每周更新一篇,先看一下效果: 2.实现 1、效果分析 效果分为两个部分,一个是上半部分的自定义RadarView,还有
本文向大家介绍python轻松查到删除自己的微信好友,包括了python轻松查到删除自己的微信好友的使用技巧和注意事项,需要的朋友参考一下 前言 相信各位一定有收到过这样的群发短信,据说还被归类为玩转微信的五大技巧之一╮(╯▽╰)╭但,其实,只要跑一下脚本,就轻松找出删除自己的好友(轻松摔碎玻璃心,逃 原理 新建群组,如果加不进来就是被删好友了(不要在群组里讲话,别人是看不见的)。 用的是微信网页
本文向大家介绍Android自定义TextView仿微信朋友圈文字展开全文功能,包括了Android自定义TextView仿微信朋友圈文字展开全文功能的使用技巧和注意事项,需要的朋友参考一下 Android自定义TextView仿微信朋友圈文字信息,展开全文功能 代码及注释如下: 首先写一个xml文件 showmore.xml: 接下来就可以引用了,与普通的控件一样 activity_test.x
本文向大家介绍Android仿微信/支付宝密码输入框,包括了Android仿微信/支付宝密码输入框的使用技巧和注意事项,需要的朋友参考一下 在用到支付类app时,都有一个简密的输入框。。开始实现的时候思路有点问题,后来到github上搜了下,找到了一个开源的库看起来相当的牛逼,,来个地址先: https://github.com/Jungerr/GridPasswordView 效果图: 这个开源