android 仿QQ,微信群组里的@功能,支持@多人,并能一键删除,能获取上传对应的id(修改版)

首先注明该文章是借签别人的博客,原文博文地址点击打开链接


android 仿QQ,微信群组里的@功能,支持@多人,并能一键删除,能获取上传对应的id

这个需求来源:本人做集成环信聊天时,项目需要@功能,但是环信并没有提供@功能。环信@功能地址点击打开链接


输入@符号之后进入好友列表
点击某个人,返回这个人的信息,并以@xxx的格式显示在 EditText 中
@部分需要变色
删除的时候需要把“@xxx”整体直接删除
基于以上几点要求,我有个想法:
通过InputFilter判断用户输入,当有“@”符号输入时,跳转到好友列表页,返回用户信息之后,把文字转换成bitmap,用SpannableString 做实现后面的功能 


UXchatActivity

package ucux.app.activitys;

import android.os.Bundle;
import android.text.Spanned;

import ucux.app.R;

public class UXchatActivity extends BaseActivity implements OnClickListener {
    public static final int RESULT_CODE_SEND_MEMBER = 32;
    private EditText mEditTextContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mEditTextContent = (EditText) findViewById(R.id.et_sendmessage);
        mEditTextContent.setFilters(new InputFilter[]{new MyInputFilter()});
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == RESULT_CODE_SEND_MEMBER) {// @群成员
            UxChatUtils.sendMember(this, data, cidNameMap, mEditTextContent);
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_send:// 点击发送按钮(发文字和表情)
                mChatManager.sendText(s, mPMSessionResult.getPMSID(), UxChatUtils.getAtMemberList(mEditTextContent, cidNameMap));
                cidNameMap.clear();// 传完之后清空一下@的列表
                break;
        }
    }

    // @群组成员

    /**
     * 存储@的cid、name对
     */
    private Map<String, String> cidNameMap = new HashMap<>();

    /**
     * 识别输入框的是不是@符号
     */
    private class MyInputFilter implements InputFilter {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source.toString().equalsIgnoreCase("@") || source.toString().equalsIgnoreCase("@")) {
                if (currentChatType() == 2)// 群聊,才能@群组成员
                    goAt();
            }
            return source;
        }
    }

    private void goAt() {
        Intent intent = new Intent(UXchatActivity.this, GroupNumberListActivity.class);
        intent.putExtra("PMSID", mPMSessionResult.getPMSID());
        intent.putExtra("SEMDMEMBER", true);
        startActivityForResult(intent, RESULT_CODE_SEND_MEMBER);
    }

    private View.OnLongClickListener longClickListener = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View view) {
            try {
                switch (view.getId()) {
                    case R.id.iv_userhead:
                        EMPM empm = (EMPM) view.getTag(R.id.tag_send_member);
                        Forward lForward = MessageTranslateUtil.TranformForward(empm);

                        if ((currentChatType() == 2) && (lForward != null) && (empm.direct()) && (!UxChatUtils.isExistInMemberList(cidNameMap, lForward.getUID()))) {// 群聊
                            Intent intent = new Intent();
                            intent.putExtra(GroupNumberListActivity.KEY_UID, lForward.getUID() + " ");
                            intent.putExtra(GroupNumberListActivity.KEY_NAME, "@" + lForward.getName() + " ");
                            UxChatUtils.sendMember(UXchatActivity.this, intent, cidNameMap, mEditTextContent);
                        } else {
                            return false;
                        }
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return true;
        }
    };

}

UxChatUtils

/**
 * 聊天工具类(新增的)
 * Created by Administrator on 2017/3/2.
 */

public class UxChatUtils {

