Pārlūkot izejas kodu

增加聊天页面黑名单列表模块

Pq 2 mēneši atpakaļ
vecāks
revīzija
fe2cc55d72

+ 46 - 0
chatModule/src/main/java/com/cooleshow/chatmodule/adapter/BlackListAdapter.java

@@ -0,0 +1,46 @@
+package com.cooleshow.chatmodule.adapter;
+
+import android.view.View;
+import android.widget.ImageView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.utils.GlideUtils;
+import com.cooleshow.chatmodule.R;
+import com.cooleshow.chatmodule.bean.ContactListBean;
+import com.cooleshow.chatmodule.utils.helper.ChatGroupHelper;
+import com.tencent.imsdk.v2.V2TIMFriendInfo;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Author by pq, Date on 2022/5/7.
+ */
+public class BlackListAdapter extends BaseQuickAdapter<V2TIMFriendInfo, BaseViewHolder> {
+    public BlackListAdapter() {
+        super(R.layout.tc_item_black_list_layout);
+        addChildClickViewIds(R.id.iv_remove_black);
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, V2TIMFriendInfo bean) {
+        String avatar = null;
+        String name = "用户" + bean.getUserID();
+        if (bean.getUserProfile() != null) {
+            avatar = bean.getUserProfile().getFaceUrl();
+            name = bean.getUserProfile().getNickName();
+        }
+        holder.setText(R.id.tv_name, name);
+        ImageView iv_icon = holder.getView(R.id.iv_icon);
+
+        GlideUtils.INSTANCE.loadImage(getContext(), avatar, iv_icon, R.drawable.tc_icon_teacher_default_head);
+
+        boolean isTeacher = ChatGroupHelper.isTeacherById(bean.getUserID());
+        View iv_role_tag = holder.getView(R.id.iv_role_tag);
+        if (isTeacher) {
+            iv_role_tag.setVisibility(View.VISIBLE);
+        } else {
+            iv_role_tag.setVisibility(View.GONE);
+        }
+    }
+}

+ 26 - 0
chatModule/src/main/java/com/cooleshow/chatmodule/contract/BlackListFragmentContract.java

@@ -0,0 +1,26 @@
+package com.cooleshow.chatmodule.contract;
+
+import com.cooleshow.base.presenter.view.BaseView;
+import com.cooleshow.chatmodule.bean.ContactListBean;
+import com.tencent.imsdk.v2.V2TIMFriendInfo;
+
+import java.util.List;
+
+/**
+ * Author by pq, Date on 2022/4/20.
+ */
+public interface BlackListFragmentContract {
+
+    interface View extends BaseView {
+        void getBlackListSuccess(List<V2TIMFriendInfo> v2TIMFriendInfos);
+
+        void getBlackListError();
+
+        void operateSuccess();
+
+
+    }
+
+    interface Presenter {
+    }
+}

+ 77 - 0
chatModule/src/main/java/com/cooleshow/chatmodule/presenter/BlackListPresenter.java

@@ -0,0 +1,77 @@
+package com.cooleshow.chatmodule.presenter;
+
+import android.text.TextUtils;
+
+import com.cooleshow.base.common.BaseConstant;
+import com.cooleshow.base.presenter.BasePresenter;
+import com.cooleshow.base.rx.BaseObserver;
+import com.cooleshow.base.utils.LOG;
+import com.cooleshow.base.utils.RequestBodyUtil;
+import com.cooleshow.chatmodule.api.IMApi;
+import com.cooleshow.chatmodule.bean.ContactListBean;
+import com.cooleshow.chatmodule.contract.BlackListFragmentContract;
+import com.cooleshow.chatmodule.contract.ContactListFragmentContract;
+import com.tencent.imsdk.v2.V2TIMFriendInfo;
+import com.tencent.imsdk.v2.V2TIMFriendOperationResult;
+import com.tencent.imsdk.v2.V2TIMManager;
+import com.tencent.imsdk.v2.V2TIMValueCallback;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Author by pq, Date on 2022/5/6.
+ */
+public class BlackListPresenter extends BasePresenter<BlackListFragmentContract.View> implements BlackListFragmentContract.Presenter {
+
+    public void queryBlackList() {
+        V2TIMManager.getFriendshipManager().getBlackList(new V2TIMValueCallback<List<V2TIMFriendInfo>>() {
+            @Override
+            public void onSuccess(List<V2TIMFriendInfo> v2TIMFriendInfos) {
+                // 获取黑名单列表成功
+                if (getView() != null) {
+                    getView().getBlackListSuccess(v2TIMFriendInfos);
+                }
+
+            }
+            @Override
+            public void onError(int code, String desc) {
+                // 获取黑名单列表失败
+                if (getView() != null) {
+                    getView().getBlackListError();
+                }
+            }
+        });
+    }
+
+    public void removeBlackList(String targetId) {
+        if (getView() != null) {
+            getView().showLoading();
+        }
+        List<String> userIDList = new ArrayList<>();
+        userIDList.add(targetId);
+        V2TIMManager.getFriendshipManager().deleteFromBlackList(userIDList, new V2TIMValueCallback<List<V2TIMFriendOperationResult>>() {
+            @Override
+            public void onSuccess(List<V2TIMFriendOperationResult> v2TIMFriendOperationResults) {
+                // 解除拉黑成功
+                if (getView() != null) {
+                    LOG.i("removeBlackList onSuccess");
+                    getView().hideLoading();
+                    getView().operateSuccess();
+                }
+            }
+
+            @Override
+            public void onError(int code, String desc) {
+                // 解除拉黑失败
+                if (getView() != null) {
+                    LOG.i("removeBlackList onError:" + code + " " + desc);
+                    getView().hideLoading();
+                }
+            }
+        });
+    }
+}

