Files
zhini_im/开发文档/添加黑名单功能/添加黑名单功能.txt
rw0067680 c01808ac21 first commit
Change-Id: Ib7c2ab10a2562044fcaf9879388a6cbc1db6ac61
2025-12-23 10:00:49 +08:00

530 lines
17 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 设置中添加黑名单功能实现文档
## 功能背景
根据用户需求,在"我的-设置"页面中增加黑名单功能,让用户可以查看和管理黑名单用户,提供完整的黑名单管理体验。
## 问题描述
**测试步骤**:我的-设置页面
**问题**:缺少黑名单管理功能,用户无法查看和管理已加入黑名单的用户。
## 功能实现
### 1. 设置页面添加黑名单条目
#### 1.1 修改setting_activity.xml
**文件路径**`app/src/main/res/layout/setting_activity.xml`
```xml
<!-- 在青少年模式下方添加黑名单条目 -->
<cn.wildfire.chat.kit.widget.OptionItemView
android:id="@+id/blacklist_option"
style="@style/OptionItem"
app:show_arrow_indicator="true"
app:show_divider="true"
app:title="黑名单" />
```
#### 1.2 修改SettingActivity.java
**文件路径**`app/src/main/java/com/xunpaisoft/social/im/setting/SettingActivity.java`
```java
// 添加点击事件绑定
findViewById(R.id.blacklist_option).setOnClickListener(v -> blacklist());
// 添加跳转方法
void blacklist() {
Intent intent = new Intent(this, BlacklistActivity.class);
startActivity(intent);
}
```
### 2. 创建黑名单页面
#### 2.1 创建BlacklistActivity.java
**文件路径**`app/src/main/java/com/xunpaisoft/social/im/setting/BlacklistActivity.java`
```java
public class BlacklistActivity extends WfcBaseActivity {
private RecyclerView recyclerView;
private BlacklistAdapter adapter;
private List<UserInfo> blacklistUsers = new ArrayList<>();
private UserViewModel userViewModel;
@Override
protected int contentLayout() {
return R.layout.activity_blacklist;
}
@Override
protected void afterViews() {
super.afterViews();
initViews();
loadBlacklist();
}
private void initViews() {
setToolBarTitle("黑名单");
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new BlacklistAdapter(blacklistUsers, new BlacklistAdapter.OnUserClickListener() {
@Override
public void onRemoveUser(UserInfo userInfo) {
showRemoveConfirmDialog(userInfo);
}
});
recyclerView.setAdapter(adapter);
userViewModel = new UserViewModel();
}
private void loadBlacklist() {
// 获取黑名单用户ID列表
List<String> blacklistUserIds = ChatManagerHolder.gChatManager.getBlackList(true);
if (blacklistUserIds == null || blacklistUserIds.isEmpty()) {
showEmptyView();
return;
}
// 获取用户详细信息
List<UserInfo> userInfos = userViewModel.getUserInfos(blacklistUserIds);
if (userInfos != null && !userInfos.isEmpty()) {
blacklistUsers.clear();
blacklistUsers.addAll(userInfos);
adapter.notifyDataSetChanged();
} else {
showEmptyView();
}
}
private void showEmptyView() {
findViewById(R.id.emptyView).setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
}
private void showRemoveConfirmDialog(UserInfo userInfo) {
String userName = TextUtils.isEmpty(userInfo.displayName) ? userInfo.name : userInfo.displayName;
new AlertDialog.Builder(this)
.setTitle("移除黑名单")
.setMessage("确定要将 " + userName + " 从黑名单中移除吗?")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
removeFromBlacklist(userInfo);
}
})
.setNegativeButton("取消", null)
.show();
}
private void removeFromBlacklist(UserInfo userInfo) {
// 将用户从黑名单中移除
ChatManagerHolder.gChatManager.setBlackList(userInfo.uid, false, new GeneralCallback() {
@Override
public void onSuccess() {
runOnUiThread(() -> {
// 从本地列表中移除
blacklistUsers.remove(userInfo);
adapter.notifyDataSetChanged();
// 如果列表为空,显示空状态
if (blacklistUsers.isEmpty()) {
showEmptyView();
}
Toast.makeText(BlacklistActivity.this, "已从黑名单中移除", Toast.LENGTH_SHORT).show();
});
}
@Override
public void onFail(int errorCode) {
runOnUiThread(() -> {
Toast.makeText(BlacklistActivity.this, "移除失败,请重试", Toast.LENGTH_SHORT).show();
});
}
});
}
}
```
#### 2.2 创建activity_blacklist.xml
**文件路径**`app/src/main/res/layout/activity_blacklist.xml`
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gray5"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<!-- 黑名单用户列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="8dp" />
<!-- 空状态视图 -->
<LinearLayout
android:id="@+id/emptyView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginBottom="16dp"
android:src="@drawable/ic_empty_blacklist"
android:alpha="0.6" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂无黑名单用户"
android:textColor="@color/color_9999"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="您可以将不想联系的用户加入黑名单"
android:textColor="@color/color_9999"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
```
### 3. 创建黑名单用户列表适配器
#### 3.1 创建BlacklistAdapter.java
**文件路径**`app/src/main/java/com/xunpaisoft/social/im/setting/BlacklistAdapter.java`
```java
public class BlacklistAdapter extends RecyclerView.Adapter<BlacklistAdapter.ViewHolder> {
private List<UserInfo> userList;
private OnUserClickListener listener;
public interface OnUserClickListener {
void onRemoveUser(UserInfo userInfo);
}
public BlacklistAdapter(List<UserInfo> userList, OnUserClickListener listener) {
this.userList = userList;
this.listener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_blacklist_user, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
UserInfo userInfo = userList.get(position);
// 设置头像
if (!TextUtils.isEmpty(userInfo.portrait)) {
GlideUtils.loadImage(holder.avatarImageView.getContext(), userInfo.portrait, holder.avatarImageView, R.mipmap.icon_default_man, R.mipmap.icon_default_man);
} else {
holder.avatarImageView.setImageResource(R.mipmap.icon_default_man);
}
// 设置用户名
String displayName = TextUtils.isEmpty(userInfo.displayName) ? userInfo.name : userInfo.displayName;
holder.nameTextView.setText(displayName);
// 设置移除按钮点击事件
holder.removeButton.setOnClickListener(v -> {
if (listener != null) {
listener.onRemoveUser(userInfo);
}
});
}
@Override
public int getItemCount() {
return userList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView avatarImageView;
TextView nameTextView;
TextView removeButton;
public ViewHolder(@NonNull View itemView) {
super(itemView);
avatarImageView = itemView.findViewById(R.id.avatarImageView);
nameTextView = itemView.findViewById(R.id.nameTextView);
removeButton = itemView.findViewById(R.id.removeButton);
}
}
}
```
#### 3.2 创建item_blacklist_user.xml
**文件路径**`app/src/main/res/layout/item_blacklist_user.xml`
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="horizontal"
android:padding="16dp">
<!-- 用户头像 -->
<ImageView
android:id="@+id/avatarImageView"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="12dp"
android:scaleType="centerCrop"
android:src="@mipmap/icon_default_man" />
<!-- 用户信息区域 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_vertical">
<TextView
android:id="@+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="用户名"
android:textColor="@color/color_3333"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 移除按钮 -->
<TextView
android:id="@+id/removeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/btn_remove_blacklist"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:minWidth="60dp"
android:paddingHorizontal="12dp"
android:paddingVertical="6dp"
android:text="移除"
android:textColor="@color/white"
android:textSize="14sp" />
</LinearLayout>
```
### 4. 创建样式和资源文件
#### 4.1 创建btn_remove_blacklist.xml
**文件路径**`app/src/main/res/drawable/btn_remove_blacklist.xml`
```xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FF6B6B" />
<corners android:radius="16dp" />
</shape>
```
#### 4.2 创建ic_empty_blacklist.xml
**文件路径**`app/src/main/res/drawable/ic_empty_blacklist.xml`
```xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="80dp"
android:height="80dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#CCCCCC"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
<path
android:fillColor="#CCCCCC"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>
```
### 5. 注册Activity
#### 5.1 修改AndroidManifest.xml
**文件路径**`app/src/main/AndroidManifest.xml`
```xml
<activity
android:name=".im.setting.BlacklistActivity"
android:label="黑名单"
android:screenOrientation="portrait" />
```
## 技术实现细节
### 1. IM接口调用
#### 1.1 获取黑名单
```java
// 获取黑名单用户ID列表
List<String> blacklistUserIds = ChatManagerHolder.gChatManager.getBlackList(true);
```
#### 1.2 移除黑名单
```java
// 将用户从黑名单中移除
ChatManagerHolder.gChatManager.setBlackList(userInfo.uid, false, new GeneralCallback() {
@Override
public void onSuccess() {
// 移除成功处理
}
@Override
public void onFail(int errorCode) {
// 错误处理
}
});
```
### 2. 用户信息获取
#### 2.1 同步获取用户信息
```java
// 获取用户详细信息
List<UserInfo> userInfos = userViewModel.getUserInfos(blacklistUserIds);
```
#### 2.2 头像加载
```java
// 使用GlideUtils加载用户头像
if (!TextUtils.isEmpty(userInfo.portrait)) {
GlideUtils.loadImage(holder.avatarImageView.getContext(), userInfo.portrait, holder.avatarImageView, R.mipmap.icon_default_man, R.mipmap.icon_default_man);
} else {
holder.avatarImageView.setImageResource(R.mipmap.icon_default_man);
}
```
### 3. 界面交互
#### 3.1 确认对话框
```java
private void showRemoveConfirmDialog(UserInfo userInfo) {
String userName = TextUtils.isEmpty(userInfo.displayName) ? userInfo.name : userInfo.displayName;
new AlertDialog.Builder(this)
.setTitle("移除黑名单")
.setMessage("确定要将 " + userName + " 从黑名单中移除吗?")
.setPositiveButton("确定", (dialog, which) -> removeFromBlacklist(userInfo))
.setNegativeButton("取消", null)
.show();
}
```
#### 3.2 空状态处理
```java
private void showEmptyView() {
findViewById(R.id.emptyView).setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
}
```
## 功能效果
### 1. 设置页面结构
```
设置
├── 账号安全
├── 消息通知(开关)
├── 青少年模式
├── 黑名单 ← 新增
├── 清除缓存
├── 意见反馈
├── 版本更新
└── 关于我们
```
### 2. 黑名单页面功能
- **用户列表显示**:显示所有黑名单用户的头像和姓名
- **移除功能**:点击移除按钮可以移除用户
- **确认对话框**:移除前显示确认对话框
- **空状态提示**:无黑名单用户时显示友好提示
- **实时更新**:移除后立即更新界面
### 3. 用户体验
- **操作简单**:一键移除黑名单用户
- **安全确认**:移除前需要用户确认
- **状态反馈**:操作成功或失败都有提示
- **界面友好**:空状态时提供使用说明
## 文件清单
### 1. 新增文件
1. `app/src/main/java/com/xunpaisoft/social/im/setting/BlacklistActivity.java` - 黑名单页面
2. `app/src/main/java/com/xunpaisoft/social/im/setting/BlacklistAdapter.java` - 列表适配器
3. `app/src/main/res/layout/activity_blacklist.xml` - 黑名单页面布局
4. `app/src/main/res/layout/item_blacklist_user.xml` - 用户列表项布局
5. `app/src/main/res/drawable/btn_remove_blacklist.xml` - 移除按钮样式
6. `app/src/main/res/drawable/ic_empty_blacklist.xml` - 空状态图标
### 2. 修改文件
1. `app/src/main/res/layout/setting_activity.xml` - 添加黑名单条目
2. `app/src/main/java/com/xunpaisoft/social/im/setting/SettingActivity.java` - 添加跳转逻辑
3. `app/src/main/AndroidManifest.xml` - 注册BlacklistActivity
## 优势特点
### 1. 用户体验
- **功能完整**:支持查看和移除黑名单用户
- **操作便捷**:一键移除,操作简单
- **安全可靠**:移除前需要确认,避免误操作
- **状态清晰**:空状态时提供友好提示
### 2. 技术优势
- **架构清晰**使用MVVM架构代码结构清晰
- **性能优良**使用RecyclerView支持大量数据
- **内存安全**正确处理Activity生命周期
- **错误处理**:完善的网络错误处理机制
### 3. 业务价值
- **用户管理**:提供完整的黑名单管理功能
- **隐私保护**:用户可以管理不想联系的用户
- **体验提升**:完善的功能提升用户满意度
- **系统完整**补全了IM系统的用户管理功能
## 总结
本次功能实现成功在设置页面添加了黑名单功能,通过以下方式实现:
1. **界面完善**:在设置页面添加黑名单条目,创建专门的黑名单管理页面
2. **功能完整**:支持查看黑名单用户列表,支持移除黑名单用户
3. **用户体验**:提供确认对话框、空状态提示、操作反馈等完善的用户体验
4. **技术实现**使用IM接口进行黑名单管理使用RecyclerView展示用户列表
功能实现后,用户可以在设置页面进入黑名单管理,查看所有黑名单用户,并可以方便地移除不需要的用户,完全满足了用户需求,提升了应用的用户管理功能。