    //上传需要的uid值
    public static ArrayList<String> getAtMemberList(EditText mEditText, Map<String, String> cidNameMap) {
        ArrayList<String> atMembers = new ArrayList<>();

        ArrayList<String> list = new ArrayList<>();
        String content = String.valueOf(mEditText.getText().toString().trim());
        String[] sss = content.split(" ");
        for (String s : sss) {
            list.add(s);
        }
        for (int i = 0; i < list.size(); i++) {
            String keys = "";
            Iterator it = cidNameMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();
                Object obj = entry.getValue();
                if (obj != null && list.get(i).contains((String) obj)) {
                    keys = (String) entry.getKey();
                }
            }

            if (!TextUtils.isEmpty(keys))
                atMembers.add(keys);
        }
        return atMembers;
    }

    /**
     * 返回的所有的用户名,用于识别输入框中的所有要@的人
     * 如果用户删除过,会出现不匹配的情况,需要在for循环中做处理
     */
    private static String nameStr;
    /**
     * 上一次返回的用户名,用于把要@的用户名拼接到输入框中
     */
    private static String lastNameStr;

    public static void sendMember(Context context, Intent data, Map<String, String> cidNameMap, EditText mEditText) {
        String tmpCidStr = data.getStringExtra(GroupNumberListActivity.KEY_UID);
        String tmpNameStr = data.getStringExtra(GroupNumberListActivity.KEY_NAME);

        String[] tmpCids = tmpCidStr.split(" ");
        String[] tmpNames = tmpNameStr.split(" ");

        if (tmpCids.length > 0) {
            for (int i = 0; i < tmpCids.length; i++) {
                if (tmpNames.length > i) {
                    cidNameMap.put(tmpCids[i], tmpNames[i]);
                }
            }
        }
        // 这里的lists集合,是把输入框里已经有的人名放进集合中,再在一个一个的比较选择返回的人名,如果是一样的就return,并且不再显示到输入框
        ArrayList<String> lists = new ArrayList<String>();
        String content = String.valueOf(mEditText.getText().toString().trim());
        String[] ssss = content.split(" ");
        Collections.addAll(lists, ssss);
        for (int i = 0; i < lists.size(); i++) {
            if (lists.get(i).equals(tmpNameStr.trim())) {
                int curIndex = mEditText.getSelectionStart();
                if (curIndex >= 1) {
                    mEditText.getText().replace(curIndex - 1, curIndex, "");
                }
                return;
            }
        }
        //返回的人名,自增加
        if (nameStr == null) {
            nameStr = tmpNameStr;
        } else {
            nameStr = nameStr + tmpNameStr;

        }
        lastNameStr = tmpNameStr;
        // 获取光标当前位置
        int curIndex = mEditText.getSelectionStart();
        // 把要@的人插入光标所在位置
        mEditText.getText().insert(curIndex, lastNameStr);
        // 通过输入@符号进入好友列表并返回@的人,要删除之前输入的@
        if (curIndex >= 1) {
            mEditText.getText().replace(curIndex - 1, curIndex, "");
        }
        setAtImageSpan(context, mEditText, nameStr);
    }

    private static void setAtImageSpan(final Context context, EditText mEditText, String nameStr) {
        String content = String.valueOf(mEditText.getText());
        if (content.endsWith("@") || content.endsWith("@")) {
            content = content.substring(0, content.length() - 1);
        }
        String tmp = content;
        SpannableString ss = new SpannableString(tmp);
        if (nameStr != null) {
            String[] names = nameStr.split(" ");
            if (names.length > 0) {
                for (String name : names) {
                    if (name != null && name.trim().length() > 0) {
                        //把获取到的名字转为bitmap对象
                        final Bitmap bmp = getNameBitmap(context, name);
                        // 这里会出现删除过的用户,需要做判断,过滤掉
                        if (tmp.contains(name) && (tmp.indexOf(name) + name.length()) <= tmp.length()) {
                            // 把取到的要@的人名,用DynamicDrawableSpan代替
                            ss.setSpan(new DynamicDrawableSpan(DynamicDrawableSpan.ALIGN_BASELINE) {
                                           @Override
                                           public Drawable getDrawable() {
                                               BitmapDrawable drawable = new BitmapDrawable(context.getResources(), bmp);
                                               drawable.setBounds(0, 0, bmp.getWidth(), bmp.getHeight());
                                               return drawable;
                                           }
                                       }, tmp.indexOf(name),
                                    tmp.indexOf(name) + name.length(),
                                    SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                    }
                }
            }
        }
        mEditText.setTextKeepState(ss);
    }

    /**
     * 把返回的人名,转换成bitmap
     *
     * @param name 人名
     * @return 图片
     */
    private static Bitmap getNameBitmap(Context context, String name) {
        /* 把@相关的字符串转换成bitmap 然后使用DynamicDrawableSpan加入输入框中 */
        name = "" + name;
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        // 设置字体画笔的颜色
        // paint.setColor(context.getResources().getColor(R.color.transculent_black));
        paint.setTextSize(30);
        Rect rect = new Rect();
        paint.getTextBounds(name, 0, name.length(), rect);
        // 获取字符串在屏幕上的长度
        int width = (int) (paint.measureText(name));
        final Bitmap bmp = Bitmap.createBitmap(width + 5, rect.height() + 5, Bitmap.Config.ARGB_8888);// 长宽+5,可调
        Canvas canvas = new Canvas(bmp);
        canvas.drawColor(context.getResources().getColor(R.color.color_primary));
        canvas.drawText(name, rect.left, rect.height() - rect.bottom, paint);
        return bmp;
    }

    /**
     * 群组成员列表中是否已经有相应的uid
     *
     * @param cidNameMap cidNameMap
     * @param uid        uid
     * @return true-->有
     */
    public static boolean isExistInMemberList(Map<String, String> cidNameMap, long uid) {
        try {
            for (Object o : cidNameMap.entrySet()) {
                Map.Entry entry = (Map.Entry) o;
                Object key = entry.getKey();
                if (Long.parseLong(key.toString()) == uid)
                    return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}


GroupNumberListActivity

if (getIntent().getBooleanExtra("SEMDMEMBER", false)){
						// 传回群成员相关信息,并且关闭页面
						Intent intent = new Intent();
						intent.putExtra(KEY_UID, String.valueOf(mPMSMemberList.get(position).getUID()) + " ");
						intent.putExtra(KEY_NAME, "@" + mPMSMemberList.get(position).getUName() + " ");
						setResult(RESULT_OK, intent);
						finish();
					}

在adapter中的头像设置长按监听,长按头像就@那个成员

                holder.iv_avatar.setTag(R.id.tag_send_member, message);
                holder.iv_avatar.setOnLongClickListener(longClickListener);



猜你喜欢

转载自blog.csdn.net/u012482178/article/details/60957085