IM中@联系人的实现

相信大家在使用IM软件中的时候肯定会使用到@功能

这里实现其实需要考虑步骤
1.@弹出群员框的弹出
2.如何间隔@XX的对象
3.如何删除@功能
4.重复选择@人功能的筛选
5.@列表传输

首先,我们需要获取一个群员列表,建群的时候,进入聊天界面之后就需要获取一份群成员列表。
先探讨第一个问题,弹出@列表,在每次EditText触发onTextChanged胡时候调用下面的onAtTextChanged,弹出列表,然后选择后添加到@的列表中,
这里需要考虑同时出现多个@的情况
每个@的成员,需要有一个空格来间隔,微信也是这样处理的,
删除@的人员的时候需要通过检查空格检测到最近的一个是否是成员。
```
/**
* 最近一次at的索引
*/
private var mLastAtIndex = -1

/**
 * at输入变更回调
 * @param inputText 输入框
 * @param start 当前光标在的索引
 * @param before
 * @param count
 */
private fun onAtTextChanged(inputText: EditText, start: Int, before: Int, count: Int) {
    val add = count > before 
    ALog.d(TAG, "onAtTextChanged add: $add, mLastAtIndex: $mLastAtIndex")
    if (mLastAtIndex >= 0) {//表示当前在at中
        //表示在@前插入文本,这时候就不处理,不用过滤@列表,只是增删上一次a@的位置索引
        if (start <= mLastAtIndex) {
            if (add) {
                mLastAtIndex += count
            } else {
                //如果删除位置是当前的@位置,且之前原位置大于当前@位置,表示当前的@被删除了,取消@状态
                if (start + before > mLastAtIndex) {
                    showAtList(false)  //弹出@成员列表
                } else {
                    mLastAtIndex -= before  //设置上一个@的位置
                }
            }
        } else {
            //如果是在@后插入的文本,则作为搜索条件来查询@成员
            val search = inputText.text.substring(mLastAtIndex + 1)
            ALog.d(TAG, "onAtTextChanged search: $search")
            Observable.create(ObservableOnSubscribe<List<Recipient>> {
                try {
                    it.onNext(mAllAtList.filter {
                        it.address.serialize().contains(search) ||
                                it.profileName?.contains(search, true) == true ||
                                it.systemDisplayName?.contains(search, true) == true
                    })
                } finally {
                    it.onComplete()
                }
            }).subscribeOn(Schedulers.computation())
                    .observeOn(AndroidSchedulers.mainThread())
                    .compose(RxLifecycle.bind(this).toLifecycleTransformer())
                    .subscribe({
                        mChatAtAdapter.setAtList(it, search) //群成员中有搜索功能
                    }, {
                        ALog.e(TAG, "onAtTextChanged error", it)
                    })
        }
        //如果变回小于0,则不在显示@列表
        if (mLastAtIndex < 0) {
            showAtList(false)
        }

    } else {
        if (add) {
            //如果新输入的字符是@,则进入at状态,并
            val target = inputText.text.substring(start, start + count)
            if (target == GroupViewModel.CHAT_AT_CHAR) {
                mLastAtIndex = start
                showAtList(true)
            }
        } else {
            //如果是回退,则判断当前文本最后是否以@结尾,如果是则一并删除
top Created with Sketch.