欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android仿微信@好友功能 输入@跳转、删除整块

程序员文章站 2023-12-09 20:52:27
最近在做聊天功能的时候,有一个需求是仿照微信做@好友的功能,本来以为挺简单,但是做到这块的时候,发现和想象的有点不一样,什么整块删除,块可编辑,总之,加个@的功能很简单,但...

最近在做聊天功能的时候,有一个需求是仿照微信做@好友的功能,本来以为挺简单,但是做到这块的时候,发现和想象的有点不一样,什么整块删除,块可编辑,总之,加个@的功能很简单,但是要做和微信的一样还是费了一些功夫,下面是一个demo仅供参考,防止遗忘

先上个效果图

Android仿微信@好友功能 输入@跳转、删除整块

就是这么个功能

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仿微信@好友功能 输入@跳转、删除整块,希望对大家有所帮助