EditText输入@的相关处理

  1. 项目中需求要求输入框中输入@时打开好友列表选择好友并有跳转操作
  2. 实现思路:使用Span处理富文本,自定义TextWatcher处理输入监听
  3. 对EditText添加监听器addTextChangedListener(superTextWatcher);
  4. 对EditText设置setMovementMethod(LinkMovementMethod.getInstance());
  5. 处理Activity回调superTextWatcher.onActivityResult(et_huifu, requestCode, data);
/**
 * @ 对象
 * Created by swing on 2019/7/2 0002.
 */
public class AUser {
    public AUser() {
    }

    public AUser(String callNickName, String callPid) {
        this.callNickName = callNickName;
        this.callPid = callPid;
    }

    /**
     * callNickName : string
     * callPid : string
     */

    private String callNickName;
    private String callPid;

    public String getCallNickName() {
        return callNickName;
    }

    public void setCallNickName(String callNickName) {
        this.callNickName = callNickName;
    }

    public String getCallPid() {
        return callPid;
    }

    public void setCallPid(String callPid) {
        this.callPid = callPid;
    }
}
/**
 * EditText的@处理 未处理剪裁复制时的逻辑
 * Created by swing on 2019/6/26 0026.
 */
public class SuperTextWatcher implements android.text.TextWatcher {
    public static final String ISEDITTEXTINPUTA = "isEditTextInputA";
    public static final String NAME = "name";
    public static final String ID = "id";
    private static String a = "@";
    private static String startDevider = "" + a;
    private static String endDevider = " ";
    private Activity activity;
    private EditText editText;
    private int requestCode;
    private SpannableString spnableInfo;
    private List<AUser> aUsers;

    public SuperTextWatcher(Activity activity, EditText editText, List<AUser> aUsers) {
        this.activity = activity;
        this.editText = editText;
        this.aUsers = aUsers;
    }

