IM中@联系人的实现

342 阅读2分钟
原文链接: xiaozhuanlan.com

相信大家在使用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 {

            //如果是回退,则判断当前文本最后是否以@结尾,如果是则一并删除