+ 238 - 0
chatModule/src/main/java/com/cooleshow/chatmodule/ui/BlackListFragment.java

@@ -0,0 +1,238 @@
+package com.cooleshow.chatmodule.ui;
+
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.View;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.listener.OnItemChildClickListener;
+import com.chad.library.adapter.base.listener.OnItemClickListener;
+import com.cooleshow.base.constanst.Constants;
+import com.cooleshow.base.constanst.LoginStatusConstants;
+import com.cooleshow.base.event.LoginStatusEvent;
+import com.cooleshow.base.ui.fragment.BaseMVPFragment;
+import com.cooleshow.base.utils.SizeUtils;
+import com.cooleshow.base.widgets.CustomSuspensionDecoration;
+import com.cooleshow.base.widgets.EmptyViewLayout;
+import com.cooleshow.base.widgets.dialog.CommonConfirmDialog;
+import com.cooleshow.base.widgets.dialog.CommonDialog;
+import com.cooleshow.chatmodule.R;
+import com.cooleshow.chatmodule.adapter.BlackListAdapter;
+import com.cooleshow.chatmodule.adapter.ContactListAdapter;
+import com.cooleshow.chatmodule.bean.ContactListBean;
+import com.cooleshow.chatmodule.constants.IMConstants;
+import com.cooleshow.chatmodule.contract.BlackListFragmentContract;
+import com.cooleshow.chatmodule.contract.ContactListFragmentContract;
+import com.cooleshow.chatmodule.databinding.TcFragmentBlackListLayoutBinding;
+import com.cooleshow.chatmodule.databinding.TcFragmentContactListLayoutBinding;
+import com.cooleshow.chatmodule.presenter.BlackListPresenter;
+import com.cooleshow.chatmodule.presenter.ContactListPresenter;
+import com.cooleshow.chatmodule.utils.helper.ChatAvatarClickHelper;
+import com.cooleshow.chatmodule.utils.helper.ChatHelper;
+import com.cooleshow.chatmodule.utils.helper.IMThemManager;
+import com.cooleshow.chatmodule.widget.CommonConfirmDialog2;
+import com.cooleshow.chatmodule.widget.CustomIndexBarDataHelperImpl;
+import com.mcxtzhang.indexlib.suspension.SuspensionDecoration;
+import com.scwang.smart.refresh.layout.api.RefreshLayout;
+import com.scwang.smart.refresh.layout.listener.OnRefreshListener;
+import com.tencent.imsdk.v2.V2TIMFriendInfo;
+import com.tencent.qcloud.tuikit.timcommon.component.MessageProperties;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+/**
+ * 联系人列表
+ */
+public class BlackListFragment extends BaseMVPFragment<TcFragmentBlackListLayoutBinding, BlackListPresenter> implements BlackListFragmentContract.View, View.OnClickListener {
+
+    private BlackListAdapter mListAdapter;
+    private String searchCondition;
+    private EmptyViewLayout mEmptyViewLayout;
+
+
+    @Override
+    protected TcFragmentBlackListLayoutBinding getLayoutView() {
+        return TcFragmentBlackListLayoutBinding.inflate(getLayoutInflater());
+    }
+
+    @Override
+    protected BlackListPresenter createPresenter() {
+        return new BlackListPresenter();
+    }
+
+    @Override
+    protected void initView(View rootView) {
+        IMThemManager.getInstance().setSearchIconStyles(mViewBinding.ivSearchIcon);
+        IMThemManager.getInstance().setSearchButtonStyles(mViewBinding.tvSearch);
+        IMThemManager.getInstance().setEditStyle(mViewBinding.etTargetName);
+
+        mViewBinding.etTargetName.setHint("请输入用户名称");
+        mViewBinding.tvSearch.setOnClickListener(this);
+        mViewBinding.tvFilter.setOnClickListener(this);
+        mListAdapter = new BlackListAdapter();
+        setEmptyView();
+        LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
+        mViewBinding.recyclerView.setLayoutManager(layoutManager);
+        mViewBinding.recyclerView.setAdapter(mListAdapter);
+
+        mListAdapter.setOnItemChildClickListener(new OnItemChildClickListener() {
+            @Override
+            public void onItemChildClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
+                if (position < mListAdapter.getData().size()) {
+                    V2TIMFriendInfo v2TIMFriendInfo = mListAdapter.getData().get(position);
+                    if (view.getId() == R.id.iv_remove_black) {
+                        String id = v2TIMFriendInfo.getUserID();
+                        String name = "用户" + id;
+                        if (v2TIMFriendInfo.getUserProfile() != null) {
+                            name = v2TIMFriendInfo.getUserProfile().getNickName();
+                        }
+                        showConfirmDialog(id, name);
+                    }
+                }
+            }
+        });
+
+        mViewBinding.refreshLayout.setOnRefreshListener(new OnRefreshListener() {
+            @Override
+            public void onRefresh(@NonNull RefreshLayout refreshLayout) {
+                getData();
+            }
+        });
+    }
+
+
+    @Override
+    protected void initData() {
+
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        getData();
+    }
+
+    private void showConfirmDialog(String id, String nickName) {
+        CommonDialog commonDialog = new CommonDialog(getContext());
+        commonDialog.show();
+        commonDialog.setTitle("移除黑名单");
+        commonDialog.setContent(String.format("将%s移除黑名单后,您可向对方发送和接收消息。", nickName));
+        commonDialog.setOnConfirmClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (presenter != null) {
+                    presenter.removeBlackList(id);
+                    commonDialog.dismiss();
+                }
+            }
+        });
+        commonDialog.setOnCancelClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (commonDialog != null) {
+                    commonDialog.dismiss();
+                }
+            }
+        });
+    }
+
+
+    private void setEmptyView() {
+        if (mEmptyViewLayout == null) {
+            mEmptyViewLayout = new EmptyViewLayout(getContext());
+        }
+        Drawable conversationListEmptyDrawable = MessageProperties.getInstance().getConversationListEmptyDrawable();
+        if (conversationListEmptyDrawable != null) {
+            mEmptyViewLayout.setContent(conversationListEmptyDrawable, "暂无联系人");
+        } else {
+            mEmptyViewLayout.setContent(com.cooleshow.base.R.drawable.icon_empty_content, "暂无联系人");
+        }
+        mListAdapter.setEmptyView(mEmptyViewLayout);
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.tv_search) {
+            String targetSearchStr = mViewBinding.etTargetName.getText().toString().trim();
+            searchCondition = targetSearchStr;
+            getData();
+        }
+        if (v.getId() == R.id.tv_filter) {
+
+        }
+    }
+
+
+    private void getData() {
+        if (presenter != null) {
+            presenter.queryBlackList();
+        }
+    }
+
+    @Override
+    public void getBlackListSuccess(List<V2TIMFriendInfo> v2TIMFriendInfos) {
+        if (isDetached()) {
+            return;
+        }
+        mViewBinding.refreshLayout.finishRefresh();
+        if (mListAdapter != null) {
+            if (v2TIMFriendInfos != null && v2TIMFriendInfos.size() > 0) {
+                mListAdapter.setNewInstance(v2TIMFriendInfos);
+            } else {
+                mListAdapter.getData().clear();
+                mListAdapter.notifyDataSetChanged();
+            }
+        }
+    }
+
+    @Override
+    public void getBlackListError() {
+        if (isDetached()) {
+            return;
+        }
+        if (mListAdapter != null) {
+            mListAdapter.getData().clear();
+            mListAdapter.notifyDataSetChanged();
+        }
+        mViewBinding.refreshLayout.finishRefresh();
+    }
+
+    @Override
+    public void operateSuccess() {
+        if (isDetached()) {
+            return;
+        }
+        getData();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        EventBus.getDefault().register(this);
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    public void loadEventBus(LoginStatusEvent event) {
+        if (event != null && event.eventCode == LoginStatusConstants.LOGIN_OUT) {
+            searchCondition = "";
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        EventBus.getDefault().unregister(this);
+    }
+}

+ 4 - 2
chatModule/src/main/java/com/cooleshow/chatmodule/ui/ChatFragment.java

@@ -38,7 +38,7 @@ import androidx.fragment.app.Fragment;
  * Author by pq, Date on 2023/6/28.
  */
 public class ChatFragment extends BaseFragment<TcFragmentChatLayoutBinding> implements View.OnClickListener {
-    public static final String[] titles = new String[]{"聊天", "群聊", "联系人",};
+    public static final String[] titles = new String[]{"聊天", "群聊", "联系人","黑名单"};
     private ArrayList<Fragment> fragments = new ArrayList<>();
     private View mViewUnred;
     private IUnReadMessageObserver mUnReadMessageObserver = new IUnReadMessageObserver() {
@@ -141,13 +141,15 @@ public class ChatFragment extends BaseFragment<TcFragmentChatLayoutBinding> impl
         mConversationListFragment = new ConversationListFragment();
         ContactRoomListFragment contactRoomListFragment = new ContactRoomListFragment();
         ContactPersonListFragment contactPersonListFragment = new ContactPersonListFragment();
+        BlackListFragment blackListFragment = new BlackListFragment();
         contactPersonListFragment.setParentTopView(mViewBinding.viewTopBg);
         fragments.add(mConversationListFragment);
         fragments.add(contactRoomListFragment);
         fragments.add(contactPersonListFragment);
+        fragments.add(blackListFragment);
         MessagePagerAdapter messagePagerAdapter = new MessagePagerAdapter(this);
         messagePagerAdapter.setData(fragments);
-        mViewBinding.viewPager.setOffscreenPageLimit(3);
+        mViewBinding.viewPager.setOffscreenPageLimit(fragments.size());
         mViewBinding.viewPager.setAdapter(messagePagerAdapter);
         tabLayoutMediator.attach();
     }

+ 8 - 0
chatModule/src/main/java/com/cooleshow/chatmodule/utils/helper/ChatGroupHelper.java

@@ -142,6 +142,14 @@ public class ChatGroupHelper {
         return TextUtils.equals(roleType, ROLE_TYPE_TEACHER);
     }
 
+    public static boolean isTeacherById(String userId) {
+        if (TextUtils.isEmpty(userId)) {
+            return false;
+        }
+        return userId.contains(ROLE_TYPE_TEACHER);
+    }
+
+
     public static boolean isGroupConversation(int value) {
         return value == GROUP_TYPE_VALUE;//h5那边过来的conversation类型值等于3为群组
     }

BIN
chatModule/src/main/res/drawable-xhdpi/icon_remove_black.png


BIN
chatModule/src/main/res/drawable-xxhdpi/icon_remove_black.png


+ 115 - 0
chatModule/src/main/res/layout/tc_fragment_black_list_layout.xml

@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <View
+        android:background="@color/transparent"
+        android:id="@+id/view_top_bg"
+        app:layout_constraintBottom_toBottomOf="@+id/tv_filter"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"/>
+    <TextView
+        android:visibility="gone"
+        android:id="@+id/tv_filter"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        android:drawablePadding="5dp"
+        android:ellipsize="end"
+        android:gravity="center"
+        android:includeFontPadding="false"
+        android:maxLength="6"
+        android:maxLines="1"
+        android:paddingStart="13dp"
+        android:text="筛选"
+        android:textColor="@color/color_333333"
+        android:textSize="@dimen/sp_14"
+        app:layout_constraintBottom_toBottomOf="@+id/view_search_bg"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="@+id/view_search_bg" />
+
+    <View
+        android:id="@+id/view_search_bg"
+        android:layout_width="0dp"
+        android:layout_height="34dp"
+        android:layout_marginStart="8dp"
+        android:layout_marginEnd="14dp"
+        android:background="@drawable/bg_white_18dp"
+        app:layout_constraintLeft_toRightOf="@+id/tv_filter"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ImageView
+        android:id="@+id/iv_search_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="12dp"
+        android:src="@drawable/icon_search"
+        app:layout_constraintBottom_toBottomOf="@+id/view_search_bg"
+        app:layout_constraintLeft_toLeftOf="@+id/view_search_bg"
+        app:layout_constraintTop_toTopOf="@+id/view_search_bg" />
+
+    <com.cooleshow.base.widgets.ClearEditText
+        android:id="@+id/et_target_name"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="5dp"
+        android:background="@null"
+        android:ellipsize="end"
+        android:hint="请输入用户名称"
+        android:maxLines="1"
+        android:paddingStart="8dp"
+        android:includeFontPadding="false"
+        android:theme="@style/MyEditText"
+        android:textCursorDrawable="@drawable/shape_2dc7aa_1dp"
+        android:textColor="@color/color_aaaaaa"
+        android:textSize="@dimen/sp_14"
+        app:layout_constraintBottom_toBottomOf="@+id/view_search_bg"
+        app:layout_constraintLeft_toRightOf="@+id/iv_search_icon"
+        app:layout_constraintRight_toLeftOf="@+id/tv_search"
+        app:layout_constraintTop_toTopOf="@+id/view_search_bg" />
+
+    <TextView
+        android:id="@+id/tv_search"
+        android:layout_width="56dp"
+        android:layout_height="28dp"
+        android:layout_marginEnd="3dp"
+        android:background="@drawable/shape_1ecdac_18dp"
+        android:gravity="center"
+        android:text="搜索"
+        android:textColor="@color/white"
+        android:textSize="@dimen/sp_14"
+        android:includeFontPadding="false"
+        app:layout_constraintBottom_toBottomOf="@+id/view_search_bg"
+        app:layout_constraintRight_toRightOf="@+id/view_search_bg"
+        app:layout_constraintTop_toTopOf="@+id/view_search_bg" />
+
+    <androidx.constraintlayout.widget.Group
+        android:id="@+id/group_search"
+        app:constraint_referenced_ids="tv_search,et_target_name,iv_search_icon,view_search_bg"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+    <com.scwang.smart.refresh.layout.SmartRefreshLayout
+        android:id="@+id/refreshLayout"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:srlEnableLoadMore="false"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/view_search_bg">
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/recyclerView"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginTop="@dimen/dp_10"
+        android:scrollbars="none"
+        android:overScrollMode="never"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/liv_letters"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/view_search_bg"
+        app:layout_constraintVertical_bias="0.0"/>
+    </com.scwang.smart.refresh.layout.SmartRefreshLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 97 - 0
chatModule/src/main/res/layout/tc_item_black_list_layout.xml

@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@color/white"
+    android:paddingStart="@dimen/dp_14">
+
+    <de.hdodenhof.circleimageview.CircleImageView
+        android:id="@+id/iv_icon"
+        android:layout_width="@dimen/dp_44"
+        android:layout_height="@dimen/dp_44"
+        android:layout_marginTop="12dp"
+        android:layout_marginBottom="12dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:qmui_corner_radius="6dp" />
+
+    <LinearLayout
+        android:id="@+id/ll_klx_tag"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:background="@drawable/shape_im_teacher_tag_bg"
+        android:gravity="center"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_icon"
+        app:layout_constraintLeft_toLeftOf="@+id/iv_icon"
+        app:layout_constraintRight_toRightOf="@+id/iv_icon">
+
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/icon_im_teacher_avatar_tag" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="14dp"
+            android:gravity="center"
+            android:paddingStart="3dp"
+            android:text="@string/teacher_tag_str"
+            android:textColor="@color/white"
+            android:textSize="@dimen/sp_9" />
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/tv_name"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="11dp"
+        android:layout_marginEnd="10dp"
+        android:ellipsize="end"
+        android:includeFontPadding="false"
+        android:maxLines="1"
+        android:textColor="@color/color_1a1a1a"
+        android:textSize="@dimen/sp_16"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_icon"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintHorizontal_chainStyle="packed"
+        app:layout_constraintLeft_toRightOf="@+id/iv_icon"
+        app:layout_constraintRight_toLeftOf="@+id/iv_role_tag"
+        app:layout_constraintTop_toTopOf="@+id/iv_icon"
+        app:layout_constraintWidth_default="wrap"
+        app:layout_goneMarginEnd="27dp"
+        tools:text="哈喽王哈喽王哈喽王哈喽王哈喽王哈喽王哈喽王哈喽王哈喽王哈喽王" />
+
+    <ImageView
+        android:id="@+id/iv_role_tag"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/icon_teacher_tag"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="@+id/tv_name"
+        app:layout_constraintLeft_toRightOf="@+id/tv_name"
+        app:layout_constraintRight_toLeftOf="@+id/iv_remove_black"
+        app:layout_constraintTop_toTopOf="@+id/tv_name"
+        tools:visibility="visible" />
+
+    <ImageView
+        android:id="@+id/iv_remove_black"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="12dp"
+        android:src="@drawable/icon_remove_black"
+        app:layout_constraintBottom_toBottomOf="@+id/tv_name"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="@+id/tv_name" />
+
+    <View
+        android:layout_width="0dp"
+        android:layout_height="1px"
+        android:background="@color/divide_color_f0f0f0"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="@+id/tv_name" />
+</androidx.constraintlayout.widget.ConstraintLayout>