    /**
     * @param start: 字符串中即将发生修改的位置。
     * @param count: 字符串中即将被修改的文字的长度。如果是新增的话则为0。
     * @param after: 被修改的文字修改之后的长度。如果是删除的话则为0。
     */
    @Override
    public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
        if (spnableInfo == null) {
            spnableInfo = getASpan(activity, new SpannableString(charSequence), aUsers);
        }
        //如果光标在用户名中间输入时将光标移动至结尾
        String previousString = charSequence.toString().substring(0, start);
        String nextString = charSequence.toString().substring(start, charSequence.length());
        int previousStartIndex = previousString.lastIndexOf(startDevider);
        int previousEndIndex = previousString.lastIndexOf(endDevider);
        int nextStartIndex = nextString.indexOf(startDevider);
        int nextEndIndex = nextString.indexOf(endDevider);
        if (editText != null
                && previousStartIndex != -1
                && previousStartIndex > previousEndIndex
                && nextEndIndex != -1
                && (nextStartIndex == -1 || nextEndIndex < nextStartIndex)) {
            editText.setText(spnableInfo);
            editText.setSelection(spnableInfo.length());
        }
        //如果删除字符时是用户名则删除用户名(包含开始结束符)
        if (count > 0 && after == 0) {
            String subString = charSequence.toString().substring(0, start);
            if (subString.contains(startDevider)) {
                int lastStart = subString.lastIndexOf(startDevider);
                int lastEnd = subString.lastIndexOf(endDevider);
                if (charSequence.toString().lastIndexOf(endDevider) == start - endDevider.length() + 1
                        && (lastEnd == -1 || lastEnd < lastStart)) {
                    if (editText != null && spnableInfo != null) {
                        //暂时只能删除最后一个,随机删除待处理
                        editText.setText(spnableInfo.subSequence(0, lastStart));
                        editText.setSelection(editText.getText().toString().length());
                        if (!aUsers.isEmpty()) {
                            aUsers.remove(aUsers.size() - 1);
                        }
                    }
                    onInputTextAdelete(subString.lastIndexOf(startDevider));
                }
            }
        }
    }

    /**
     * @param start:  有变动的字符串的序号
     * @param before: 被改变的字符串长度,如果是新增则为0。
     * @param count:  添加的字符串长度,如果是删除则为0。
     */
    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
        if (count == 1 && before == 0) {
            String subString = charSequence.toString().substring(start, start + count);
            if (subString.contains(a)) {
                onInputTextA(start);
            }
        }
    }

    @Override
    public void afterTextChanged(Editable editable) {
    }

    /**
     * @param start 输入@的位置
     */
    public void onInputTextA(int start) {
        toActivity(activity, "/myself/MyAttentionActivity", 1100);
    }

    /**
     * @param end 删除@的位置
     */
    public void onInputTextAdelete(int end) {
    }

    /**
     * 输入@后跳转目标
     *
     * @param activity 源
     * @param url      目标
     */
    public void toActivity(Activity activity, String url, int requestCode) {
        this.requestCode = requestCode;
        if (this.activity == null)
            this.activity = activity;
        ARouter.getInstance()
                .build(url)
                .withBoolean(ISEDITTEXTINPUTA, true)
                .withTransition(ActivityHelper.getNextActivityAnimShow(), ActivityHelper.getCurrentActivityAnimShow())
                .navigation(activity, requestCode);
    }

    /**
     * 回退响应结果
     */
    public void onActivityResult(int requestCode, @Nullable Intent data) {
        if (this.requestCode == requestCode) {
            onAttentionActivityResult(data);
        } else if (requestCode == 800) {
            if (editText != null)
                editText.setSelection(editText.getText().toString().length());
        }
    }

    /**
     * 关注人列表页回退响应结果
     */
    private void onAttentionActivityResult(@Nullable Intent data) {
        String name = "";
        String id = "";
        if (data.hasExtra(NAME))
            name = data.getStringExtra(NAME);
        if (data.hasExtra(ID))
            id = data.getStringExtra(ID);
        String content = editText.getText().toString();
        for (AUser aUser : aUsers) {
            if (aUser.getCallPid().equals(id)) {
                if (content.endsWith(a)) {
                    content = content.substring(0, content.length() - 1);
                    spnableInfo = new SpannableString(content);
                }
                SpannableString nameSpannableString = getASpan(activity, spnableInfo, aUsers);
                editText.setText(nameSpannableString);
                editText.setMovementMethod(LinkMovementMethod.getInstance());
                editText.setSelection(nameSpannableString.length());
                return;
            }
        }
        aUsers.add(new AUser(name, id));
        SpannableString nameSpannableString = getSpan(content, name);
        editText.setText(nameSpannableString);
        editText.setMovementMethod(LinkMovementMethod.getInstance());
        editText.setSelection(nameSpannableString.length());
    }

    private SpannableString getSpan(String content, String name) {
        if (content.endsWith(a)) {
            content = content.substring(0, content.length() - 1);
        }
        String nameA = startDevider + name + endDevider;
        content = content + nameA;
        spnableInfo = new SpannableString(content);
        getASpan(activity, spnableInfo, aUsers);
        return spnableInfo;
    }

    /**
     * 跳转他人个人页面
     *
     * @param activity 源
     * @param url      目标
     */
    private static void toOtherPeopleActivity(Activity activity, String url, String id, int requestCode) {
        ARouter.getInstance().build(url)
                .withString(ID, id)
                .navigation(activity, requestCode);
    }

    /**
     * 对字符串添加@特效
     *
     * @param spnableInfo 原始文本
     * @param aUsers      人员列表
     */
    public static SpannableString getASpan(Activity activity, SpannableString spnableInfo, @NonNull List<AUser> aUsers) {
        String content = spnableInfo.toString();
        if (content.endsWith(a))
            content = content.substring(0, content.lastIndexOf(a));
        int index = 0;
        int dividerStart = content.indexOf(startDevider);
        int dividerEnd = content.indexOf(endDevider);
        if (dividerStart == -1 || dividerEnd == -1) {
            spnableInfo.setSpan(null, index, spnableInfo.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            spnableInfo.setSpan(new ForegroundColorSpan(Color.parseColor("#FF333333")), index, spnableInfo.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            return spnableInfo;
        }
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            spnableInfo.setSpan(null, index, dividerStart, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            spnableInfo.setSpan(new ForegroundColorSpan(Color.parseColor("#FF333333")), index, dividerStart, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            spnableInfo.setSpan(null, dividerStart, dividerStart + startDevider.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            spnableInfo.setSpan(new ForegroundColorSpan(Color.parseColor("#FF2274D0")), dividerStart, dividerStart + startDevider.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            //aUsers的顺序必须是文本中@的顺序,可使用name判断增加匹配度
            spnableInfo.setSpan(new AClickableSpan(activity, aUsers.size() > i ? aUsers.get(i) : null), dividerStart + startDevider.length(), dividerEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            spnableInfo.setSpan(new ForegroundColorSpan(Color.parseColor("#FF2274D0")), dividerStart + startDevider.length(), dividerEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            spnableInfo.setSpan(null, dividerEnd, dividerEnd + endDevider.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            spnableInfo.setSpan(new ForegroundColorSpan(Color.parseColor("#FF2274D0")), dividerEnd, dividerEnd + endDevider.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            index = dividerEnd + endDevider.length();
            if (index >= spnableInfo.length()) {
                break;
            }
            content = spnableInfo.toString().substring(index);
            dividerStart = content.indexOf(startDevider);
            if (dividerStart == -1) {
                break;
            }
            dividerEnd = content.substring(dividerStart).indexOf(endDevider) + dividerStart;
            dividerStart = dividerStart + index;
            dividerEnd = dividerEnd + index;
        }
        return spnableInfo;
    }

    public List<AUser> getaUsers() {
        return aUsers;
    }

    public void setaUsers(List<AUser> aUsers) {
        this.aUsers = aUsers;
    }

    static class AClickableSpan extends ClickableSpan {
        private AUser aUser;
        private Activity activity;

        public AClickableSpan(Activity activity, AUser aUser) {
            this.aUser = aUser;
            this.activity = activity;
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            ds.setUnderlineText(false);
        }

        @Override
        public void onClick(View widget) {
            if (aUser != null && aUser.getCallPid() != null)
                toOtherPeopleActivity(activity, "/myself/OtherPeopleActivity", aUser.getCallPid(), 800);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/duoluo9/article/details/93872220