103 Commits

Author SHA1 Message Date
fbc2a57593 1:修改点唱房头像框显示 2025-12-05 00:25:51 +08:00
lzl
016e1329da 刷新 2025-12-05 00:23:22 +08:00
lzl
7f200fbafc 点唱修改。 2025-12-05 00:04:12 +08:00
fac83d7c23 1:修改点唱房已点歌曲展示置顶的问题 2025-12-04 23:56:19 +08:00
lzl
f985ea9aeb 点唱修改。 2025-12-04 23:47:51 +08:00
lzl
a808da0df5 1001 速度过快null 2025-12-04 23:20:40 +08:00
lzl
dc42ad9049 cpview CircularImage 2025-12-04 23:13:52 +08:00
lzl
741063f239 Merge remote-tracking branch 'origin/branch_new' into branch_new 2025-12-04 23:11:17 +08:00
lzl
99dbd3d321 cpview 播放添加延迟2秒 2025-12-04 23:11:11 +08:00
f5c00c640d 1:修改点唱房展示错误 2025-12-04 23:09:16 +08:00
lzl
532f85e9e2 cpview 回退 2025-12-04 23:07:36 +08:00
lzl
b46913b920 拍卖房 fix bugs. 2025-12-04 22:51:36 +08:00
lzl
2756fdb4b7 签约视图高度and闪退修改 62 2025-12-04 21:13:12 +08:00
babd07e592 1:修改bug 2025-12-04 21:12:00 +08:00
c632692982 1:修改bug 2025-12-04 20:56:30 +08:00
lzl
56bb994377 点唱无唱者闪退修改 2025-12-04 18:48:43 +08:00
defb31a217 1:打赏去掉趣味展示 2025-12-04 17:58:04 +08:00
lzl
f8460f0239 房间类型切换隐藏延时and关闭 2025-12-04 17:41:40 +08:00
5b22ebd218 1:修改家族展示续签按钮位置
2:修改购买爵位前,先请求一次接口
3:修改所有CP更改为心动
4:修改挚友,初始获取数据变更成40条
5:未实名认证不能进行歌手认证
6: 点唱房换麦出现页面展示不对
2025-12-04 17:38:13 +08:00
lzl
ff2b5aa668 小黑屋跳转逻辑修改。 2025-12-04 16:29:26 +08:00
lzl
057f623eec 小黑屋退出闪退 2025-12-04 15:59:57 +08:00
46b0a856fe 1:修改家族展示续签按钮位置
2:修改购买爵位前,先请求一次接口
3:修改所有CP更改为心动
4:修改挚友,初始获取数据变更成40条
5:未实名认证不能进行歌手认证
2025-12-04 15:20:05 +08:00
lzl
0f0c2d97cc 1035 bug修改,拍卖房心动礼物无法选择添加toast 2025-12-04 15:18:30 +08:00
lzl
64f538f04d 个人信息显示,签约1035添加 2025-12-04 14:25:09 +08:00
885f981b6f 1:修改拍卖房和互娱房展示离线状态
2:修改在线列表为用户列表
3:修改扩列展示用户性别
2025-12-04 14:06:12 +08:00
lzl
f9e9811c4b 心动空间 时间显示。 2025-12-04 11:09:39 +08:00
lzl
ea188cde92 签约 充值 2025-12-04 10:19:57 +08:00
23a07562b7 1:修改CP特效出现头像不规则的问题 2025-12-04 10:18:51 +08:00
lzl
22a1f420ea 添加震动 2025-12-03 20:16:07 +08:00
0d5e64e31a 1:修改点歌房出现的错误
2:修改进入家族详情页面
2025-12-03 20:02:14 +08:00
lzl
8e9f6fa23c fix bugs.2 2025-12-03 17:33:30 +08:00
9a4b9b973b 1:修改房间离线展示 2025-12-03 17:08:01 +08:00
lzl
50ef12ee3b fix bugs. 2025-12-03 14:58:21 +08:00
lzl
0f054e1b69 fix bugs. 2025-12-03 13:59:47 +08:00
e0f6dff1d6 1:修改群聊可以不充值发送消息
2:修改群聊设置不用退出多次
2025-12-03 11:44:20 +08:00
a4c2fdb859 1:修改爵位进场很慢的情况 2025-12-03 10:33:15 +08:00
lzl
8d35790413 if ((message.getMsgType() == 1001 || message.getMsgType() == 1080) && publicScreenListeners.isEmpty()) {
cacheMessage(message.getRoomId(), message);
        }
2025-12-03 10:31:11 +08:00
lzl
dc9726d5b4 更换vap库 2025-12-03 09:09:57 +08:00
lzl
10e5504ce1 fix bugs. 2025-12-02 19:35:18 +08:00
d94d7a75df 1:修改测试出来的bug,关于:身价、我的家族、歌手认证、挚友、房间心跳、 2025-12-02 19:26:37 +08:00
lzl
8ce028379c fix bugs. 2025-12-02 15:37:29 +08:00
7bf2297750 1:我的页面展示身价 2025-12-02 14:41:21 +08:00
4d2c1a5ace 1:取消所有的切换后台、im重连给服务段发送接口
2:修改1058,所有房间添加展示离线
2025-12-02 14:11:40 +08:00
lzl
56489b3af7 Merge branch 'branch_new_dev' into branch_new 2025-12-02 11:42:12 +08:00
9135198b9d Merge remote-tracking branch 'origin/branch_new' into branch_new
# Conflicts:
#	MainModule/src/main/java/com/xscm/modulemain/activity/room/activity/RoomActivity.kt
2025-12-02 10:57:32 +08:00
1ec1b12e6c 1:点唱房添加在离线
2:修改心跳时长
2025-12-02 10:56:37 +08:00
lzl
23751fd1fa 签约 1058 2025-12-02 10:49:51 +08:00
980ec43e6c 1:修改当在游戏房间的时候,不能点击其他房间进入,
2:在进入房间后,退出上一个房间的各种调用
2025-12-01 18:41:14 +08:00
lzl
be60810221 签约 麦上用户拍卖更新麦上用户信息 2025-12-01 17:43:56 +08:00
lzl
85df01db3b 签约 显示 2025-12-01 17:28:24 +08:00
lzl
43138a56bc 签约规则 2025-12-01 16:59:58 +08:00
lzl
d42fb54aee 优化弹窗 2025-12-01 16:52:10 +08:00
lzl
5f93d184d2 签约 开始成功失败 2025-12-01 16:00:11 +08:00
e925a0c2a5 1:修改师父标签
2:修改签约房的清除魅力我更新魅力
2025-12-01 15:35:22 +08:00
lzl
49e345db2c 签约 刷新数据 2025-12-01 15:26:57 +08:00
lzl
18c3f494a3 签约 完善 2 2025-12-01 14:07:14 +08:00
lzl
06ce98a3ab 签约 完善 1 2025-12-01 11:34:56 +08:00
9183342636 1:添加在房间点击用户头像,展示有师傅的头像,并且添加点击事件
2:点击用户头像,进入用户主页的时候,展示师傅的头像
2025-12-01 10:29:34 +08:00
lzl
fd9af6a253 Merge branch 'branch_new_dev' into branch_new 2025-12-01 09:06:39 +08:00
lzl
94a55bafea 签约 A 2025-11-28 19:04:18 +08:00
847c768e4d 1:修改点唱房的页面展示问题
2:修改家族展示的问题
2025-11-28 19:01:37 +08:00
2b750c5f06 1:完成家族中续签请求接口和弹框展示的文案 2025-11-28 16:53:27 +08:00
lzl
995d7c1e90 添加接口 2025-11-28 14:39:57 +08:00
784a67214d 1:完成才艺展示功能 2025-11-28 14:38:03 +08:00
lzl
b089f4a56f 签约 1.1 2025-11-28 10:53:50 +08:00
lzl
a22cade574 签约 1 2025-11-28 10:43:16 +08:00
c216099173 1:完成我的家族功能 2025-11-28 09:13:08 +08:00
lzl
7821ef304d 合并 2025-11-28 09:09:37 +08:00
lzl
dce8b08a3f 签约上下麦 2025-11-28 09:00:38 +08:00
lzl
18559d0553 Merge branch 'branch_new_dev' into branch_new 2025-11-27 16:06:17 +08:00
lzl
fe9e192aea 合并 2025-11-27 11:59:19 +08:00
lzl
fe1ad2a732 Merge branch 'branch_new_dev' into branch_new 2025-11-27 11:53:16 +08:00
lzl
2a0c3b6d7f 合并 new_dev 2025-11-26 17:27:56 +08:00
603899ddef 1:给我的页面和设置页面添加点击日志 2025-11-26 16:32:46 +08:00
9887185133 1:添加签约房的按钮
2:我的家族和的身价页面完成
3:个性装扮降身卡完成
2025-11-26 15:52:46 +08:00
lzl
1753d9a98d 签约房UI 2025-11-26 09:04:58 +08:00
cc42d0f90f 1:修改其他房间类型送礼出现的报错 2025-11-25 09:12:09 +08:00
0dd7c367cb 1:添加cp进场动画效果
2:修改cp礼物弹框
3:添加组成cp后进入心动空间跳转
2025-11-24 18:48:14 +08:00
lzl
a1e123f0bf 接口返回数据错乱容错。 2025-11-24 16:07:59 +08:00
lzl
6edd0ed339 心动空间 优化帮助。 2025-11-24 14:10:17 +08:00
c4c6072c16 1:添加Cp动画 2025-11-24 09:59:58 +08:00
lzl
83307295bb 心动空间规则 2025-11-22 18:58:54 +08:00
a125d8d9b4 1:添加Cp动画,需调试 2025-11-22 18:55:17 +08:00
lzl
2a6d2e4709 心动空间 2025-11-22 18:38:49 +08:00
5eac6d302c 1:修改点唱房的bug
2:添加公会消息类型
2025-11-22 16:06:32 +08:00
lzl
18b1235a80 解决冲突 2025-11-22 11:27:23 +08:00
lzl
95a1e21909 合并 fix bugs 2025-11-22 11:22:41 +08:00
lzl
3c344e1359 1 2025-11-22 11:09:15 +08:00
af8b87dd47 1:挚友列表添加头像框展示,服务器返回就展示,不返回不展示 2025-11-22 09:23:32 +08:00
lzl
7e33926a03 A 2025-11-21 19:04:54 +08:00
1dfcf4e98c 1:完成挚友功能
2:添加在送特定礼物展示弹框功能
3:修改部分图片格式变成wedp
4:用户主页添加礼物墙和挚友
2025-11-21 18:54:40 +08:00
lzl
3c83906870 user home 2025-11-21 10:23:36 +08:00
lzl
355141a2a8 userHomePage add cp. 2025-11-20 19:21:20 +08:00
lzl
117ee41ff2 优化房间用户信息弹窗cp动画头像显示。 2025-11-20 16:34:06 +08:00
lzl
db79bafdbc 房间用户信息。 2025-11-20 16:11:13 +08:00
lzl
cf73819ad0 登录默认选中 2025-11-20 10:16:45 +08:00
be7c855283 1:修改我的页面点击事件 2025-11-20 10:06:17 +08:00
lzl
acec782e3a Merge branch 'branch_new_dev' into branch_new 2025-11-20 09:42:20 +08:00
57b8ded0eb 1:完成cp效果展示, 2025-11-20 09:40:53 +08:00
lzl
68dc7574bc room user info 2025-11-19 18:55:14 +08:00
lzl
f7b46d7320 Merge branch 'branch_new_dev' into branch_new 2025-11-19 10:38:48 +08:00
b3f6d3a3fb 修改点唱房页面展示错误 2025-11-19 09:43:33 +08:00
88a94c7c10 点唱房功能 2025-11-18 19:39:16 +08:00
643 changed files with 26771 additions and 2313 deletions

View File

@@ -172,7 +172,9 @@ dependencies {
// api('com.tencent.liteav:LiteAVSDK_Professional:10.9.0.13102')
// api('com.google.android.exoplayer:exoplayer-core:2.19.1')
// api('com.google.android.exoplayer:exoplayer-ui:2.19.1')
api("com.egame.vap:animplayer:2.0.8")
// api("com.egame.vap:animplayer:2.0.8")
api project(":animplayer")
api("com.liulishuo.okdownload:okdownload:1.0.7")
api('com.zlc.glide:webpdecoder:1.6.4.9.0')

View File

@@ -122,6 +122,7 @@ public class GiftPackAdapter extends BaseAdapter {
viewHolder.ivDownOn = (ImageView) convertView.findViewById(R.id.iv_down_on);
viewHolder.cl_iv_down_on = (ConstraintLayout) convertView.findViewById(R.id.cl_iv_down_on);
viewHolder.integral = (TextView) convertView.findViewById(R.id.integral);
viewHolder.im_heart = (ImageView) convertView.findViewById(R.id.im_heartssss);
convertView.setTag(viewHolder);
} else {
viewHolder = (GiftPackAdapter.ViewHolder) convertView.getTag();
@@ -168,5 +169,6 @@ public class GiftPackAdapter extends BaseAdapter {
public TextView tv_gift_change_love_values;
public ImageView ivDownOn;
public ConstraintLayout cl_iv_down_on;
public ImageView im_heart;
}
}

View File

@@ -1,6 +1,7 @@
package com.xscm.moduleutil.adapter;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -122,14 +123,16 @@ public class GiftRoomAdapter extends BaseAdapter {
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_gift_room, parent, false);
viewHolder = new ViewHolder();
viewHolder.item_layout = (ConstraintLayout) convertView.findViewById(R.id.cl_gift);
viewHolder.cl_iv_down_on = (ConstraintLayout) convertView.findViewById(R.id.cl_iv_down_on);
viewHolder.tv_gift_name = (TextView) convertView.findViewById(R.id.tv_gift_name);
viewHolder.tv_gift_price = (TextView) convertView.findViewById(R.id.tv_gift_price);
viewHolder.iv_gift_pic = (ImageView) convertView.findViewById(R.id.iv_gift_pic);
viewHolder.item_layout = (ConstraintLayout) convertView.findViewById(R.id.cl_gift);
viewHolder.ivDownOn = (ImageView) convertView.findViewById(R.id.iv_down_on);
viewHolder.cl_iv_down_on = (ConstraintLayout) convertView.findViewById(R.id.cl_iv_down_on);
viewHolder.iv_gift_select= (ImageView) convertView.findViewById(R.id.iv_gift_select);
// im_heart现在位于顶层布局中
viewHolder.im_heart = (ImageView) convertView.findViewById(R.id.im_heartssss);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
@@ -146,7 +149,15 @@ public class GiftRoomAdapter extends BaseAdapter {
if (giftModel.getIs_lock()==0){
viewHolder.iv_gift_select.setVisibility(GONE);
}else {
viewHolder.iv_gift_select.setVisibility(View.VISIBLE);
viewHolder.iv_gift_select.setVisibility(VISIBLE);
}
if (giftModel.getIs_cp()==0) {//这是cp礼物
viewHolder.im_heart.setVisibility(GONE);
}else {
if (viewHolder.im_heart != null) {
viewHolder.im_heart.setVisibility(VISIBLE);
}
}
/*
* 在给View绑定显示的数据时计算正确的position = position + curIndex * pageSize
@@ -214,6 +225,7 @@ public class GiftRoomAdapter extends BaseAdapter {
public TextView tv_gift_change_love_values;
public ImageView ivDownOn;
public ImageView iv_gift_select;
public ImageView im_heart;
public ConstraintLayout cl_iv_down_on;
}
}

View File

@@ -159,12 +159,11 @@ public class CommonAppContext extends MultiDexApplication implements Applicatio
}
//设置mqtt环境 false 测试环境 true 正式环境
// ExternalResConstants.INSTANCE.setIS_MQTT_RELEASE(false);
// ExternalResConstants.INSTANCE.setIS_MQTT_RELEASE(false);
//设置http环境 false 测试环境 true 正式环境
ExternalResConstants.INSTANCE.setIS_HTTP_RELEASE(false);
currentEnvironment = ExternalResConstants.INSTANCE.HTTP_PATH();
initialization();
}
@@ -808,7 +807,7 @@ public class CommonAppContext extends MultiDexApplication implements Applicatio
AppLifecycleUtil.onAppFrontGround();
}
if (playId!=null && !playId.equals("")){
RetrofitClient.getInstance().userRoomBack(playId, "2");
// RetrofitClient.getInstance().userRoomBack(playId, "2");
}
activityCount++;
}
@@ -823,7 +822,7 @@ public class CommonAppContext extends MultiDexApplication implements Applicatio
}
if (playId!=null && !playId.equals("")){
RetrofitClient.getInstance().userRoomBack(playId, "1");
// RetrofitClient.getInstance().userRoomBack(playId, "1");
}
AppLifecycleUtil.onAppBackGround();

View File

@@ -1,5 +1,6 @@
package com.xscm.moduleutil.bean;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
@@ -10,7 +11,7 @@ import lombok.Data;
* @Description $
*/
@Data
public class CombinedGiftBean {
public class CombinedGiftBean implements Serializable {
private int gift_id;
private String gift_price;
private String gift_name;
@@ -21,7 +22,7 @@ public class CombinedGiftBean {
private boolean is_liang;
@Data
public static class TopUsers {
public static class TopUsers implements Serializable{
private int user_id;
private String nickname;
private String avatar;

View File

@@ -0,0 +1,34 @@
package com.xscm.moduleutil.bean
/**
* 项目名称:羽声语音
* 时间2025/11/27 16:47
* 用途:
*/
class FamilyEarnings {
var id: Int=0
var nickname: String=""
var avatar: String=""
var user_code: String=""
var earnings: String=""
var createtime: Long=0
var gift_name: String=""
var gift_price: String=""
/* id 列表 id
nickname 用户昵称
avatar
user_code
earnings 收益
createtime
gift_name 礼物名称
gift_price 礼物价格*/
}

View File

@@ -40,6 +40,7 @@ public class GiftBoxBean {
private List<DailyTasksBean> daily_tasks;
private List<DailyTasksBean> daily_tasks_special;
private List<DailyTasksBean> usual_tasks;
private List<DailyTasksBean> teacher_tasks;
@Data
public static class DailyTasksBean {
@@ -54,6 +55,7 @@ public class GiftBoxBean {
private int processing_type;//跳转状态:
private String processing_type_str;//跳转状态
private String from_id;
private int reward_type;//1金币 2钻石
}
}

View File

@@ -1,5 +1,6 @@
package com.xscm.moduleutil.bean;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
@@ -10,11 +11,11 @@ import lombok.Data;
* @Description $ 礼物墙展示接口
*/
@Data
public class GiftUserWallBean {
public class GiftUserWallBean implements Serializable {
private List<GiftWallBean> liang;
private List<GiftWallBean> no_liang;
@Data
public static class GiftWallBean {
public static class GiftWallBean implements Serializable {
private int gift_id;
private String gift_price;
private String gift_name;

View File

@@ -0,0 +1,102 @@
package com.xscm.moduleutil.bean
import java.io.Serializable
class HeartCpBean : Serializable {
/* {
"code": 1,
"msg": "\u6210\u529f",
"data": {
"id": 1,
"user_id1": 20001,
"user_id2": 20003,
"status": 1,
"level": 1,
"exp": 9198,
"createtime": 1763720783,
"user_info1": {
"user_id": 20001,
"nickname": "\u9ad8\u5174\u7684\u5c0f\u6d77\u817e",
"avatar": "https:\/\/yusheng-1369267578.cos.ap-guangzhou.myqcloud.com\/images\/ios_images\/1761615690733.jpeg"
},
"user_info2": {
"user_id": 20003,
"nickname": "\u79c0\u4e3d\u7684\u978b\u57ab",
"avatar": "https:\/\/yusheng-1369267578.cos.ap-guangzhou.myqcloud.com\/images\/android_images\/33e31b18577856c4f10906b7cabaa698.jpg"
},
"next_level_exp": 802,
"pendant": "https:\/\/cos.xscmmidi.site\/admin\/520liuxingyu_17637096968287.mp4",
"gift_log": [
{
"id": 323,
"room_id": 6003,
"from_user_id": 20001,
"to_user_id": 20003,
"gift_id": 313,
"num": 1,
"cp_zone_id": 1,
"exp": "1314",
"exp_total": "9198",
"remark": "\u9001\u7ed9\u79c0\u4e3d\u7684\u978b\u57ab1\u4e2a\u9e4a\u7f18\u7ec7\u68a6,\u83b7\u5f971314\u7ecf\u9a8c\u503c\uff0c\u603b\u7ecf\u9a8c\u503c\u589e\u52a0\u81f39198",
"createtime": 1763796118,
"gift_name": "\u9e4a\u7f18\u7ec7\u68a6",
"from_user_info": {
"user_id": 20001,
"nickname": "\u9ad8\u5174\u7684\u5c0f\u6d77\u817e",
"avatar": "https:\/\/yusheng-1369267578.cos.ap-guangzhou.myqcloud.com\/images\/ios_images\/1761615690733.jpeg"
},
"to_user_info": {
"user_id": 20003,
"nickname": "\u79c0\u4e3d\u7684\u978b\u57ab",
"avatar": "https:\/\/yusheng-1369267578.cos.ap-guangzhou.myqcloud.com\/images\/android_images\/33e31b18577856c4f10906b7cabaa698.jpg"
}
}]
},
"api_version": ""
}*/
var id: Int = 0
var user_id1: Int = 0
var user_id2: Int = 0
var status: Int = 0
var level: Int = 0
var exp: Long = 0
var createtime: Long = 0
var user_info1: UserInfo = UserInfo()
var user_info2: UserInfo = UserInfo()
var next_level_exp: Long = 0
var pendant: String = ""
var gift_log: List<GiftLog> = ArrayList()
var api_version: String = ""
class GiftLog : Serializable {
var id: Int = 0
var room_id: Int = 0
var from_user_id: Int = 0
var to_user_id: Int = 0
var gift_id: Int = 0
var num: Int = 0
var cp_zone_id: Int = 0
var exp: String = ""
var exp_total: String = ""
var remark: String = ""
var createtime: Long = 0
var gift_name: String = ""
var from_user_info: UserInfo = UserInfo()
var to_user_info: UserInfo = UserInfo()
class UserInfo : Serializable {
var user_id: Int = 0
var nickname: String = ""
var avatar: String = ""
}
}
class UserInfo : Serializable {
var user_id: Int = 0
var nickname: String = ""
var avatar: String = ""
}
}

View File

@@ -0,0 +1,95 @@
package com.xscm.moduleutil.bean
/**
* 项目名称:羽声语音
* 时间2025/11/26 18:45
* 用途:
*/
class MyFamilyBean {
var group_id: String = "" //群组id
var name: String = "" //家族名称
var user_id: Int = 0 //族长id
var group_members_num: Int = 0 //签约次数 群组人数
var group_earnings: String = "" //总计收益
var group_owner_info: GroupOwnerInfoBean? = null //族长信息
class GroupOwnerInfoBean {
var nickname: String = "" //昵称
var avatar: String = "" //头像
var dress: String = "" //头像框
var user_code: String = "" //用户id
var icon: List<String> = arrayListOf()
var mic_cycle: String = "" //麦圈
var nobility_image: String = "" //贵族
var nickname_color: String = "" //贵族颜色
}
var group_members_lists: List<GroupMembersListsBean> = arrayListOf() //
class GroupMembersListsBean{
var market_value: String = "" //身价
var nickname: String = ""
var avatar: String = ""
var user_code: String = ""
var user_id: Int = 0
var end_time: Long = 0 //签约到期时间点
var dress: String = ""
var icon: List<String> = arrayListOf()
var mic_cycle: String = "" //麦圈
var nobility_image: String = "" //贵族
var nickname_color: String = "" //贵族颜色
var free_renewal: Int = 0 //免费续签次数
var today_earnings: Double = 0.0 //今日收礼收益
var yesterday_earnings: Double = 0.0 //昨日收礼收益
var is_online: Int = 0 //是否在线 1在线 0离线
var is_show_sign: Int = 0 //是否显示续约按钮 1显示 0不显示
var sign_times: Int = 0 //非首签签约时长
var sign_user_ratio : Int = 0 //非首签签约比例
var end_day: String = "" //签约剩余时长
val free_re_sign_day : Int=0 //免费续签时长
}
/* "group_id": "string",
"name": "string",
"user_id": "string",
"group_members_num": "string",
"group_earnings": "string",
"group_owner_info": {
"nickname": "string",
"avatar": "string",
"dress": "string",
"user_code": "string",
"icon": [
"string"
],
"mic_cycle": "string",
"nobility_image": "string",
"nickname_color": "string"
},
"group_members_lists": [
{
"market_value": "string",
"nickname": "string",
"avatar": "string",
"user_code": "string",
"user_id": "string",
"end_time": "string",
"dress": "string",
"icon": [
"string"
],
"mic_cycle": "string",
"nobility_image": "string",
"nickname_color": "string",
"free_renewal": "string",
"today_earnings": "string",
"yesterday_earnings": "string"
}
]
}*/
}

View File

@@ -10,7 +10,7 @@ import lombok.Data;
@Data
public class NewsMessageList {
private int id;
private int type;//类型 1系统消息 2官方公告 3活动中心
private int type;//类型 1系统消息 2官方公告 3活动中心 6邀请加入公会
private int admin_id;
private String title;//标题
private String content;//内容
@@ -22,4 +22,5 @@ public class NewsMessageList {
private String createtime;
private String updatetime;
private String delete_time;
private int guild_invited_status;
}

View File

@@ -0,0 +1,73 @@
package com.xscm.moduleutil.bean
import com.chad.library.adapter.base.entity.MultiItemEntity
import lombok.Data
import java.util.ArrayList
/**
* 项目名称:羽声语音
* 时间2025/11/20 15:13
* 用途:心动空间中的关系实体
*/
@Data
class RelationBean : MultiItemEntity {
var cp: UserInfo.CpInfo = UserInfo.CpInfo()
var no_cp: List<NoCpBean> = ArrayList()
override fun getItemType(): Int {
// 情况3no_cp集合relation_name不等于""并且relation_list的大小是1
if (no_cp.isNotEmpty() && no_cp[0].relation_name.isNotEmpty() && no_cp[0].relation_list.size == 1) {
return 3
}
// 情况4no_cp集合relation_list的大小是1
if (no_cp.isNotEmpty() && no_cp[0].relation_list.size == 1) {
return 4
}
if (no_cp.isNotEmpty() && no_cp[0].relation_name.isNotEmpty() && no_cp[0].relation_list.size > 1){
return 5
}
// 其他情况返回5
return 6
}
class NoCpBean : MultiItemEntity{
var relation_name: String = ""
var relation_list: List<RelationshipBean> = ArrayList()
override fun getItemType(): Int {
return 0
}
}
/*"cp": [
{
"relation_name": "string",
"relation_list": [
{
"nickname1": "string",
"avatar1": "string",
"user_id1": "string"
}
]
}
],
"no_cp": [
{
"relation_name": "string",
"relation_list": [
{
"user_info1": {},
"user_info2": "string",
"level": "string",
"exp": "string"
}
]
}
]
}*/
}

View File

@@ -1,5 +1,7 @@
package com.xscm.moduleutil.bean;
import com.chad.library.adapter.base.entity.MultiItemEntity;
import java.io.Serializable;
import lombok.Data;
@@ -10,7 +12,7 @@ import lombok.Data;
* @description: 关系信息
*/
@Data
public class RelationshipBean implements Serializable {
public class RelationshipBean implements Serializable, MultiItemEntity {
private int relation_id;//关系id 3,
@@ -31,4 +33,14 @@ public class RelationshipBean implements Serializable {
private int heart_value;// 0,
private int is_top;// 0
private int type;// 1,亲密2真爱
private int sex1;//1女 2
private int sex2;//
private String dress1;//
private String dress2;//
@Override
public int getItemType() {
return 0;
}
}

View File

@@ -0,0 +1,38 @@
package com.xscm.moduleutil.bean;
import com.xscm.moduleutil.BaseEvent;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 送礼后的成功回调
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class RoomGiftData extends BaseEvent {
private int gift_total;
private List<GiftUserData> gift_user_data;
private CpType cp_type;
@Data
public static class GiftUserData {
private String user_id;//受理人id
private String gift_price;//礼物价格
}
@Data
public static class CpType {
private int cp_type;//0不处理 1表明心意 2组成cp
private String text;//发送方弹起的信息
private String text1;//接收方弹起的信息
private int gift_id;//礼物id
}
}

View File

@@ -1,14 +1,17 @@
package com.xscm.moduleutil.bean;
import com.xscm.moduleutil.BaseEvent;
import com.xscm.moduleutil.bean.blindboxwheel.BlindBoxBean;
import com.xscm.moduleutil.bean.room.*;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class RoomMessageEvent {
public class RoomMessageEvent extends BaseEvent {
private int MsgType; // 消息类型,如 QXRoomMessageTypeJoin
private String RoomId; // 房间 ID
private T Text; // 携带的数据对象
@@ -50,7 +53,7 @@ public class RoomMessageEvent {
private String AcceptRoomId;//接收者所在的房间id
private String PkId;
private String room_id;//当type==1的时候。这个roomId是对方的房间id
private String user_id="";
private String user_id = "";
private String pk_end_times;//pk结束时间
private List<RoomPitBean> userCharmList;
@@ -64,11 +67,11 @@ public class RoomMessageEvent {
private String victory_cover;//胜利的头像
private String defeated_name;//输掉的名称
private String defeated_cover;//输掉的头像
private String end_time;//惩罚时间 /// 在交友房中,是倒计时时间
private String end_time;//惩罚时间 /// 在交友房中,是倒计时时间 //签约房倒计时
private int is_mute;//1静音对方 0不静音对方
private int is_mute_pit;
private int count;//排麦模式下的人数
private int step ; //1:等待邂逅 2心动连线 3牵手良缘
private int step; //1:等待邂逅 2心动连线 3牵手良缘
private int friend_id; //场次id
// private List<FriendInfo.HeartList> list;//交友心动值发生变化
private List<UserInfo> list;//交友房麦位发生变化 //推送的事麦上用户信息这里使用了userinfo接收的
@@ -97,12 +100,24 @@ public class RoomMessageEvent {
private EmotionDeatils emoji;
private String is_pk;//是否是pk
private SingerInfo.SongInfo song_info;
private SingerInfo.SongInfo next_song_info;
private String rights_icon;//Cp特效
private String sign_id = "-1";//签约ID
private String sign_value;//签约最高价
private String sign_day;//被签约天数
private String current_body_value;//被签约身价
}
@Data
public static class text {
private long position;
private int is_mute;
private RoomGiftData.CpType cp_type;
}
}

View File

@@ -34,6 +34,8 @@ public class RoonGiftModel {
private int activities_id;//4盲盒 5天空之境
private int gift_bag;//10天空之境 11岁月之城 12时空之巅
private int is_lock;//爵位礼物 0不锁 1
private int is_cp;//1:是 0不是
public boolean isCan_send_self() {
if ( isManghe()) {
return true;

View File

@@ -0,0 +1,21 @@
package com.xscm.moduleutil.bean
import java.io.Serializable
class SignInfo : Serializable {
/* sign_id
// 0 未开始 1进行中
sign_status;
// 签约天数
sign_day;
// 当前身价
current_body_value;
// 倒计时 时间戳
end_time;*/
var sign_id: String = ""
var sign_status: Int = 0
var sign_day: Int = 0
var current_body_value: Int = 0
var end_time: Long = 0
}

View File

@@ -0,0 +1,54 @@
package com.xscm.moduleutil.bean;
import java.io.Serializable;
import lombok.Data;
@Data
public class SingerInfo implements Serializable {
private static final long serialVersionUID = 1L;
private SongInfo song_info;
private SongInfo next_song_info;
@Data
public static class SongInfo implements Serializable{
private static final long serialVersionUID = 1L;
/*"id": 29,
"room_id": 6001,
"user_id": 20001,
"singer_song_id": 9,
"status": 1,
"sort": 0,
"createtime": 1763435086,
"boss_user_id": 20001,
"boss_nickname": "高兴的小海腾",
"boss_avatar": "https://yusheng-1369267578.cos.ap-guangzhou.myqcloud.com/images/ios_images/1761615690733.jpeg",
"boss_dress": "",
"boss_mic_cycle": "https://cos.xscmmidi.site/admin/ripple3695_17627709565119.svga",
"singer_user_id": 20000,
"singer_nickname": "坚定的故事",
"singer_avatar": "https://yusheng-1369267578.cos.ap-guangzhou.myqcloud.com/images/android_images/4ead5077435f1da7b8aae1a878bb5ac9.jpg",
"singer_dress": "",
"singer_mic_cycle": "https://cos.xscmmidi.site/admin/ripple3695_17627709565119.svga",
"song_name": "公敌"*/
private int id = 0;
private int room_id = 0;
private int user_id = 0;
private int singer_song_id = 0;
private int status = 0;
private int sort = 0;
private long createtime = 0;
private int boss_user_id = 0;
private String boss_nickname = "";
private String boss_avatar = "";
private String boss_dress = "";
private String boss_mic_cycle = "";
private int singer_user_id = 0;
private String singer_nickname = "";
private String singer_avatar = "";
private String singer_dress = "";
private String singer_mic_cycle = "";
private String song_name = "";
}
}

View File

@@ -0,0 +1,40 @@
package com.xscm.moduleutil.bean
/**
* SingerSongCount 类,用于存储歌手和歌曲数量信息
* 这个类可能用于统计或展示每位歌手的歌曲数量
*/
class SingerSongCount {
// 类定义结束,这里可以添加属性和方法来存储和操作歌手及其歌曲数量
var total: Int = 0
var today: Int = 0
var yesterday: Int = 0
var week: Int = 0
var month: Int = 0
var already: Int = 0
/* total
string
总数
必需
today
string
今天
必需
yesterday
string
昨天
必需
week
string
本周
必需
month
string
本月
必需
already
string
已点*/
}

View File

@@ -0,0 +1,67 @@
package com.xscm.moduleutil.bean
class SongPlaylist {
var count: Int = 0
var lists: List<SongPlaylistBean> = ArrayList()
class SongPlaylistBean {
var id: Int = 0
var room_id :String =""
var user_id: String = ""
var singer_song_id: String = ""
var status:String =""
var sort: Int = 0
var boss_nickname: String = ""
var song_name: String = ""
var gift_id: String = ""
var gift_num: String = ""
var createtime: String = ""
var gift_name: String = ""
var gift_price: String = ""
var base_image: String = ""
var singer_nickname: String = ""
}
/* id
string 列表ID
user_id
string
歌手ID
song_name
string
歌曲名
gift_id
string
礼物ID
gift_num
string
礼物数量
createtime
string
添加时间
gift_name
string
礼物名称
gift_price
string
礼物价格
base_image
string
礼物图片
nickname
string
歌手昵称*/
}

View File

@@ -1,5 +1,6 @@
package com.xscm.moduleutil.bean;
import com.chad.library.adapter.base.entity.MultiItemEntity;
import com.google.gson.annotations.SerializedName;
import com.xscm.moduleutil.BaseEvent;
import com.xscm.moduleutil.bean.room.FriendInfo;
@@ -11,9 +12,9 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*@author qx
*@data 2025/6/3
*@description: 个人信息,点击我的获取
* @author qx
* @data 2025/6/3
* @description: 个人信息,点击我的获取
*/
@EqualsAndHashCode(callSuper = true)
@Data
@@ -38,7 +39,7 @@ public class UserInfo extends BaseEvent implements Serializable {
private int is_in_pit;//是否在麦上1在0不在
private int is_open_live_remind;//是否设置开播提醒
private String birthday;//生日
private String profile;//简介
private String profile = "";//简介
private String home_bgimages;//背景图片
private int is_follow;//是否关注
private List<UserTagBean> tag_list;
@@ -49,7 +50,7 @@ public class UserInfo extends BaseEvent implements Serializable {
private String chat_bubble;//聊天气泡
private String charm;//魅力值
private String room_id;
private String guild;//公会名称
private String guild = "";//公会名称
private String is_mute;//禁言状态 0否 1是
private String is_mute_pit;//禁麦状态 0否 1是
private String is_manager;//是否是管理员 0否 1是
@@ -76,12 +77,95 @@ public class UserInfo extends BaseEvent implements Serializable {
private String nickname_color = "";//昵称颜色
private String mic_cycle;//麦圈
private String is_hide;//0不能设置1可以设置
private String hide_status;//0-取消隐身1-设置隐身
private String hide_status;//0-取消隐身1-设置隐身
private String enter_image;//爵位飘屏的背景
private String enter_text;//爵位飘屏的文字
private int singer_status;//歌手认证状态0-待审核1-通过2-拒绝 -1未认证
private int singer_level;//歌手等级
private CpInfo cp_info;
private int market_value;//身价
private String market_value_coin="";//身价配置 多少金币数
private String market_value_market="";//身价配置 多少身价数
private String sign_value;
private String sign_id;
private Master master;
private int is_online;//是否在线 : 1在线 2离线
@Data
public static class Master implements Serializable {
private String user_id;
private String nickname;
private String avatar;
}
/*"cp_info": {
"name": "string",
"user_id1": "string",
"user_id2": "string",
"level": "string",
"exp": "string",
"pendant": "string",
"direction": "string",
}*/
@Data
public static class CpInfo implements Serializable, MultiItemEntity {
private int id;
private int user_id1;
private int user_id2;
private int status;
private long createtime;
public String name = "-1";
public String level = "-1";
public String exp = "-1";
public String pendant = "-1";
public String direction = "-1";
public UserInfo1 user_info1;
public UserInfo2 user_info2;
@Override
public int getItemType() {
if (name != null && !name.isEmpty()) {
return 1;
}
return 2;
}
@Data
public static class UserInfo1 implements Serializable {
public String user_id;
public String nickname;
public String avatar;
public String dress;
}
@Data
public static class UserInfo2 implements Serializable {
public String user_id;
public String nickname;
public String avatar;
public String dress;
}
/*"user_info1": {
"user_id": "string",
"nickname": "string",
"avatar": "string",
"dress": "string"
},
"user_info2": {
"user_id": "string",
"nickname": "string",
"avatar": "string",
"dress": "string"
}*/
}
// @Data
// public static class TagList{
@@ -89,13 +173,14 @@ public class UserInfo extends BaseEvent implements Serializable {
// private String tag_name;
// }
@Data
public static class GiftWall {
public static class GiftWall implements Serializable {
private String gift_name;
private String total;
private List<SendUserInfo> send_user_info;
@Data
public static class SendUserInfo{
public static class SendUserInfo implements Serializable {
private String nickname;
private String avatar;
}

View File

@@ -72,23 +72,26 @@ public class EMMessageInfo implements MultiItemEntity {
public static final int QXRoomMessageTypeRoomPKEnd = 1032;
/// pk断开
public static final int QXRoomMessageTypeRoomPKDisconnect = 1033;
///排麦模式下的人数变化
/// 排麦模式下的人数变化
public static final int QXRoomMessageTypeRoomMaiwrens = 1034;
public static final int QXRoomMessageTypeRoomDress = 1035;//动态修改用户头像信息
public static final int QXRoomMessageTypeRoomOnline = 1036;//
public static final int QXRoomMessageTypeRoomOPK = 1037;
public static final int QXRoomMessageTypeRoomOMh = 1038;
///清除当前消息列表
/// 清除当前消息列表
public static final int QXRoomMessageTypeClearMsg = 123;
///播放音乐
/// 播放音乐
public static final int QXRoomMessageTypeRoomMusicPlay = 124;
///关闭对方麦克风
/// 关闭对方麦克风
public static final int QXRoomMessageTypeMuteRemoteAudio = 125;
///小黑屋 关麦
/// 小黑屋 关麦
public static final int QXRoomMessageTypeMuteLocalAudio = 126;
public static final int QXRoomMessageTypeCPDx = 130;//心动礼物,单向发送
public static final int QXRoomMessageTypeCPSx = 131;//心动礼物,双向发送
/// 交友房阶段发生变化
public static final int QXRoomMessageTypeRoomFriendPartDidChanged = 1049;
@@ -104,22 +107,46 @@ public class EMMessageInfo implements MultiItemEntity {
public static final int QXRoomMessageTypeHeartDidChanged = 1054;
/// 小黑屋有人退出房间
public static final int QXRoomMessageTypeHeartDid = 1055;
///盲盒抽奖进度条
/// 盲盒抽奖进度条
public static final int QXRoomMessageTypeMangH = 1056;
///巡乐会
/// 巡乐会
public static final int QXRoomMessageTypeXlh = 1057;
///在离线
/// 在离线
public static final int QXRoomMessageTypezailx = 1058;
///清除个人魅力值
/// 清除个人魅力值
public static final int QXRoomMessageTypeQingGRMl = 1059;
///有红包列表
/// 有红包列表
public static final int QXRoomMessageTypeQXRoomMessageRed = 1060;
///移除红包
/// 移除红包
public static final int QXRoomMessageTypeQXRoomMessageRedRemove = 1061;
///房间内换麦
public static final int QXRoomMessageTypehm = 1039;
/// 点歌房当前歌曲发生变化
public static final int QXRoomMessageTypeSingerRoomCurrentSongDidChanged = 1070;
/// 点歌房下一首歌曲发生变化
public static final int QXRoomMessageTypeSingerRoomNextSongDidChanged = 1071;
//已点歌曲数量
public static final int QXRoomMessageTypeSongerNum = 1072;
/// 房间内换麦
public static final int QXRoomMessageTypehm = 1039;
public static final int QXRoomMessageTypeCPText = 1080;//CP特效进入房间的特效
/// 签约开始
public static final int QXRoomMessageTypeSignStartText = 1090;
/// 签约出价 FromUserInfo 出价最高用户信息sign_value出的价sign_id场次
public static final int QXRoomMessageTypeSignMaxUserText = 1091;
/**
* 签约结束
* FromUserInfo出价用户信息
* ToUserInfo被签用户信息
* sign_value出的最高价
*/
public static final int QXRoomMessageTypeSignEndText = 1092;
/// 延时到这个时间点
public static final int QXRoomMessageTypeSignDelayText = 1093;
private RoomMessageEvent emMessage;

View File

@@ -40,6 +40,7 @@ public class RoomAuction implements Serializable {
private String nobility_image;//贵族图标
private String nickname_color;//昵称颜色
private String mic_cycle;//麦圈
private int is_online=1;//是否在线 : 1在线 2离线
}
@Data

View File

@@ -75,7 +75,7 @@ public class RoomBean implements Serializable {
private String room_name;//房间名称
private String room_cover;//房间封面
private String room_intro;//房间公告
private String type_id;//房间类型 1:点唱(pk) 2拍卖真爱拍小黑屋 3/4交友 6小黑屋 7:互娱 8交友
private String type_id;//房间类型 1:点唱(pk) 2拍卖真爱拍小黑屋 3/4交友 6小黑屋 7:互娱 8交友 10:签约
private String type_name;//房间类型名称
private String user_id;//房主id
private String label_id;//类型id 2:ktv type:1/3/4/8

View File

@@ -6,6 +6,9 @@ import java.io.Serializable;
import java.util.List;
import com.xscm.moduleutil.bean.NobilitDeatils;
import com.xscm.moduleutil.bean.SignInfo;
import com.xscm.moduleutil.bean.SingerInfo;
import lombok.Data;
/**
@@ -34,6 +37,11 @@ public class RoomInfoResp implements Serializable {
private int hour_ranking_open;//1:开启 0关闭
private NobilitDeatils.NobilityInfo nobility_info;
private SingerInfo singer_info;
private SignInfo sign_info;
private String room_id="";
private String msg="";
//弹出麦位操作弹出
public boolean isWheatManager() {

View File

@@ -37,7 +37,7 @@ public class RoomPitBean implements Serializable {
}
private String id;//id
private String pit_number = "";//麦位号
private String pit_number="";//麦位号
private String state;//麦位状态 正常 1封麦3禁麦
private int is_lock;//0未锁麦 1锁麦
private int is_mute;//0未禁麦 1禁麦
@@ -64,7 +64,7 @@ public class RoomPitBean implements Serializable {
private String dress_picture;
private RankInfo rank_info;
private int ball_state;//1开球0未开球
private int is_online;//是否在线 : 1在线 2离线
private int is_online=1;//是否在线 : 1在线 2离线
private String to_pit_number;
private boolean is_pk;//是否是在pk模式中
private boolean isMute;//是否打开麦圈
@@ -77,4 +77,8 @@ public class RoomPitBean implements Serializable {
private String nickname_color;//昵称颜色
private String mic_cycle;//麦圈
private boolean occupied;
private boolean imageType;//是否是演唱者
}

View File

@@ -16,12 +16,14 @@ public class RoomSettingBean implements MultiItemEntity {
public static final int QXRoomSettingTypeRoomTypeBoy = 12;
/// 女神房
public static final int QXRoomSettingTypeRoomTypeGirl = 13;
///交友 房
/// 交友 房
public static final int QXRoomSettingTypeRoomTypeJiaoy = 27;
//互娱
public static final int QXRoomSettingTypeRoomTypeHUYU = 28;
//练歌房
public static final int QXRoomSettingTypeRoomTypeLianG = 31;
//签约
public static final int QXRoomSettingTypeRoomTypeSIGNCONTRACT = 32;
/// 常用工具
/// 房间补贴
@@ -70,7 +72,7 @@ public class RoomSettingBean implements MultiItemEntity {
private boolean select;//是否选中
public RoomSettingBean(String name, String icon, String selectName, String selectIcon, int type, int read, boolean isSelected, boolean status,boolean select) {
public RoomSettingBean(String name, String icon, String selectName, String selectIcon, int type, int read, boolean isSelected, boolean status, boolean select) {
this.name = name;
this.icon = icon;
this.selectName = selectName;
@@ -86,6 +88,7 @@ public class RoomSettingBean implements MultiItemEntity {
public int getItemType() {
return itemType;
}
public void updateItemType() {
if (type == -1) { // 特殊值表示标题
this.itemType = ITEM_TYPE_DEFAULT;

View File

@@ -28,7 +28,7 @@ public class RoomUserBean implements Serializable {
private String avatar;//用户头像
private String dress;//头像装扮
private int is_room_owner;//是否是房主1是0不是
private int pit_number;//麦位号,如果在麦位上就返回值
private int pit_number = 0;//麦位号,如果在麦位上就返回值
private String state;//麦位状态如果在麦位撒好难过就有返回值正常1封麦3禁麦
private String count_down;//麦位倒计时,在麦位上就有返回值,禁麦倒计时
private int is_collect;//是否收藏1是0没有

View File

@@ -15,11 +15,13 @@ public class ZhuangBanShangChengBean {
private String is_perpetual;
private String special_num ;//靓号
private String title ;//装扮名称
private String type ;//类型,顶部的头部选择
private String type="" ;//类型,顶部的头部选择
private String remaining_day ;//价格
private String base_image ;//显示图片
private String play_image;//播放图像
private boolean is_select = false;
private int num ;//数量
private String ext_value="" ;//这是使用降身卡的时候返回的参数对应的是降身卡的前面类似10%
public boolean isIs_select() {
return is_select;

View File

@@ -0,0 +1,160 @@
package com.xscm.moduleutil.dialog;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.color.ThemeableDrawableUtils;
import com.xscm.moduleutil.utils.ColorManager;
public class BaseCpDialog extends Dialog {
private String title;
private String message;
private String positiveButtonText;
private String negativeButtonText;
private View.OnClickListener positiveButtonClickListener;
private View.OnClickListener negativeButtonClickListener;
private boolean isCountdownEnabled = false; // 是否启用倒计时
private int countdownSeconds = 0; // 倒计时秒数
private CountDownTimer countDownTimer; // 倒计时对象
public BaseCpDialog(Context context, String title, String message,
String positiveButtonText, String negativeButtonText,
View.OnClickListener positiveButtonClickListener,
View.OnClickListener negativeButtonClickListener,
boolean isCountdownEnabled, int countdownSeconds) {
super(context);
this.title = title;
this.message = message;
this.positiveButtonText = positiveButtonText;
this.negativeButtonText = negativeButtonText;
this.positiveButtonClickListener = positiveButtonClickListener;
this.negativeButtonClickListener = negativeButtonClickListener;
this.isCountdownEnabled = isCountdownEnabled;
this.countdownSeconds = countdownSeconds;
}
private void init() {
Window window = getWindow();
if (window != null) {
window.setGravity(Gravity.CENTER); // 居中显示
window.setBackgroundDrawableResource(R.drawable.bg_r16_fff); // 透明背景
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_confirm);
init();
// 动态设置背景
// getWindow().setBackgroundDrawableResource(R.drawable.bg_r16_fff);
// 初始化视图
TextView tvTitle = findViewById(R.id.tv_title);
TextView tvMessage = findViewById(R.id.tv_message);
Button btnPositive = findViewById(R.id.btn_positive);
Button btnNegative = findViewById(R.id.btn_negative);
@SuppressLint({"MissingInflatedId", "LocalSuppress"})
ConstraintLayout rootView =(ConstraintLayout) findViewById(R.id.root_view);
// 设置文本
tvTitle.setText(title);
tvMessage.setText(message);
btnPositive.setText(positiveButtonText);
btnNegative.setText(negativeButtonText);
// 设置点击监听器
btnPositive.setOnClickListener(v -> {
isCountdownCancelled = true; // 标记倒计时被取消
if (countDownTimer != null) {
countDownTimer.cancel(); // 取消倒计时
countDownTimer = null;
}
if (positiveButtonClickListener != null) {
positiveButtonClickListener.onClick(v);
}
dismiss();
});
// 判断是否需要显示取消按钮
if (negativeButtonText != null && !negativeButtonText.isEmpty()) {
btnNegative.setText(negativeButtonText);
btnNegative.setVisibility(View.VISIBLE);
btnNegative.setOnClickListener(v -> {
if (negativeButtonClickListener != null) {
negativeButtonClickListener.onClick(v);
}
dismiss();
});
// 倒计时逻辑
if (isCountdownEnabled && countdownSeconds > 0) {
startCountdown(btnNegative);
}
} else {
// 隐藏取消按钮
btnNegative.setVisibility(View.GONE);
}
// 倒计时逻辑
if (isCountdownEnabled && countdownSeconds > 0) {
startCountdown(btnNegative);
}
ThemeableDrawableUtils.setThemeableRoundedBackground(btnPositive, ColorManager.getInstance().getPrimaryColorInt(), 53);
btnPositive.setTextColor(ColorManager.getInstance().getButtonColorInt());
// 找到根布局并应用动画
// if (rootView != null) {
// Animation slideDown = AnimationUtils.loadAnimation(context, R.anim.slide_down);
// Animation shake = AnimationUtils.loadAnimation(context, R.anim.shake);
//
// rootView.startAnimation(slideDown);
// rootView.startAnimation(shake);
// }
}
private boolean isCountdownCancelled = false; // 添加标志位
private void startCountdown(Button btnNegative) {
countDownTimer = new CountDownTimer(countdownSeconds * 1000L, 1000) {
@Override
public void onTick(long millisUntilFinished) {
int secondsLeft = (int) (millisUntilFinished / 1000);
btnNegative.setText(negativeButtonText + " (" + secondsLeft + "s)");
}
@Override
public void onFinish() {
// 检查是否被主动取消
if (!isCountdownCancelled) {
btnNegative.setText(negativeButtonText);
if (negativeButtonClickListener != null) {
negativeButtonClickListener.onClick(btnNegative); // 自动触发取消
}
dismiss();
}
}
}.start();
}
@Override
public void dismiss() {
if (countDownTimer != null) {
countDownTimer.cancel(); // 取消倒计时
countDownTimer = null;
}
super.dismiss();
}
}

View File

@@ -9,6 +9,7 @@ import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.text.SpannableString;
import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout;
@@ -26,6 +27,7 @@ public class ConfirmDialog extends Dialog {
private String title;
private String message;
private SpannableString spannableMessage;
private String positiveButtonText;
private String negativeButtonText;
private View.OnClickListener positiveButtonClickListener;
@@ -51,6 +53,23 @@ public class ConfirmDialog extends Dialog {
this.countdownSeconds = countdownSeconds;
}
// 新增构造函数支持SpannableString
public ConfirmDialog(Context context, String title, SpannableString spannableMessage,
String positiveButtonText, String negativeButtonText,
View.OnClickListener positiveButtonClickListener,
View.OnClickListener negativeButtonClickListener,
boolean isCountdownEnabled, int countdownSeconds) {
super(context);
this.title = title;
this.spannableMessage = spannableMessage;
this.positiveButtonText = positiveButtonText;
this.negativeButtonText = negativeButtonText;
this.positiveButtonClickListener = positiveButtonClickListener;
this.negativeButtonClickListener = negativeButtonClickListener;
this.isCountdownEnabled = isCountdownEnabled;
this.countdownSeconds = countdownSeconds;
}
private void init() {
Window window = getWindow();
if (window != null) {
@@ -76,7 +95,12 @@ public class ConfirmDialog extends Dialog {
// 设置文本
tvTitle.setText(title);
tvMessage.setText(message);
// 根据是否有spannableMessage来设置不同的文本
if (spannableMessage != null) {
tvMessage.setText(spannableMessage);
} else {
tvMessage.setText(message);
}
btnPositive.setText(positiveButtonText);
btnNegative.setText(negativeButtonText);
@@ -113,6 +137,15 @@ public class ConfirmDialog extends Dialog {
// 隐藏取消按钮
btnNegative.setVisibility(View.GONE);
}
//判断是否需要显示确认按钮
if (positiveButtonText != null && !positiveButtonText.isEmpty()) {
btnPositive.setText(positiveButtonText);
btnPositive.setVisibility(View.VISIBLE);
}else {
// 隐藏确认按钮
btnPositive.setVisibility(View.GONE);
}
// 倒计时逻辑
if (isCountdownEnabled && countdownSeconds > 0) {
startCountdown(btnNegative);

View File

@@ -17,8 +17,15 @@ public enum QXRoomSeatViewType {
* 拍卖麦位
*/
AUCTION(2, "拍卖麦位"),
/**
* 点唱
*/
JUKEBOX(9,"点唱麦位"),
/**
* 签约
*/
SIGNCONTRACT(10,"签约"),
/**
* 小黑屋麦位
@@ -30,6 +37,8 @@ public enum QXRoomSeatViewType {
*/
FRIEND(7, "交友房麦位");
private final int value;
private final String description;

View File

@@ -14,7 +14,10 @@ enum class RoomType(
AUCTION("拍卖(真爱拍小黑屋)", 2),
DATING("交友", 1,3, 4, 8), // 1、3、4、8 均对应交友
BLACK_ROOM("小黑屋", 6),
MUTUAL_ENTERTAINMENT("互娱", 7);
JUKEBOX("点唱", 9),
MUTUAL_ENTERTAINMENT("互娱", 7),
SIGN_CONTRACT("签约", 10);
companion object {
/**

View File

@@ -31,6 +31,4 @@ public class RoomGiftGiveEvent extends BaseEvent {
this.heart_id = heart_id;
this.auction_id = auction_id;
}
}

View File

@@ -34,7 +34,8 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.ROOM_HOUR_BEAN)
Call<BaseModel<RoomHourBean>> getRoomHourRanking(@Field("page") String page,@Field("page_limit")String page_limit);
Call<BaseModel<RoomHourBean>> getRoomHourRanking(@Field("page") String page, @Field("page_limit") String page_limit);
@FormUrlEncoded //手机换绑
@POST(Constants.MODIFY_MOBILE)
Call<BaseModel<String>> mobileView(@Field("mobile") String mobile, @Field("new_mobile") String new_mobile, @Field("sms_code") String sms_code);
@@ -43,7 +44,7 @@ public interface ApiServer {
Call<BaseModel<List<Emotion>>> upEmotion();
@GET(Constants.GET_EMOTION_DEATILS)
Call<BaseModel<List<EmotionDeatils>>> getEmotionDeatils(@Query("type_id") String type_id,@Query("pid") String pid);
Call<BaseModel<List<EmotionDeatils>>> getEmotionDeatils(@Query("type_id") String type_id, @Query("pid") String pid);
@FormUrlEncoded //手机绑定
@POST(Constants.BIND_MOBILE)
@@ -51,7 +52,7 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.USER_ROOM_BACK)
Call<ResponseBody> userRoomBack(@Field("room_id")String room_id,@Field("type")String type);
Call<ResponseBody> userRoomBack(@Field("room_id") String room_id, @Field("type") String type);
@FormUrlEncoded
@POST(Constants.USER_LOGIN)
@@ -125,9 +126,53 @@ public interface ApiServer {
@POST(Constants.POST_MESSAGE_LIST)
Call<BaseModel<List<NewsMessageList>>> getMessagetitle(@Field("type") String type, @Field("page") String page, @Field("page_limit") String page_limit);
@FormUrlEncoded
@POST(Constants.POST_INVITE)
Call<BaseModel<String>> postInvite(@Field("apply_id") String apply_id, @Field("type") String type);
@GET(Constants.GET_TEMP_KEY)
Call<BaseModel<TempKeyBean>> getTempKey();
@FormUrlEncoded
@POST(Constants.POST_SINGER_AUTH)
Call<BaseModel<String>> singerAuth(@Field("song") String song);
@FormUrlEncoded
@POST(Constants.POST_GET_SONG)
Call<BaseModel<SongPlaylist>> getSong(@Field("user_id") String user_id, @Field("room_id") String room_id, @Field("page") String page, @Field("page_limit") String page_limit);
@FormUrlEncoded
@POST(Constants.POST_SINGER_SONG_CUT)
Call<BaseModel<String>> singerSongCut(@Field("id") String id);
@FormUrlEncoded
@POST(Constants.POST_SINGER_SONG_TOP)
Call<BaseModel<String>> singerSongTop(@Field("id") String id);
@FormUrlEncoded
@POST(Constants.POST_SINGER_SONG_COUNT)
Call<BaseModel<SingerSongCount>> singerSongCount(@Field("room_id") String room_id);
@FormUrlEncoded
@POST(Constants.POST_SINGER_SONG)
Call<BaseModel<String>> singerSong(@Field("song_id") String song_id, @Field("room_id") String room_id);
@FormUrlEncoded
@POST(Constants.POST_SINGER_SONG_LIST)
Call<BaseModel<SongPlaylist>> singerSongList(@Field("room_id") String room_id, @Field("type") String type, @Field("page") String page, @Field("page_limit") String page_limit);
@FormUrlEncoded
@POST(Constants.POST_SINGER_DELETE_SONG)
Call<BaseModel<String>> deleteSong(@Field("id") String song_id);
@FormUrlEncoded
@POST(Constants.POST_SINGER_ADD_SONG)
Call<BaseModel<String>> singerAddSong(@Field("song_name") String song_name, @Field("gift_id") String gift_id, @Field("gift_num") String gift_num);
@FormUrlEncoded
@POST(Constants.POST_SINGER_UPDATE_SONG)
Call<BaseModel<String>> singerUpdateSong(@Field("id") String is, @Field("song_name") String song_name, @Field("gift_id") String gift_id, @Field("gift_num") String gift_num);
@FormUrlEncoded
@POST(Constants.POST_ROOM_RANK)
Call<BaseModel<List<CharmRankingResp>>> getRoomRank(@Field("room_id") String room_id, @Field("type") String type, @Field("time_type") String time_type, @Field("page") String page, @Field("page_limit") String page_limit);
@@ -290,9 +335,10 @@ public interface ApiServer {
//获取礼物列表
@GET(Constants.GIFT_LIST)
Call<BaseModel<List<RoonGiftModel>>> getGiftList(@Query("label") int label,@Query("room_id")String room_id);
Call<BaseModel<List<RoonGiftModel>>> getGiftList(@Query("label") int label, @Query("room_id") String room_id);
@GET(Constants.TOPIC_LIST)//获取话题
@GET(Constants.TOPIC_LIST)
//获取话题
Call<BaseModel<List<HeatedBean>>> topicList(@Query("page") String page, @Query("page_limit") String page_limit);
@FormUrlEncoded
@@ -345,6 +391,10 @@ public interface ApiServer {
Call<BaseModel<String>> commentZone(@Field("id") String id, @Field("content") String content, @Field("pid") String pid, @Field("reply_to") String reply_to);
@FormUrlEncoded
@POST(Constants.POST_FRIEND_LIST)
Call<BaseModel<RelationBean>> getFriendList(@Field("user_id") String user_id, @Field("page") String page, @Field("page_limit") String page_limit);
@GET(Constants.GET_MY_CP_ROOM_LIST)
Call<BaseModel<List<MyCpRoom>>> myCpRoom();
@@ -475,10 +525,15 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.GET_ROOM_GIFT)
Call<BaseModel<String>> roomGift(@Field("room_id") String room_id, @Field("gift_id") String gift_id, @Field("gift_num") String num, @Field("to_uid") String to_uid, @Field("type") String gift_type, @Field("pit_number") String pit_number, @Field("heart_id") String heat_id);
Call<BaseModel<RoomGiftData>> roomGift(@Field("room_id") String room_id, @Field("gift_id") String gift_id, @Field("gift_num") String num, @Field("to_uid") String to_uid, @Field("type") String gift_type, @Field("pit_number") String pit_number, @Field("heart_id") String heat_id);
@FormUrlEncoded
@POST(Constants.POST_CP_GIVE_GIFT)
Call<BaseModel<RoomGiftData>> cpGiveGift(@Field("user_id") String user_id, @Field("gift_id") String gift_id, @Field("room_id") String room_id);
@GET(Constants.GET_FIRST_CHARGE_GIFT)
Call<BaseModel<FirstChargeGiftBean>> firstChargeGift();
@GET(Constants.GET_NEW_CHARGE_GIFT)
Call<BaseModel<FirstChargeGiftBean>> getNewChargeGift();
@@ -494,8 +549,8 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.REDPACKET_CREATE)
Call<ResponseBody> redPacketCreate(@Field("type") int type, @Field("password") String password, @Field("coin_type") int coin_type, @Field("total_amount") String total_amount,
@Field("total_count")String total_count, @Field("conditions") String conditions, @Field("countdown") String countdown, @Field("room_id") String room_id,
@Field("remark") String remark);
@Field("total_count") String total_count, @Field("conditions") String conditions, @Field("countdown") String countdown, @Field("room_id") String room_id,
@Field("remark") String remark);
@GET(Constants.ROOM_REDPACKET)
Call<BaseModel<List<RedPacketInfo>>> roomRedPackets(@Query("room_id") String roomId);
@@ -540,7 +595,7 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.POST_SONG_LIST)
Call<BaseModel<List<MusicSongBean>>> songList(@Field("room_id") String room_id);
Call<BaseModel<List<MusicSongBean>>> songList(@Field("room_id") String room_id,@Field("page")String page);
@FormUrlEncoded
@POST(Constants.APPLY_PIT)
@@ -562,8 +617,9 @@ public interface ApiServer {
@POST(Constants.DELAY)
Call<BaseModel<String>> delay(@Field("friend_id") String friend_id, @Field("room_id") String room_id, @Field("delay_times") String delay_times);
@FormUrlEncoded
@POST(Constants.POST_KEEP_XINTIAO)
Call<ResponseBody> keepXintiao();
Call<ResponseBody> keepXintiao(@Field("room_id") String room_id);
@FormUrlEncoded
@POST(Constants.DOWN_PIT)
@@ -710,6 +766,10 @@ public interface ApiServer {
@POST(Constants.POST_QUIT_ROOM)
Call<ResponseBody> quitRoom(@Field("room_id") String room_id, @Field("user_id") String user_id);
@FormUrlEncoded
@POST(Constants.POST_FRIEND_LIST_MORE)
Call<BaseModel<List<RelationshipBean>>> getFriendListMore(@Field("user_id") String user_id, @Field("relation_id") String relation_id);
@FormUrlEncoded
@POST(Constants.POST_RELATION_CARD)
Call<BaseModel<RelationCardBean>> relationCard(@Field("user_id") String user_id);
@@ -745,17 +805,17 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.POST_DRAW_GIFT_LIST)
Call<BaseModel<BlindReslutBean>> drawGiftList(@Field("gift_bag_id") String gift_bag_id, @Field("gift_user_ids") String gift_user_ids,@Field("room_id")String room_id,@Field("num")String num,@Field("heart_id") String heart_id,@Field("auction_id") String auction_id);
Call<BaseModel<BlindReslutBean>> drawGiftList(@Field("gift_bag_id") String gift_bag_id, @Field("gift_user_ids") String gift_user_ids, @Field("room_id") String room_id, @Field("num") String num, @Field("heart_id") String heart_id, @Field("auction_id") String auction_id);
@GET(Constants.GET_MY_RECORD)
Call<BaseModel<List<GiftBean>>> getMyRecord(@Query("gift_bag_id")String gift_bag_id,@Query("page")String page,@Query("page_size")String page_size);
Call<BaseModel<List<GiftBean>>> getMyRecord(@Query("gift_bag_id") String gift_bag_id, @Query("page") String page, @Query("page_size") String page_size);
@GET(Constants.GET_ALL_RECORD)
Call<BaseModel<List<GiftBean>>> getAllRecord(@Query("gift_bag_id")String gift_bag_id,@Query("page")String page,@Query("page_size")String page_size);
Call<BaseModel<List<GiftBean>>> getAllRecord(@Query("gift_bag_id") String gift_bag_id, @Query("page") String page, @Query("page_size") String page_size);
@FormUrlEncoded
@POST(Constants.GIFT_SEND)
Call<BaseModel<String>> giftSend(@Field("send_id")String send_id);
Call<BaseModel<String>> giftSend(@Field("send_id") String send_id);
@GET(Constants.GET_NOBILITY_DETAIL)
Call<BaseModel<NobilitDeatils>> getNobilityDetail();
@@ -767,10 +827,10 @@ public interface ApiServer {
Call<BaseModel<NobilityPrice>> getNobilityPrice(@Query("id") String id);
@POST(Constants.POST_SEND_LOG)
Call<BaseModel<String>> postSendAppLog(@Query("log_name") String logName,@Query("log_url") String logUrl);
Call<BaseModel<String>> postSendAppLog(@Query("log_name") String logName, @Query("log_url") String logUrl);
@GET(Constants.GET_BOX_GIFT_LIST_XLH)
Call<BaseModel<BlindBoxBean>> getBoxGiftListXLH( @Query("room_id") String room_id);
Call<BaseModel<BlindBoxBean>> getBoxGiftListXLH(@Query("room_id") String room_id);
@FormUrlEncoded
@POST(Constants.POST_DRAW_GIFT_LIST_XLH)
@@ -779,6 +839,7 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.POST_XLH_ALL_RECORD)
Call<BaseModel<List<GiftBean>>> xlhAllRecord(@Field("room_id") String room_id, @Field("page") String page, @Field("page_size") String page_size);
@FormUrlEncoded
@POST(Constants.Get_XH_RANking)
Call<BaseModel<List<GiftBean>>> xlXH_RANking(@Field("room_id") String room_id, @Field("page") String page, @Field("page_size") String page_size);
@@ -788,11 +849,11 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.POST_GIFT_ALL_CLEAR)
Call<BaseModel<String>> getGiftPack(@Field("room_id") String roomId,@Field("to_uid") String user_id,@Field("heart_id") String heart_id,@Field("auction_id") String auction_id);
Call<BaseModel<String>> getGiftPack(@Field("room_id") String roomId, @Field("to_uid") String user_id, @Field("heart_id") String heart_id, @Field("auction_id") String auction_id);
@FormUrlEncoded
@POST(Constants.POST_ROOM_USER_CHARM_LIST)
Call<BaseModel<List<RoomUserCharmListBean>>> roomUserCharmList(@Field("room_id") String roomId,@Field("user_id") String user_id);
Call<BaseModel<List<RoomUserCharmListBean>>> roomUserCharmList(@Field("room_id") String roomId, @Field("user_id") String user_id);
@GET(Constants.GET_GIFT_PACK_LIST_COUNT)
Call<BaseModel<GiftPackListCount>> getGiftPackListCount();
@@ -801,4 +862,47 @@ public interface ApiServer {
@POST(Constants.ROOM_USER_RECONNECT)
Call<BaseModel<String>> roomUserReconnect(@Field("room_id") String room_id);
@GET(Constants.GET_CP_ZONE)
Call<BaseModel<HeartCpBean>> getCpRoom(@Query("user_id") String userId,@Query("page")String page);
@GET(Constants.POST_MY_FAMILY)
Call<BaseModel<MyFamilyBean>> myFamily();
@GET(Constants.POST_MY_JOIN_FAMILY)
Call<BaseModel<MyFamilyBean>> myJoinFamily();
@FormUrlEncoded
@POST(Constants.POST_FAMILY_EARNINGS)
Call<BaseModel<List<FamilyEarnings>>> familyEarnings(@Field("user_id") String user_id, @Field("page") int page, @Field("start_time") String start_time, @Field("end_time") String end_time);
@FormUrlEncoded
@POST(Constants.POST_SIGN_START)
Call<BaseModel<String>> signStart(@Field("room_id") String room_id, @Field("user_id") String user_id);
@FormUrlEncoded
@POST(Constants.POST_SIGN_END)
Call<BaseModel<String>> signEnd(@Field("sign_id") String sign_id);
@FormUrlEncoded
@POST(Constants.POST_SIGN_DELAY)
Call<BaseModel<String>> signDelay(@Field("sign_id") String sign_id, @Field("room_id") String room_id);
@FormUrlEncoded
@POST(Constants.POST_SIGN_COIN_LIST)
Call<BaseModel<List<String>>> signCoinList(@Field("sign_id") String sign_id);
@FormUrlEncoded
@POST(Constants.POST_SIGN_COIN)
Call<BaseModel<String>> signCoin(@Field("sign_id") String sign_id,@Field("sign_value") String sign_value);
@GET(Constants.GET_SKILL_LIST)
Call<BaseModel<List<String>>> skillList();
@FormUrlEncoded
@POST(Constants.POST_FREE_RE_SIGN)
Call<BaseModel<String>> freeReSign(@Field("user_id") String user_id);
@FormUrlEncoded
@POST(Constants.POST_RE_SIGN)
Call<BaseModel<String>> reSign(@Field("user_id") String user_id);
}

View File

@@ -63,8 +63,7 @@ public class BaseModelTypeAdapter<T> extends TypeAdapter<BaseModel<T>> {
model.setData(null);
} else {
// 如果 data 是字符串类型但不是 "null",可根据业务决定是否抛异常或处理
reader.skipValue();
model.setData(null);
model.setData((T)value);
}
} else {
try {

View File

@@ -0,0 +1,21 @@
package com.xscm.moduleutil.listener
import com.xscm.moduleutil.bean.RoomGiftData
import com.xscm.moduleutil.bean.RoomMessageEvent
/**
* 这是cp的监听器方便在各个模块中调用
*/
interface CPListener {
/**
* 发送CP消息的处理函数
* @param gitData 礼物数据信息,包含房间礼物相关的数据
*/
fun onSendCpMsg(gitData: RoomGiftData)
/**
* 接收房间消息事件的处理函数
* @param roomMessageEvent 房间消息事件对象,包含消息相关的所有信息
*/
fun onReceiveMsg(roomMessageEvent: RoomMessageEvent)
}

View File

@@ -15,6 +15,7 @@ import com.xscm.moduleutil.bean.RoomMessageEvent;
import com.xscm.moduleutil.bean.room.EMMessageInfo;
import com.xscm.moduleutil.event.RoomJoinMountModel;
import com.xscm.moduleutil.event.UnreadCountEvent;
import com.xscm.moduleutil.http.RetrofitClient;
import com.xscm.moduleutil.rtc.MusicPlayBean;
import com.xscm.moduleutil.utils.SpUtil;
import com.tencent.imsdk.v2.V2TIMAdvancedMsgListener;
@@ -34,6 +35,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
@@ -91,6 +93,7 @@ public class MessageListenerSingleton {
// 同时修改 removePublicScreenMessageListener 方法
public void removePublicScreenMessageListener(PublicScreenMessageListener listener) {
mRoomId = "";
if (listener == null) {
return;
}
@@ -103,6 +106,7 @@ public class MessageListenerSingleton {
}
}
}
// 修改 notify 方法以增加保护
private void notifyPublicScreenListeners(RoomMessageEvent message) {
synchronized (publicScreenListeners) {
@@ -201,7 +205,8 @@ public class MessageListenerSingleton {
if (TextUtils.isEmpty(roomId)) {
return;
}
if (Objects.equals(mRoomId, roomId))
return;
synchronized (groupOperationLock) {
if (isGroupOperationInProgress) {
// 如果有操作正在进行,延迟执行
@@ -212,12 +217,12 @@ public class MessageListenerSingleton {
isGroupOperationInProgress = true;
}
mRoomId = roomId;
new Thread(() -> {
try {
// 先退出当前群组(如果需要)
if (groupId != null && !groupId.equals(roomId)) {
LogUtils.d("MessageListener", "开始退出群组: " + groupId +"____room:"+ roomId);
LogUtils.d("MessageListener", "开始退出群组: " + groupId + "____room:" + roomId);
CountDownLatch quitLatch = new CountDownLatch(1);
boolean[] quitSuccess = {false};
@@ -225,14 +230,14 @@ public class MessageListenerSingleton {
V2TIMManager.getInstance().quitGroup("room" + groupId, new V2TIMCallback() {
@Override
public void onSuccess() {
LogUtils.d("MessageListener", "退出群组成功: " + groupId+"____room:"+ roomId);
LogUtils.d("MessageListener", "退出群组成功: " + groupId + "____room:" + roomId);
quitSuccess[0] = true;
quitLatch.countDown();
}
@Override
public void onError(int code, String desc) {
LogUtils.e("MessageListener", "退出群组失败: " + groupId +"____room:"+ roomId + ", code=" + code + ", desc=" + desc);
LogUtils.e("MessageListener", "退出群组失败: " + groupId + "____room:" + roomId + ", code=" + code + ", desc=" + desc);
quitSuccess[0] = false;
quitLatch.countDown();
}
@@ -313,7 +318,12 @@ public class MessageListenerSingleton {
LogUtils.d("C2C 自定义(信令)消息 " + sender.getNickName());
String message = new String(customData, StandardCharsets.UTF_8);
RoomMessageEvent event = GsonUtils.fromJson(message, RoomMessageEvent.class);
notifyMessageReceived(event);
if (event.getMsgType() == 130 || event.getMsgType() == 131) {
// EventBus.getDefault().post(event);
RetrofitClient.getInstance().getCpListener().onReceiveMsg(event);
} else {
notifyMessageReceived(event);
}
}
@Override
@@ -390,7 +400,7 @@ public class MessageListenerSingleton {
// 使用默认解析
event = GsonUtils.fromJson(message, RoomMessageEvent.class);
}
LogUtils.e("收到群自定义消息:"+mRoomId+"===" + event);
// event = GsonUtils.fromJson(message, RoomMessageEvent.class);
} catch (Exception e) {
// 处理 JSON 解析过程中可能出现的异常,例如记录日志
@@ -486,7 +496,7 @@ public class MessageListenerSingleton {
if (instance != null) {
instance.listeners.clear();
removeAllListeners();
// removeAllListeners();
isInitialized = false;
groupId = null;
LogUtils.e("@@@", "重置成功");
@@ -497,7 +507,7 @@ public class MessageListenerSingleton {
public static void reset(String roomId) {
if (instance != null) {
instance.listeners.clear();
removeAllListeners();
// removeAllListeners();
isInitialized = false;
groupId = null;
// instance = null;
@@ -508,7 +518,7 @@ public class MessageListenerSingleton {
// 确保监听器已添加
private void ensureListenersAdded() {
public void ensureListenersAdded() {
initListeners();
addAllListeners();
}
@@ -574,7 +584,32 @@ public class MessageListenerSingleton {
);
}
public void sendCustomC2CMessage(String userId, byte[] binaryData) {
// TODO: 2025/11/19 添加发送公共方法messageType发送的typemessage发送的内容 userId发送给谁
public void sendCustomC2CMessage(int messageType, String message, String userId) {
RoomMessageEvent.T t = new RoomMessageEvent.T();
t.setFromUserInfo(SpUtil.getUserInfo());
t.setText(message);
RoomMessageEvent roomMessageEvent = new RoomMessageEvent(messageType, mRoomId, t);
String json = com.blankj.utilcode.util.GsonUtils.toJson(roomMessageEvent);
// 转换为 byte[]
byte[] binaryData = json.getBytes(StandardCharsets.UTF_8);
// 创建自定义群消息
V2TIMMessage v2TIMMessage = V2TIMManager.getMessageManager().createCustomMessage(binaryData);
v2TIMMessage.setExcludedFromUnreadCount(true);
v2TIMMessage.setExcludedFromContentModeration(true);
// v2TIMMessage.setNeedReadReceipt(true);
//
// // 发送消息
V2TIMManager.getMessageManager().sendMessage(v2TIMMessage, "u" + userId, null, V2TIMMessage.V2TIM_PRIORITY_HIGH,
true,
null,
sendCallback);
}
public void sendCustomC2CMessage125(String userId, byte[] binaryData) {
// 创建自定义群消息
V2TIMMessage v2TIMMessage = V2TIMManager.getMessageManager().createCustomMessage(binaryData);
v2TIMMessage.setExcludedFromUnreadCount(true);
@@ -612,7 +647,7 @@ public class MessageListenerSingleton {
// listener.onMessageReceived(message);
// }
if (message.getMsgType() == 1001 && publicScreenListeners.isEmpty()) {
if ((message.getMsgType() == 1001 || message.getMsgType() == 1080) && publicScreenListeners.isEmpty()) {
cacheMessage(message.getRoomId(), message);
}

View File

@@ -30,6 +30,10 @@ public abstract class BasePresenter<V extends IView> implements IPresenter {
mContext = context;
}
public BasePresenter() {
}
private void attachView(V view) {
MvpRef = new WeakReference<V>(view);
}

View File

@@ -6,10 +6,12 @@ import com.xscm.moduleutil.bean.GiftLabelBean;
import com.xscm.moduleutil.bean.GiftPackBean;
import com.xscm.moduleutil.bean.GiftPackListCount;
import com.xscm.moduleutil.bean.RewardUserBean;
import com.xscm.moduleutil.bean.RoomGiftData;
import com.xscm.moduleutil.bean.RoonGiftModel;
import com.xscm.moduleutil.bean.WalletBean;
import com.xscm.moduleutil.bean.room.RoomAuction;
import com.xscm.moduleutil.http.BaseObserver;
import com.xscm.moduleutil.http.RetrofitClient;
import java.lang.ref.WeakReference;
import java.util.List;
@@ -26,7 +28,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void getRewardList(String id, int page, int page_limit) {
api.getRewardList(id, page, page_limit, new BaseObserver<List<RewardUserBean>>() {
RetrofitClient.getInstance().getRewardList(id, page, page_limit, new BaseObserver<List<RewardUserBean>>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
@@ -45,7 +47,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void getGiftLabel(String have_hot) {
api.getGiftLabel(have_hot, new BaseObserver<List<GiftLabelBean>>() {
RetrofitClient.getInstance().getGiftLabel(have_hot, new BaseObserver<List<GiftLabelBean>>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
@@ -64,7 +66,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void getGiftList(String id, int type, String roomId) {
api.getGiftList(Integer.parseInt(id), roomId, new BaseObserver<List<RoonGiftModel>>() {
RetrofitClient.getInstance().getGiftList(Integer.parseInt(id), roomId, new BaseObserver<List<RoonGiftModel>>() {
@Override
public void onSubscribe(Disposable d) {
@@ -83,7 +85,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void giveGift(String user_id, String gid, String num, String to_uid, String gift_type) {
api.giveGift(user_id, gid, num, to_uid, gift_type, new BaseObserver<String>() {
RetrofitClient.getInstance().giveGift(user_id, gid, num, to_uid, gift_type, new BaseObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
@@ -102,7 +104,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void roomGift(String room_id, String gift_id, String gift_num, String to_uid, String type, String pit_number, String heart_id) {
api.roomGift(room_id, gift_id, gift_num, to_uid, type, pit_number, heart_id, new BaseObserver<String>() {
RetrofitClient.getInstance().roomGift(room_id, gift_id, gift_num, to_uid, type, pit_number, heart_id, new BaseObserver<RoomGiftData>() {
@Override
public void onSubscribe(Disposable d) {
@@ -110,7 +112,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
}
@Override
public void onNext(String s) {
public void onNext(RoomGiftData s) {
if (MvpRef == null) {
MvpRef = new WeakReference<>(mView);
}
@@ -121,7 +123,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void wallet() {
api.wallet(new BaseObserver<WalletBean>() {
RetrofitClient.getInstance().wallet(new BaseObserver<WalletBean>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
@@ -139,7 +141,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void reward_zone(String id, String gift_id, String num, String is_pack) {
api.reward_zone(id, gift_id, num, is_pack, new BaseObserver<String>() {
RetrofitClient.getInstance().reward_zone(id, gift_id, num, is_pack, new BaseObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
@@ -158,7 +160,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void setRoomApply(String room_id, String gift_id, String gift_price) {
api.setRoomApply(room_id, gift_id, gift_price, new BaseObserver<String>() {
RetrofitClient.getInstance().setRoomApply(room_id, gift_id, gift_price, new BaseObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
@@ -176,7 +178,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void roomAuctionJoin(String auction_id, String user_id, String gift_id, String num, String type) {
api.roomAuctionJoin(auction_id, user_id, gift_id, num, type, new BaseObserver<RoomAuction.AuctionListBean>() {
RetrofitClient.getInstance().roomAuctionJoin(auction_id, user_id, gift_id, num, type, new BaseObserver<RoomAuction.AuctionListBean>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
@@ -194,7 +196,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void giftPack() {
api.giftPack(new BaseObserver<List<GiftPackBean>>() {
RetrofitClient.getInstance().giftPack(new BaseObserver<List<GiftPackBean>>() {
@Override
public void onSubscribe(Disposable d) {
@@ -216,7 +218,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void getGiftPack(String roomId, String userId, String heart_id, String auction_id) {
api.getGiftPack(roomId, userId, heart_id, auction_id, new BaseObserver<String>() {
RetrofitClient.getInstance().getGiftPack(roomId, userId, heart_id, auction_id, new BaseObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
@@ -238,7 +240,7 @@ public class RewardGiftPresenter extends BasePresenter<RewardGiftContacts.View>
@Override
public void getGiftPackListCount() {
api.getGiftPackListCount(new BaseObserver<GiftPackListCount>() {
RetrofitClient.getInstance().getGiftPackListCount(new BaseObserver<GiftPackListCount>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);

View File

@@ -2,6 +2,14 @@ package com.xscm.moduleutil.rtc;
import static com.blankj.utilcode.util.SnackbarUtils.getView;
import static io.agora.rtc2.Constants.NETWORK_TYPE_DISCONNECTED;
import static io.agora.rtc2.Constants.NETWORK_TYPE_LAN;
import static io.agora.rtc2.Constants.NETWORK_TYPE_MOBILE_2G;
import static io.agora.rtc2.Constants.NETWORK_TYPE_MOBILE_3G;
import static io.agora.rtc2.Constants.NETWORK_TYPE_MOBILE_4G;
import static io.agora.rtc2.Constants.NETWORK_TYPE_MOBILE_5G;
import static io.agora.rtc2.Constants.NETWORK_TYPE_UNKNOWN;
import static io.agora.rtc2.Constants.NETWORK_TYPE_WIFI;
import static io.agora.rtc2.video.VideoEncoderConfiguration.*;
import static io.agora.rtc2.video.VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15;
import static io.agora.rtc2.video.VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_30;
@@ -593,6 +601,25 @@ public class AgoraManager {
}
}
@Override
public void onNetworkTypeChanged(int type) {
super.onNetworkTypeChanged(type);
switch (type) {
case NETWORK_TYPE_UNKNOWN://未知网络
break;
case NETWORK_TYPE_DISCONNECTED://SDK与网络断开连接
break;
case NETWORK_TYPE_LAN:
case NETWORK_TYPE_WIFI:
case NETWORK_TYPE_MOBILE_2G:
case NETWORK_TYPE_MOBILE_3G:
case NETWORK_TYPE_MOBILE_4G:
case NETWORK_TYPE_MOBILE_5G:
break;
}
}
};
}
/**

View File

@@ -1,5 +1,14 @@
package com.xscm.moduleutil.rtc;
import static io.agora.rtc2.Constants.NETWORK_TYPE_DISCONNECTED;
import static io.agora.rtc2.Constants.NETWORK_TYPE_LAN;
import static io.agora.rtc2.Constants.NETWORK_TYPE_MOBILE_2G;
import static io.agora.rtc2.Constants.NETWORK_TYPE_MOBILE_3G;
import static io.agora.rtc2.Constants.NETWORK_TYPE_MOBILE_4G;
import static io.agora.rtc2.Constants.NETWORK_TYPE_MOBILE_5G;
import static io.agora.rtc2.Constants.NETWORK_TYPE_UNKNOWN;
import static io.agora.rtc2.Constants.NETWORK_TYPE_WIFI;
import com.blankj.utilcode.util.ObjectUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.xscm.moduleutil.interfaces.SoundLevelUpdateListener;
@@ -21,7 +30,7 @@ public class MyIRtcEngineEventHandler extends IRtcEngineEventHandler {
this.mRtcEventListener = mRtcEventListener;
}
public MyIRtcEngineEventHandler(RtcEventListener mRtcEventListener,List<SoundLevelUpdateListener> soundLevelUpdateListeners) {
public MyIRtcEngineEventHandler(RtcEventListener mRtcEventListener, List<SoundLevelUpdateListener> soundLevelUpdateListeners) {
this.soundLevelUpdateListeners = soundLevelUpdateListeners;
this.mRtcEventListener = mRtcEventListener;
}
@@ -80,7 +89,7 @@ public class MyIRtcEngineEventHandler extends IRtcEngineEventHandler {
if (!ObjectUtils.isEmpty(soundLevelUpdateListeners)) {
for (SoundLevelUpdateListener listener : soundLevelUpdateListeners) {
if (listener != null) {
listener.onRemoteSoundLevelUpdate(info.uid > 0 ? String.valueOf(info.uid) : SpUtil.getUserId()+"", info.volume);
listener.onRemoteSoundLevelUpdate(info.uid > 0 ? String.valueOf(info.uid) : SpUtil.getUserId() + "", info.volume);
}
}
}
@@ -108,4 +117,12 @@ public class MyIRtcEngineEventHandler extends IRtcEngineEventHandler {
});
}
}
@Override
public void onNetworkTypeChanged(int type) {
super.onNetworkTypeChanged(type);
if (mRtcEventListener != null) {
mRtcEventListener.onNetworkTypeChanged(type);
}
}
}

View File

@@ -47,4 +47,8 @@ public interface RtcEventListener {
void destroy();
void onNetworkTypeChanged(int type);
}

View File

@@ -36,7 +36,7 @@ public class IMConnectionService extends Service {
Log.d(TAG, "IM connect success");
if (CommonAppContext.getInstance().playId != null) {
LogUtils.e("@@@", ""+CommonAppContext.getInstance().playId);
RetrofitClient.getInstance().roomUserReconnect(CommonAppContext.getInstance().playId);
// RetrofitClient.getInstance().roomUserReconnect(CommonAppContext.getInstance().playId);
}
}

View File

@@ -46,11 +46,10 @@ public class MqttConnect {
this.clientId = clientId;
// 这里是你自己需要订阅的主题
shutdown = "qx_room_topic"; // 关机
update_app = "qx_xunlehui"; // 发送更新APP
// qx_hour_ranking = "qx_hour_ranking";
qx_hour_ranking = "qx_hour_ranking";
qx_redpacket_arrive = "qx_redpacket_arrive";
shutdown = "qx_room_topic"; // 房间飘屏
update_app = "qx_xunlehui"; // 巡乐会飘屏
qx_hour_ranking = "qx_hour_ranking";//小时榜飘屏
qx_redpacket_arrive = "qx_redpacket_arrive"; //红包飘屏的主题
ArrayList<String> topicList = new ArrayList<>();
topicList.add(shutdown);

View File

@@ -19,7 +19,7 @@ import java.util.Map;
public class ColorManager {
private static ColorManager instance;
private String primaryColor = "#3ABC6D"; // 默认主题色
private String buttonColor = "#6D6D6D"; // 默认按钮色
private String buttonColor = "#FFFFFF"; // 默认按钮色
// 监听器列表,用于通知颜色变化
private List<ColorChangeListener> listeners = new ArrayList<>();
@@ -80,7 +80,7 @@ public class ColorManager {
try {
return Color.parseColor(buttonColor);
} catch (Exception e) {
return Color.parseColor("#6D6D6D"); // 默认颜色
return Color.parseColor("#FFFFFF"); // 默认颜色
}
}

View File

@@ -207,7 +207,7 @@ public class ImageUtils {
return;
}
}
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
Glide.with(mImageView).load(path).placeholder(R.mipmap.default_avatar).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
public static void loadHeadCC(String path, ImageView mImageView) {

View File

@@ -23,6 +23,7 @@ public class MeHeadView extends ConstraintLayout {
private ImageView mIvSex;
private ImageView mIvOnline;
private ImageView iv_frame_bg;
private ImageView iv_master_bg;
public MeHeadView(Context context) {
this(context, null, 0);
@@ -43,7 +44,8 @@ public class MeHeadView extends ConstraintLayout {
mIvFrame = findViewById(R.id.iv_frame);
mIvSex = findViewById(R.id.iv_sex);
mIvOnline = findViewById(R.id.iv_online);
iv_frame_bg=findViewById(R.id.iv_frame_bg);
iv_frame_bg = findViewById(R.id.iv_frame_bg);
iv_master_bg = findViewById(R.id.iv_master_bg);
mIvSex.setVisibility(GONE);
}
@@ -59,17 +61,68 @@ public class MeHeadView extends ConstraintLayout {
mIvFrame.setSource(framePicture, 1);
}
if (nobilityImage!=null && !TextUtils.isEmpty(nobilityImage)){
if (nobilityImage != null && !TextUtils.isEmpty(nobilityImage)) {
iv_frame_bg.setVisibility(VISIBLE);
ImageUtils.loadHead(nobilityImage, iv_frame_bg);
}else {
ImageUtils.loadRoomItem(nobilityImage, iv_frame_bg);
} else {
iv_frame_bg.setVisibility(GONE);
}
}
public void setMaster(String headPicture) {
if (!TextUtils.isEmpty(headPicture)) {
ImageUtils.loadHead(headPicture, mRiv);
}
iv_master_bg.setVisibility(VISIBLE);
iv_master_bg.setImageResource(R.mipmap.icon_master);
}
public void setOnline(boolean isOnline) {
mIvOnline.setVisibility(VISIBLE);
mIvOnline.setImageResource(isOnline ? R.mipmap.me_online_icon : R.mipmap.me_icon_unchecked);
}
public void setSex(int sex, String headPicture, String dress) {
if (!TextUtils.isEmpty(headPicture)) {
ImageUtils.loadHead(headPicture, mRiv);
}
if (TextUtils.isEmpty(dress)) {
mIvFrame.setVisibility(GONE);
} else {
mIvFrame.setVisibility(VISIBLE);
mIvFrame.setSource(dress, 1);
}
mIvSex.setVisibility(VISIBLE);
mIvSex.setImageResource(sex == 1 ? R.mipmap.nan : R.mipmap.nv);
}
/**
* 设置头像,性别,头像框,贵族
* @param sex
* @param headPicture
* @param framePicture
* @param nobilityImage
*/
public void setAll(int sex,String headPicture, String framePicture, String nobilityImage) {
if (!TextUtils.isEmpty(headPicture)) {
ImageUtils.loadHead(headPicture, mRiv);
}
if (TextUtils.isEmpty(framePicture)) {
mIvFrame.setVisibility(GONE);
} else {
mIvFrame.setVisibility(VISIBLE);
mIvFrame.setSource(framePicture, 1);
}
mIvSex.setImageResource(sex == 1 ? R.mipmap.nan : R.mipmap.nv);
if (nobilityImage != null && !TextUtils.isEmpty(nobilityImage)) {
iv_frame_bg.setVisibility(VISIBLE);
ImageUtils.loadRoomItem(nobilityImage, iv_frame_bg);
} else {
iv_frame_bg.setVisibility(GONE);
}
}
}

View File

@@ -189,7 +189,7 @@ public class TimeUtils {
}
public static String getDateToStringNoZ(long time) {
Date d = new Date(time);
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sf.format(d);
}
@@ -237,4 +237,25 @@ public class TimeUtils {
return sb.toString().trim();
}
/**
* 格式化时长(毫秒),只返回天数部分。
* 例如:输入 90000000 (90,000秒即1天多),返回 "1天"
*
* @param durationMs 时长,单位为毫秒
* @return 格式化后的天数字符串,如 "1天",如果不足一天则返回空字符串 ""
*/
public static String formatDurationDaysOnly(long durationMs) {
long totalSeconds = durationMs / 1000;
long days = totalSeconds / 86400;
// 如果天数大于0则构建返回字符串
if (days > 0) {
return days + "";
}
// 如果天数不足1天根据需求可以返回空字符串也可以返回 "0天" 或其他
return "1天"; // 或者 return "0天";
}
}

View File

@@ -0,0 +1,939 @@
package com.xscm.moduleutil.utils.roomview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.blankj.utilcode.util.LogUtils;
import com.tencent.qgame.animplayer.AnimConfig;
import com.tencent.qgame.animplayer.AnimView;
import com.tencent.qgame.animplayer.inter.IAnimListener;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.utils.ImageUtils;
import com.xscm.moduleutil.widget.CircularImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* 项目名称:羽声语音
* 时间2025/11/24 9:50
* 用途:
*/
public class RoomCPView extends FrameLayout {
private AnimView anim_cp;
private boolean isLoadEffect = false;
private boolean isShow = true; // 是否开启特效
private ReentrantLock lock = new ReentrantLock();
private List<String> animationArray = new ArrayList<>();
public ExecutorService queue = Executors.newSingleThreadExecutor();
private Context mContext;
private boolean isOnece;
private CircularImage room_cp_head1;
private CircularImage room_cp_head2;
private TextView room_cp_name1, room_cp_name2;
private LinearLayout avatarContainer1;
private ConstraintLayout avatarsParentContainer;
// 动画队列和锁机制
private final Queue<AnimationTask> animationQueue = new LinkedList<>();
private boolean isAnimationRunning = false;
private final Object animationLock = new Object();
// 下载任务缓存
private final Queue<DownloadTask> downloadQueue = new LinkedList<>();
private boolean isDownloadRunning = false;
private final Object downloadLock = new Object();
private String currPlayPath = "";
public void setQueue(ExecutorService queue) {
this.queue = queue;
}
public RoomCPView(@NonNull Context context) {
super(context);
this.mContext = context;
init();
}
public RoomCPView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
init();
}
public RoomCPView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
init();
}
public RoomCPView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.mContext = context;
init();
}
private void init() {
isLoadEffect = false;
initView();
// 设置动画监听器
setupAnimListener();
}
/**
* 设置动画监听器
*/
private void setupAnimListener() {
if (anim_cp != null) {
anim_cp.setAnimListener(new IAnimListener() {
@Override
public void onVideoDestroy() {
LogUtils.e("onVideoDestroy");
}
@Override
public void onVideoComplete() {
LogUtils.e("onVideoComplete");
// 确保所有UI操作在主线程中执行
post(() -> {
if (anim_cp != null) {
// 停止头像动画
stopAvatarAnimation();
// 隐藏动画视图和头像
anim_cp.setVisibility(View.GONE);
avatarContainer1.setVisibility(View.GONE);
if (isOnece) {
return;
}
// 通知播放完成
notifyPlaybackComplete();
loadStartAnimation();
}
});
}
@Override
public void onVideoRender(int i, @Nullable AnimConfig animConfig) {
// LogUtils.e("onVideoRender", i, animConfig);
}
@Override
public void onVideoStart() {
LogUtils.e("onVideoStart");
// 确保所有UI操作在主线程中执行
post(() -> {
// 动画开始,显示视图和头像
setVisibility(View.VISIBLE);
anim_cp.setVisibility(View.VISIBLE);
avatarContainer1.setVisibility(View.VISIBLE);
// 启动头像上下浮动动画
// startAvatarFloatAnimation();
});
}
@Override
public boolean onVideoConfigReady(@NonNull AnimConfig animConfig) {
LogUtils.e("onVideoConfigReady", animConfig);
return true;
}
@Override
public void onFailed(int i, @Nullable String s) {
LogUtils.e("onFailed", s);
// 确保所有UI操作在主线程中执行
post(() -> {
// 动画失败,隐藏视图
setVisibility(View.GONE);
anim_cp.setVisibility(View.GONE);
// 继续播放下一个
loadStartAnimation();
});
}
});
}
}
private void initView() {
LayoutInflater.from(getContext()).inflate(R.layout.room_cp_vip_view, this, true);
anim_cp = findViewById(R.id.anim_cp);
room_cp_head1 = findViewById(R.id.room_cp_head1);
room_cp_head2 = findViewById(R.id.room_cp_head2);
room_cp_name1 = findViewById(R.id.room_cp_name1);
room_cp_name2 = findViewById(R.id.room_cp_name2);
// 获取头像的父布局
avatarContainer1 = findViewById(R.id.ll_head);
// 获取包含两个头像的父 LinearLayout
avatarsParentContainer = (ConstraintLayout) avatarContainer1.getParent();
// // 初始状态隐藏头像和名称
// room_cp_head1.setVisibility(View.GONE);
// room_cp_head2.setVisibility(View.GONE);
// room_cp_name1.setVisibility(View.GONE);
// room_cp_name2.setVisibility(View.GONE);
}
public void setCPTextData(String room_head1, String room_head2, String room_cp_name1, String room_cp_name2) {
ImageUtils.loadHeadCC(room_head1, room_cp_head1);
ImageUtils.loadHeadCC(room_head2, room_cp_head2);
this.room_cp_name1.setText(room_cp_name1);
this.room_cp_name2.setText(room_cp_name2);
}
private void loadStartAnimation() {
if (!isShow) {
// isshow 为是否开启特效 如果未开启则return
return;
}
String animationPath = null;
// list加锁
lock.lock();
try {
// 如果list长度大于0
if (!animationArray.isEmpty()) {
// 动画路径则赋值取list中的第一个数据
animationPath = animationArray.get(0);
// 移除list的第一条数据
animationArray.remove(0);
isLoadEffect = true;
} else {
isLoadEffect = false;
// 队列为空,释放资源但不销毁视图
post(() -> {
destroyEffectView();
});
}
} finally {
// 解锁
lock.unlock();
}
if (isLoadEffect && animationPath != null && !TextUtils.isEmpty(animationPath)) {
String finalAnimationPath = animationPath;
post(new Runnable() {
@Override
public void run() {
// 处理MP4动画文件可能是网络URL
handleMP4File(finalAnimationPath, new DownloadCallback() {
@Override
public void onSuccess(String localPath) {
post(() -> {
// 设置MP4动画文件
currPlayPath = localPath;
// 启动从底部弹起动画
startBottomUpAnimation();
// 开始播放动画
anim_cp.setLoop(1);
});
}
@Override
public void onError(String error) {
LogUtils.e("MP4下载或播放失败: " + error);
// 处理失败情况,继续播放下一个
post(() -> {
lock.lock();
try {
isLoadEffect = false;
} finally {
lock.unlock();
}
loadStartAnimation();
});
}
});
}
});
}
}
/**
* CP特效进来
*
* @param room_head1 头像1
* @param room_head2 头像2
* @param room_name1 名称1
* @param room_name2 名称2
* @param mp4Path MP4动画文件路径
*/
public void displayEffectView(String room_head1, String room_head2, String room_name1, String room_name2, String mp4Path) {
// 确保视图已初始化
reinitView();
// 设置CP数据但不显示头像
setCPTextData(room_head1, room_head2, room_name1, room_name2);
// 确保头像初始为隐藏状态
// room_cp_head1.setVisibility(View.GONE);
// room_cp_head2.setVisibility(View.GONE);
// room_cp_name1.setVisibility(View.GONE);
// room_cp_name2.setVisibility(View.GONE);
// 确保视图可见
setVisibility(View.VISIBLE);
// 检查队列是否已初始化
if (queue == null) {
queue = Executors.newSingleThreadExecutor();
}
queue.execute(new Runnable() {
@SuppressLint("CheckResult")
@Override
public void run() {
// 如果mp4Path不存在return
if (mp4Path == null || mp4Path.isEmpty()) {
return;
}
// 将mp4Path链接转为小写
String playImage = mp4Path;
String pathExtension = getFileExtension(playImage).toLowerCase();
// 判定礼物的后缀是否为svga或者mp4如果非这两种 则return
if (!("svga".equals(pathExtension) || "mp4".equals(pathExtension))) {
return;
}
// 锁住list
lock.lock();
try {
// 添加动画数据进list
animationArray.add(playImage);
// 如果没有在加载则开始加载
if (!isLoadEffect) {
// 更改加载状态标记
Observable.timer(2000, TimeUnit.MILLISECONDS).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
isLoadEffect = true;
loadStartAnimation();
}
});
}
} finally {
// 解锁
lock.unlock();
}
}
});
}
/**
* 原始的动画方法,现在只被内部调用
*/
public void startAnimation(AnimationListener listener) {
// 设置进入动画
AlphaAnimation fadeIn = new AlphaAnimation(0f, 1f);
fadeIn.setDuration(500);
fadeIn.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
// 保持显示1秒后开始退出动画
postDelayed(() -> {
AlphaAnimation fadeOut = new AlphaAnimation(1f, 0f);
fadeOut.setDuration(500);
fadeOut.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (listener != null) {
listener.onAnimationEnd();
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
startAnimation(fadeOut);
}, 1000);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
startAnimation(fadeIn);
}
public interface AnimationListener {
void onAnimationEnd();
}
// 添加播放完成监听接口
public interface OnPlaybackCompleteListener {
void onPlaybackComplete();
}
// 添加成员变量
private List<OnPlaybackCompleteListener> playbackCompleteListeners = new ArrayList<>();
// 添加监听器管理方法
public void addOnPlaybackCompleteListener(OnPlaybackCompleteListener listener) {
if (listener != null && !playbackCompleteListeners.contains(listener)) {
playbackCompleteListeners.add(listener);
}
}
public void removeOnPlaybackCompleteListener(OnPlaybackCompleteListener listener) {
if (listener != null) {
playbackCompleteListeners.remove(listener);
}
}
public void clearPlaybackCompleteListeners() {
playbackCompleteListeners.clear();
}
// 触发播放完成回调的方法
private void notifyPlaybackComplete() {
for (OnPlaybackCompleteListener listener : new ArrayList<>(playbackCompleteListeners)) {
if (listener != null) {
listener.onPlaybackComplete();
}
}
}
/**
* 动画任务类,用于存储动画所需的数据
*/
public static class AnimationTask {
String room_head1;
String room_head2;
String room_cp_name1;
String room_cp_name2;
String mp4Path; // MP4动画文件路径
AnimationListener listener;
AnimationTask(String room_head1, String room_head2, String room_cp_name1, String room_cp_name2, String mp4Path, AnimationListener listener) {
this.room_head1 = room_head1;
this.room_head2 = room_head2;
this.room_cp_name1 = room_cp_name1;
this.room_cp_name2 = room_cp_name2;
this.mp4Path = mp4Path;
this.listener = listener;
}
}
/**
* 处理MP4文件如果是网络URL则下载到本地
*
* @param path 文件路径或URL
* @param callback 下载回调
*/
private void handleMP4File(String path, DownloadCallback callback) {
// 判断是否是网络URL
if (path != null && (path.startsWith("http://") || path.startsWith("https://"))) {
// 是网络URL需要下载
downloadFile(path, callback);
} else {
// 本地路径,直接使用
if (callback != null) {
callback.onSuccess(path);
}
}
}
/**
* 下载文件到本地
*
* @param url 下载URL
* @param callback 下载回调
*/
private void downloadFile(String url, DownloadCallback callback) {
synchronized (downloadLock) {
// 创建下载任务并加入队列
DownloadTask task = new DownloadTask(url, callback);
downloadQueue.offer(task);
// 如果当前没有下载任务在执行,则开始下载
if (!isDownloadRunning) {
processNextDownload();
}
}
}
/**
* 处理下一个下载任务
*/
private void processNextDownload() {
synchronized (downloadLock) {
if (downloadQueue.isEmpty()) {
isDownloadRunning = false;
return;
}
isDownloadRunning = true;
DownloadTask currentTask = downloadQueue.poll();
// 执行下载任务
new DownloadAsyncTask(currentTask.callback).execute(currentTask.url);
}
}
/**
* 异步下载任务
*/
private class DownloadAsyncTask extends AsyncTask<String, Void, String> {
private DownloadCallback callback;
private String errorMessage;
public DownloadAsyncTask(DownloadCallback callback) {
this.callback = callback;
}
@Override
protected String doInBackground(String... urls) {
String url = urls[0];
try {
// 获取文件名
int lastSlashIndex = url.lastIndexOf('/');
String fileName = lastSlashIndex != -1 ? url.substring(lastSlashIndex + 1) : url;
int queryIndex = fileName.indexOf("?");
if (queryIndex != -1) {
fileName = fileName.substring(0, queryIndex);
}
// 创建本地文件
File dir = new File(getContext().getCacheDir(), "animations");
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, fileName);
// 如果文件已存在,直接返回本地路径
if (file.exists()) {
return file.getAbsolutePath();
}
// 下载文件
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
errorMessage = "服务器返回HTTP错误代码: " + connection.getResponseCode();
return null;
}
InputStream input = connection.getInputStream();
FileOutputStream output = new FileOutputStream(file);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
output.close();
input.close();
connection.disconnect();
return file.getAbsolutePath();
} catch (IOException e) {
errorMessage = "下载失败: " + e.getMessage();
return null;
}
}
@Override
protected void onPostExecute(String result) {
synchronized (downloadLock) {
// 下载完成,处理下一个下载任务
processNextDownload();
}
// 通知回调
if (callback != null) {
if (result != null) {
callback.onSuccess(result);
} else {
callback.onError(errorMessage != null ? errorMessage : "未知错误");
}
}
}
}
/**
* 下载任务类
*/
private static class DownloadTask {
String url;
DownloadCallback callback;
DownloadTask(String url, DownloadCallback callback) {
this.url = url;
this.callback = callback;
}
}
/**
* 下载回调接口
*/
private interface DownloadCallback {
void onSuccess(String localPath);
void onError(String error);
}
/**
* 获取文件扩展名
*
* @param url 文件URL
* @return 文件扩展名
*/
private String getFileExtension(String url) {
if (url != null && url.contains(".")) {
return url.substring(url.lastIndexOf(".") + 1);
}
return "";
}
/**
* 销毁特效视图
*/
public void destroyEffectView() {
// 停止头像动画
stopAvatarAnimation();
// 清理监听器
clearPlaybackCompleteListeners();
// 停止动画视图但保留组件以便重用
if (anim_cp != null) {
anim_cp.stopPlay();
anim_cp.setVisibility(View.GONE);
}
// 隐藏视图但不移除,以便再次使用
setVisibility(View.GONE);
// 清空动画队列
lock.lock();
try {
animationArray.clear();
isLoadEffect = false;
} finally {
lock.unlock();
}
}
/**
* 从底部弹起动画
*/
private void startBottomUpAnimation() {
// 获取父视图的高度如果为0则使用屏幕高度
float parentHeight = 0;
if (getParent() != null) {
parentHeight = ((View) getParent()).getHeight();
}
if (parentHeight <= 0) {
parentHeight = getResources().getDisplayMetrics().heightPixels;
}
// 设置初始位置在屏幕底部外
// setTranslationY(parentHeight);
// 创建从底部弹起的动画
TranslateAnimation bottomUpAnimation = new TranslateAnimation(
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0,
Animation.RELATIVE_TO_PARENT, 1.0f, Animation.RELATIVE_TO_PARENT, 0.0f);
bottomUpAnimation.setDuration(2000); // 动画持续时间
// 创建弹性插值器
Interpolator overshootInterpolator = new OvershootInterpolator(0.5f);
bottomUpAnimation.setInterpolator(overshootInterpolator);
// 应用动画
startAnimation(bottomUpAnimation);
// 动画结束后重置位置
bottomUpAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
setVisibility(View.VISIBLE);
anim_cp.setVisibility(View.VISIBLE);
avatarContainer1.setVisibility(VISIBLE);
anim_cp.startPlay(new File(currPlayPath));
}
@Override
public void onAnimationEnd(Animation animation) {
startAvatarFloatAnimation();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
avatarsParentContainer.startAnimation(bottomUpAnimation);
}
/**
* 头像上下动画
*/
private void startAvatarFloatAnimation() {
// 确保包含两个头像的父布局已初始化
if (avatarsParentContainer == null) {
return;
}
// 包含两个头像的父布局上下浮动动画
AnimationSet avatarsAnimationSet = new AnimationSet(true);
// 使用适中的移动距离,确保头像框显示完整
TranslateAnimation avatarsFloatUp = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -0.01f);
avatarsFloatUp.setDuration(900); // 增加动画持续时间,使动画更平滑
avatarsFloatUp.setRepeatCount(Animation.INFINITE);
avatarsFloatUp.setRepeatMode(Animation.REVERSE);
avatarsAnimationSet.addAnimation(avatarsFloatUp);
avatarsParentContainer.startAnimation(avatarsAnimationSet);
}
/**
* 停止头像动画
*/
private void stopAvatarAnimation() {
if (avatarsParentContainer != null) {
avatarsParentContainer.clearAnimation();
}
}
/**
* 停止播放动画
*/
public void stopPlay() {
stopAvatarAnimation();
if (anim_cp != null) {
anim_cp.stopPlay();
anim_cp.setVisibility(View.GONE);
}
setVisibility(View.GONE);
}
/**
* 开启或关闭特效视图
*
* @param isShow 是否显示
*/
public void openOrCloseEffectViewWith(boolean isShow) {
this.isShow = isShow;
if (anim_cp != null) {
anim_cp.stopPlay();
anim_cp.setVisibility(View.GONE);
}
setVisibility(isShow ? View.VISIBLE : View.GONE);
}
/**
* 下载并播放动画
*
* @param context 上下文
* @param playImage 动画URL
* @param callback 下载回调
*/
public void downloadAndPlay(Context context, String playImage, DownloadCallback callback) {
String fileName = playImage.substring(playImage.lastIndexOf("/"));
String filePath = context.getCacheDir().getAbsolutePath() + fileName;
LogUtils.e("@@@@@filePath: " + filePath.toString());
File file = new File(filePath);
if (!file.exists()) {
LogUtils.e("无缓存");
// 使用OkHttp进行下载
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(playImage)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
LogUtils.e("MP4下载失败: " + e.toString());
// 在主线程中回调失败
post(() -> {
if (callback != null) {
callback.onError(e.getMessage());
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
try (ResponseBody responseBody = response.body()) {
if (responseBody != null) {
File downloadedFile = new File(filePath);
FileOutputStream fos = new FileOutputStream(downloadedFile);
fos.write(responseBody.bytes());
fos.close();
// 在主线程中回调成功
post(() -> {
if (callback != null) {
callback.onSuccess(downloadedFile.getAbsolutePath());
}
});
} else {
// 在主线程中回调失败
post(() -> {
if (callback != null) {
callback.onError("Response body is null");
}
});
}
} catch (Exception e) {
LogUtils.e("MP4文件保存失败: " + e.getMessage());
// 在主线程中回调失败
post(() -> {
if (callback != null) {
callback.onError(e.getMessage());
}
});
}
} else {
LogUtils.e("MP4下载响应失败");
// 在主线程中回调失败
post(() -> {
if (callback != null) {
callback.onError("Response not successful: " + response.code());
}
});
}
}
});
} else {
// 文件已存在,直接回调成功
if (callback != null) {
callback.onSuccess(file.getAbsolutePath());
}
}
}
/**
* 重新初始化视图,以便再次播放
*/
public void reinitView() {
if (anim_cp == null) {
// 如果动画视图已被销毁,重新初始化
initView();
// 重新设置动画监听器
setupAnimListener();
}
// 确保线程池可用
if (queue == null || queue.isShutdown()) {
queue = Executors.newSingleThreadExecutor();
}
// 重置状态
isLoadEffect = false;
isShow = true;
}
/**
* 完全销毁视图,释放所有资源
* 当不再需要此视图时调用
*/
public void completeDestroy() {
// 停止头像动画
stopAvatarAnimation();
// 清理监听器
clearPlaybackCompleteListeners();
// 停止并移除动画视图
if (anim_cp != null) {
anim_cp.stopPlay();
removeView(anim_cp);
anim_cp = null;
}
// 停止线程池
if (queue != null) {
queue.shutdown();
queue = null;
}
// 隐藏并移除整个视图
setVisibility(View.GONE);
if (getParent() != null) {
((ViewGroup) getParent()).removeView(this);
}
}
}

View File

@@ -7,6 +7,7 @@ import android.os.Looper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SoundEffectConstants;
import android.view.View;
import android.widget.FrameLayout;
@@ -57,6 +58,12 @@ import okhttp3.ResponseBody;
public class AvatarFrameView extends FrameLayout {
private PlaybackManager playbackManager;
private boolean isMute = false;
public void setMute(boolean b) {
this.isMute = b;
}
public enum RenderType {SVGA, MP4}
private RenderType renderType;
@@ -113,49 +120,6 @@ public class AvatarFrameView extends FrameLayout {
// 初始化播放管理器
playbackManager = new PlaybackManager(mainHandler);
// 获取 MP4PlaybackCallback 单例实例并设置引用
// MP4PlaybackCallback callback = MP4PlaybackCallback.getInstance();
// callback.setAvatarFrameView(this);
// 设置播放完成监听
// mBinding.playView.setAnimListener(callback);
// if (mBinding != null) {
// mBinding.playView.setAnimListener(this);
// }
// MP4PlaybackCallback = new IAnimListener() {
// @Override
// public boolean onVideoConfigReady(@NonNull AnimConfig animConfig) {
// return false;
// }
//
// @Override
// public void onVideoStart() {
//
// }
//
// @Override
// public void onVideoRender(int i, @Nullable AnimConfig animConfig) {
//
// }
//
// @Override
// public void onVideoComplete() {
// onPlaybackComplete();
// }
//
// @Override
// public void onVideoDestroy() {
//
// }
//
// @Override
// public void onFailed(int i, @Nullable String s) {
// onPlaybackComplete();
// }
// };
// // 设置播放完成监听
// mBinding.playView.setAnimListener(MP4PlaybackCallback);
}
private String getFileExtension(String url) {
@@ -488,7 +452,7 @@ public class AvatarFrameView extends FrameLayout {
} else {
mBinding.playView.setLoop(1); // 播放一次
}
mBinding.playView.setMute(isMute);
// 开始播放前检查视图状态
if (!isDestroyed && mBinding != null && mBinding.playView != null) {
mBinding.playView.startPlay(file);

View File

@@ -92,6 +92,7 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
private final SVGAParser parser = new SVGAParser(CommonAppContext.getInstance());
public boolean isMentorShip = false;
public BaseWheatView(Context context) {
this(context, null, 0);
@@ -158,6 +159,9 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
}
}
public void isMentorShip(boolean isMentorShip) {
this.isMentorShip = isMentorShip;
}
/**
* 设置麦位数据
@@ -175,11 +179,15 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
setCardiac(pitBean.getCharm(), getTzbl());
if (bean.getUser_id() != null && !bean.getUser_id().equals("0") && !bean.getUser_id().isEmpty()) {
if (CommonAppContext.getInstance().getOnlineMap() != null && CommonAppContext.getInstance().getOnlineMap().get(bean.getUser_id()) != null) {
iv_on_line.setVisibility(CommonAppContext.getInstance().getOnlineMap().get(bean.getUser_id()) == 1 ? GONE : VISIBLE);
} else {
iv_on_line.setVisibility(GONE);
}
if (bean.getIs_online()==1){
iv_on_line.setVisibility(GONE);
}else if (bean.getIs_online()==2){
if (!bean.getUser_id().equals(SpUtil.getUserId()+"")) {
iv_on_line.setVisibility(VISIBLE);
}
}else {
iv_on_line.setVisibility(GONE);
}
} else {
iv_on_line.setVisibility(GONE);
}
@@ -201,52 +209,56 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
setPitData(bean);
//心动值
//显示心动
if ("1".equals(pitBean.getShutup())) {
mIvShutup.setVisibility(VISIBLE);
} else {
mIvShutup.setVisibility(GONE);
}
//自动调节麦位波纹
if (mIvRipple != null) {
mIvRipple.setScaleX(1.1f);
mIvRipple.setScaleY(1.1f);
}
if (pitNumber.equals("9")) {
iv_tag_type.setImageResource(R.mipmap.zc);
if (mRiv.getLayoutParams() instanceof ConstraintLayout.LayoutParams) {
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) mRiv.getLayoutParams();
params.matchConstraintPercentWidth = 0.66f; // 设置为 52%
params.width = 0; // 必须设为 0dpMATCH_CONSTRAINT
mRiv.setLayoutParams(params);
if (!isMentorShip){
//心动值
//显示心动
if ("1".equals(pitBean.getShutup())) {
mIvShutup.setVisibility(VISIBLE);
} else {
mIvShutup.setVisibility(GONE);
}
} else if (pitNumber.equals("10")) {
iv_tag_type.setImageResource(R.mipmap.jb);
if (mRiv.getLayoutParams() instanceof ConstraintLayout.LayoutParams) {
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) mRiv.getLayoutParams();
params.matchConstraintPercentWidth = 0.66f; // 设置为 52%
params.width = 0; // 必须设为 0dpMATCH_CONSTRAINT
mRiv.setLayoutParams(params);
if (pitNumber.equals("9")) {
iv_tag_type.setImageResource(R.mipmap.zc);
if (mRiv.getLayoutParams() instanceof ConstraintLayout.LayoutParams) {
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) mRiv.getLayoutParams();
params.matchConstraintPercentWidth = 0.66f; // 设置为 52%
params.width = 0; // 必须设为 0dpMATCH_CONSTRAINT
mRiv.setLayoutParams(params);
}
} else if (pitNumber.equals("10")) {
iv_tag_type.setImageResource(R.mipmap.jb);
if (mRiv.getLayoutParams() instanceof ConstraintLayout.LayoutParams) {
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) mRiv.getLayoutParams();
params.matchConstraintPercentWidth = 0.66f; // 设置为 52%
params.width = 0; // 必须设为 0dpMATCH_CONSTRAINT
mRiv.setLayoutParams(params);
}
} else if (pitNumber.equals("-1")) {
iv_tag_type.setImageResource(R.mipmap.mu_yc);
if (mRiv.getLayoutParams() instanceof ConstraintLayout.LayoutParams) {
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) mRiv.getLayoutParams();
params.matchConstraintPercentWidth = 0.66f; // 设置为 52%
params.width = 0; // 必须设为 0dpMATCH_CONSTRAINT
mRiv.setLayoutParams(params);
}
} else if (pitNumber.equals("0")) {
iv_tag_type.setVisibility(GONE);
mIvShutup.setVisibility(VISIBLE);
} else if (pitNumber.equals("888")) {
iv_tag_type.setVisibility(GONE);
mIvShutup.setVisibility(GONE);
} else {
iv_tag_type.setVisibility(GONE);
}
} else if (pitNumber.equals("-1")) {
iv_tag_type.setImageResource(R.mipmap.mu_yc);
if (mRiv.getLayoutParams() instanceof ConstraintLayout.LayoutParams) {
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) mRiv.getLayoutParams();
params.matchConstraintPercentWidth = 0.66f; // 设置为 52%
params.width = 0; // 必须设为 0dpMATCH_CONSTRAINT
mRiv.setLayoutParams(params);
}
} else if (pitNumber.equals("0")) {
iv_tag_type.setVisibility(GONE);
mIvShutup.setVisibility(VISIBLE);
} else if (pitNumber.equals("888")) {
iv_tag_type.setVisibility(GONE);
mIvShutup.setVisibility(GONE);
} else {
iv_tag_type.setVisibility(GONE);
}
AgoraManager.getInstance().addSoundLevelListener(new SoundLevelUpdateListener() {
@Override
public void onRemoteSoundLevelUpdate(String userId, int soundLevel) {
@@ -416,9 +428,13 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
public void setOnlineStatus() {
if (pitBean.getUser_id() != null && !pitBean.getUser_id().equals("0") && !pitBean.getUser_id().isEmpty()) {
if (CommonAppContext.getInstance().getOnlineMap() != null && CommonAppContext.getInstance().getOnlineMap().get(pitBean.getUser_id()) != null) {
iv_on_line.setVisibility(CommonAppContext.getInstance().getOnlineMap().get(pitBean.getUser_id()) == 1 ? GONE : VISIBLE);
} else {
if (pitBean.getIs_online()==1){
iv_on_line.setVisibility(GONE);
}else if (pitBean.getIs_online()==2){
if (!pitBean.getUser_id().equals(SpUtil.getUserId()+"")) {
iv_on_line.setVisibility(VISIBLE);
}
}else {
iv_on_line.setVisibility(GONE);
}
} else {

View File

@@ -278,6 +278,11 @@ public class Constants {
public static final String POST_GRAB = "/api/Redpacket/grab";//抢红包
public static final String GET_ROOM_GIFT = "/api/Room/room_give_gift";//直播间送礼
public static final String POST_CP_GIVE_GIFT = "/api/UserCp/cpGiveGift";//用户CP礼物回赠
public static final String GET_CP_ZONE = "/api/UserCp/cpZone";//心动空间
public static final String POST_MY_FAMILY = "/api/Family/myFamily";//我的家族
public static final String POST_MY_JOIN_FAMILY = "/api/Family/myJoinFamily";//我加入的家族
public static final String POST_FAMILY_EARNINGS = "/api/Family/familyEarnings";//家族收益详情
public static final String GET_ROOM_USER = "/api/Room/room_user_home";//房间内点击头像
public static final String APPLY_PIT = "/api/RoomPit/apply_pit";//申请上麦
public static final String DOWN_PIT = "/api/RoomPit/down_pit";//下麦
@@ -365,6 +370,7 @@ public class Constants {
public static final String GET_APP_UPDATE = "/api/Version/get_app_version";//版本更新
public static final String POST_CLEAR_USER_CHARM = "/api/Room/clear_user_charm";//清除魅力值
public static final String POST_MESSAGE_LIST = "/api/UserMessage/get_user_message_list";//消息列表
public static final String POST_INVITE = "/api/Guild/invite_apply_handle";//【新】受邀申请处理
public static final String POST_BIND_DETAIL = "/api/Bind/bind_detail";//绑定详情
public static final String POST_USER_WALL = "/api/User/user_gift_wall";//礼物墙
public static final String POST_USER_OLINE_STATUS = "/api/Room/user_online_status";//用户在线状态
@@ -385,7 +391,7 @@ public class Constants {
public static final String GET_THEME_DATA = "/api/Theme/get_theme_data";//主题接口
public static final String START_FRIEND = "/api/Friend/start_friend";//点击开始按钮 交友房
public static final String DELAY = "/api/Friend/delay";//点击延时 交友房
public static final String POST_KEEP_XINTIAO = "/api/Xintiao/keep_xintiao";//心跳
public static final String POST_KEEP_XINTIAO = "/api/Xintiao/keep_room_heartbeat";//心跳
public static final String END_FRIEND = "/api/Friend/end_friend";//点击结束 交友房
public static final String CREATE_RELATION = "/api/Friend/create_relation";//卡关系 (创建关系) 交友房
public static final String GET_BOX_GIFT_LIST = "/api/BlindBoxTurntable/get_gift_list";//获取活动礼物列表
@@ -411,7 +417,22 @@ public class Constants {
public static final String GET_NOBILITY_DETAIL = "/api/Nobility/get_nobility_detail";//爵位详情
public static final String GET_NOBILITY_LIST = "/api/Nobility/get_nobility_list";//爵位列表
public static final String GET_NOBILITY_PRICE = "/api/Nobility/get_nobility_price";//爵位购买价格
public static final String POST_SINGER_AUTH = "/api/SingerSong/singerAuth";//歌手认证
public static final String POST_GET_SONG = "/api/SingerSong/getSong";//获取用户的歌单
public static final String POST_SINGER_SONG = "/api/SingerSong/singerSong";//点歌
public static final String POST_SINGER_SONG_TOP = "/api/SingerSong/singerSongTop";//歌曲置顶
public static final String POST_SINGER_SONG_COUNT = "/api/SingerSong/singerSongCount";//点歌各类型各个总数
public static final String POST_SINGER_SONG_LIST = "/api/SingerSong/singerSongList";//点歌列表
public static final String POST_SINGER_SONG_CUT = "/api/SingerSong/singerSongCut";//切歌
public static final String POST_SINGER_ADD_SONG = "/api/SingerSong/singerAddSong";//歌手添加歌曲
public static final String POST_SINGER_DELETE_SONG = "/api/SingerSong/singerDelSong";//歌手删除 歌曲
public static final String POST_SINGER_UPDATE_SONG = "/api/SingerSong/singerEditSong";//歌手修改歌曲
public static final String POST_FRIEND_LIST = "/api/User/get_friend_list";//挚友列表
public static final String POST_FRIEND_LIST_MORE = "/api/User/get_friend_list_more";//挚友列表查看更多
public static final String POST_SEND_LOG = "api/Report/android_log_report";//上传log信息
public static final String GET_SKILL_LIST = "/api/Sign/skill_list";//才艺列表
public static final String POST_FREE_RE_SIGN = "/api/Sign/free_re_sign";//免费续约
public static final String POST_RE_SIGN = "/api/Sign/re_sign";//续签(花金币)
@@ -419,6 +440,12 @@ public class Constants {
public static final String BIND_MOBILE = "/api/UserData/bind_mobile";//手机绑定
public static final String POST_SIGN_START = "/api/Sign/start_sign";//签约开始
public static final String POST_SIGN_END = "/api/Sign/end_sign";//签约结束
public static final String POST_SIGN_DELAY = "/api/Sign/sign_delay";//签约延时
public static final String POST_SIGN_COIN_LIST = "/api/Sign/sign_coin_list";//签约出价价格列表
public static final String POST_SIGN_COIN = "/api/Sign/sign_coin";//签约出价
}

View File

@@ -0,0 +1,41 @@
package com.xscm.moduleutil.widget
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager
/**
* 项目名称:羽声语音
* 时间2025/12/3 9:30
* 用途:
*/
class CustomViewPager(context: Context, attrs: AttributeSet?) : ViewPager(context, attrs) {
private var initialX = 0f
private var initialY = 0f
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
// 记录初始触摸点
initialX = ev.x
initialY = ev.y
parent.requestDisallowInterceptTouchEvent(true) // 请求父容器不要拦截事件
}
MotionEvent.ACTION_MOVE -> {
val deltaX = Math.abs(ev.x - initialX)
val deltaY = Math.abs(ev.y - initialY)
// 如果水平滑动距离大于垂直滑动距离才认为是水平滑动ViewPager才拦截事件
if (deltaX > deltaY && deltaX > 30) { // 30是阈值可以根据需要调整
return super.onInterceptTouchEvent(ev)
}
// 否则,不拦截,让子视图处理
parent.requestDisallowInterceptTouchEvent(true)
return false
}
}
return super.onInterceptTouchEvent(ev)
}
}

View File

@@ -6,6 +6,7 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.xscm.moduleutil.bean.GiftBean;
import com.xscm.moduleutil.utils.roomview.RoomCPView;
import java.util.List;
import java.util.concurrent.ExecutorService;
@@ -20,6 +21,8 @@ public class QXGiftPlayerManager {
private GiftAnimView fullEffectView;
private GiftAnimView chatEffectView;
private RoomCPView roomCPView;
private Context context;
private QXGiftPlayerManager(Context context) {
@@ -39,6 +42,15 @@ public class QXGiftPlayerManager {
return bgEffectView;
}
public RoomCPView getRoomCPView(){
if (roomCPView==null){
initRoomCPView();
}
return roomCPView;
}
public GiftAnimView getDefaultFullEffectView() {
if (fullEffectView == null) {
initFullEffectView();
@@ -62,10 +74,25 @@ public class QXGiftPlayerManager {
bgEffectView.setBackgroundColor(0x00000000);
bgEffectView.setClickable(false); // userInteractionEnabled = NO
// 添加全屏特效视图聊天特效视图
// 添加全屏特效视图聊天特效视图和CP视图
((ViewGroup) bgEffectView).addView(getDefaultFullEffectView());
((ViewGroup) bgEffectView).addView(getDefaultChatEffectView());
((ViewGroup) bgEffectView).addView(getRoomCPView());
}
private void initRoomCPView() {
roomCPView=new RoomCPView(context);
roomCPView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
));
// 创建专用线程池替代GCD队列
ExecutorService queue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
Executors.defaultThreadFactory());
roomCPView.setQueue(queue);
}
public void displayFullEffectView(String gift) {
getDefaultFullEffectView().displayEffectView(gift);
}
@@ -78,6 +105,31 @@ public class QXGiftPlayerManager {
getDefaultChatEffectView().displayEffectView(gift);
}
/**
* 显示CP动画
* @param room_head1 头像1的URL
* @param room_head2 头像2的URL
* @param room_cp_name1 名称1
* @param room_cp_name2 名称2
* @param mp4Path MP4动画文件路径
*/
public void displayCPView(String room_head1, String room_head2, String room_cp_name1, String room_cp_name2, String mp4Path) {
getRoomCPView().displayEffectView(room_head1, room_head2, room_cp_name1, room_cp_name2, mp4Path);
}
/**
* 开启或关闭CP动画
* @param isShow 是否显示
*/
public void openOrCloseCPViewWith(boolean isShow) {
}
/**
* 停止CP动画
*/
public void stopCPPlay() {
}
public void openOrCloseEffectViewWith(boolean isShow) {
@@ -102,6 +154,12 @@ public class QXGiftPlayerManager {
chatEffectView = null;
}
if (roomCPView != null) {
// 先调用destroyEffectView方法它会自动从父视图中移除
roomCPView.destroyEffectView();
roomCPView = null;
}
if (bgEffectView != null) {
bgEffectView = null;
}
@@ -114,6 +172,8 @@ public class QXGiftPlayerManager {
if (chatEffectView != null) {
chatEffectView.stopPlay();
}
if (roomCPView != null) {
}
}
private void initFullEffectView() {

View File

@@ -74,7 +74,7 @@ public class RoomSingSongWheat2View extends BaseWheatView {
updateSexIcon();
// updateCharmViewVisibility(bean);
updatePkState(bean);
iv_on_line.setVisibility(GONE);
// iv_on_line.setVisibility(GONE);
}
private void handleOnState(RoomPitBean bean) {

View File

@@ -71,7 +71,7 @@ public class RoomSingSongWheatView extends BaseWheatView {
updateSexIcon();
updatePkState(bean);
iv_on_line.setVisibility(GONE);
// iv_on_line.setVisibility(GONE);
}
private void handleOnState(RoomPitBean bean) {

View File

@@ -29,11 +29,11 @@ class ShineTextView : AppCompatTextView {
//流光效果下字体流动次数
var shineCount: Int = Int.MAX_VALUE
//注入效果 开始,中间,结束
var startColor: Int = Color.WHITE
var shineColor: Int = Color.WHITE
var endColor: Int = Color.WHITE
var startColor: Int = Color.BLACK
var shineColor: Int = Color.BLACK
var endColor: Int = Color.BLACK
//一次动效时长
var shineDuration: Int = 400
var shineDuration: Int = 1000
var _count: Int = 0 //自行运行动画次数
@@ -77,7 +77,7 @@ class ShineTextView : AppCompatTextView {
mLinearGradient = LinearGradient(
0f,
0f,
(mViewWidth / 4).toFloat(),
(mViewWidth / 1).toFloat(),
0f,
intArrayOf(currentTextColor, shineColor, currentTextColor),
null,
@@ -104,7 +104,7 @@ class ShineTextView : AppCompatTextView {
0f,
0f,
0f,
intArrayOf(Color.TRANSPARENT,Color.TRANSPARENT),
intArrayOf(Color.BLACK,Color.BLACK),
null,
Shader.TileMode.CLAMP
)

View File

@@ -69,16 +69,18 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
private String user_id;
private String giftNumber = "";
private int point;
@Override
protected RewardGiftPresenter bindPresenter() {
return new RewardGiftPresenter(this, getActivity());
}
public static void show(String id,String userId,int point, FragmentManager fragmentManager) {
public static void show(String id, String userId, int point, FragmentManager fragmentManager) {
RewardGiftDialogFragment dialogFragment = new RewardGiftDialogFragment();
Bundle args = new Bundle();
args.putString("circle_id", id); // 可选:传递参数
args.putString("user_id", userId);
args.putInt("point",point);
args.putInt("point", point);
// 设置参数...
dialogFragment.setArguments(args);
dialogFragment.show(fragmentManager, "RewardGiftDialogFragment");
@@ -87,9 +89,9 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
circle_id=getArguments().getString("circle_id");
user_id=getArguments().getString("user_id");
point=getArguments().getInt("point");
circle_id = getArguments().getString("circle_id");
user_id = getArguments().getString("user_id");
point = getArguments().getInt("point");
}
@Override
@@ -97,12 +99,13 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
super.initDialogStyle(window);
window.setGravity(Gravity.BOTTOM);
}
@Override
protected void initData() {
MvpPre.getRewardList(circle_id, 1, 10);
MvpPre.getGiftLabel("1");
MvpPre.wallet();
mGiftNumList=new ArrayList<>();
mGiftNumList = new ArrayList<>();
mGiftNumList.add(new GiftNumBean("20", "x20"));
mGiftNumList.add(new GiftNumBean("15", "x15"));
mGiftNumList.add(new GiftNumBean("10", "x10"));
@@ -118,7 +121,7 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
@Override
protected void convert(BaseViewHolder helper, RewardUserBean item) {
GifAvatarOvalView gifAvatarOvalView = helper.getView(com.xscm.moduleutil.R.id.im_reward1);
if (item!=null ) {
if (item != null) {
ImageUtils.loadHeadCC(item.getAvatar(), helper.getView(com.xscm.moduleutil.R.id.im_reward1));
}
}
@@ -130,13 +133,13 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
mBinding.tvGive.setOnClickListener(this::onClisk);
float[] corners = {0f, 65f, 65f, 0f};
ThemeableDrawableUtils.setThemeableRoundedBackground( mBinding.tvGive, ColorManager.getInstance().getPrimaryColorInt(), corners);
ThemeableDrawableUtils.setThemeableRoundedBackground(mBinding.tvGive, ColorManager.getInstance().getPrimaryColorInt(), corners);
mBinding.tvGive.setTextColor(ColorManager.getInstance().getButtonColorInt());
mBinding.cz.setTextColor(ColorManager.getInstance().getPrimaryColorInt());
}
private void onClisk(View view1) {
if (view1.getId()==R.id.tv_give_coin_num){
if (view1.getId() == R.id.tv_give_coin_num) {
if (mSelectGiftNumPopupWindow == null) {
mSelectGiftNumPopupWindow = new SelectGiftNumPopupWindow(getSelfActivity(), (adapter, view, position) -> {
@@ -152,7 +155,7 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
}
});
} else {
mBinding.tvGiveCoinNum.setText(giftNumBean.getNumber());
mBinding.tvGiveCoinNum.setText(giftNumBean.getText());
}
mSelectGiftNumPopupWindow.dismiss();
});
@@ -160,12 +163,12 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
mSelectGiftNumPopupWindow.setData(mGiftNumList);
mSelectGiftNumPopupWindow.showAtLocation(mBinding.tvGiveCoinNum, Gravity.BOTTOM | Gravity.RIGHT, 100, 230);
}else if (view1.getId()== com.xscm.moduleutil.R.id.tv_reward_num){
RewardDialogFragment.show(circle_id,getChildFragmentManager());
}else if (view1.getId()== R.id.cz){
RechargeDialogFragment.show("",null, getActivity().getSupportFragmentManager(),"0","0");
}else if (view1.getId()== R.id.tv_give){
for (int i=0;i<mGiftNumList.size();i++) {
} else if (view1.getId() == com.xscm.moduleutil.R.id.tv_reward_num) {
RewardDialogFragment.show(circle_id, getChildFragmentManager());
} else if (view1.getId() == R.id.cz) {
RechargeDialogFragment.show("", null, getActivity().getSupportFragmentManager(), "0", "0");
} else if (view1.getId() == R.id.tv_give) {
for (int i = 0; i < mGiftNumList.size(); i++) {
if (mBinding.tvGiveCoinNum.getText().toString().equals(mGiftNumList.get(i).getText())) {
giftNumber = mGiftNumList.get(i).getNumber();
}
@@ -196,25 +199,24 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
mBinding.tvRewardTitle.setVisibility(View.VISIBLE);
}
}
private List<GiftLabelBean> giftLabelBeanList;
@Override
public void getGiftLabel(List<GiftLabelBean> giftLabelBeans) {
if (giftLabelBeans == null) return;
if (SpUtil.getShelf()==1){
for (GiftLabelBean giftLabelBean1 : giftLabelBeans){
if (giftLabelBean1.getId().equals("2")){
giftLabelBeans.remove(giftLabelBean1);
break;
}
for (GiftLabelBean giftLabelBean1 : giftLabelBeans) {
if (giftLabelBean1.getId().equals("2")) {
giftLabelBeans.remove(giftLabelBean1);
break;
}
}
mBinding.viewPager.setAdapter(new MyFragmentPagerAdapter(getChildFragmentManager(), giftLabelBeans,fragmentList,""));
mBinding.viewPager.setAdapter(new MyFragmentPagerAdapter(getChildFragmentManager(), giftLabelBeans, fragmentList, ""));
mBinding.slidingTabLayout.setViewPager(mBinding.viewPager);
mBinding.slidingTabLayout.setCurrentTab(0);
refreshCurrentGiftFragment(giftLabelBeans.get(0).getId(),2,"");
refreshCurrentGiftFragment(giftLabelBeans.get(0).getId(), 2, "");
mBinding.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
@@ -224,7 +226,7 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
@Override
public void onPageSelected(int position) {
// 当页面切换时,控制 tv_bb_qs 按钮的显示
refreshCurrentGiftFragment(giftLabelBeans.get(position).getId(),2,"");
refreshCurrentGiftFragment(giftLabelBeans.get(position).getId(), 2, "");
}
@Override
@@ -233,11 +235,13 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
}
});
}
private void refreshCurrentGiftFragment(String id,int type,String roomId) {
if (getCurrentGiftFragment()!=null){
getCurrentGiftFragment().loadDataIfNeeded(id,type,roomId);
private void refreshCurrentGiftFragment(String id, int type, String roomId) {
if (getCurrentGiftFragment() != null) {
getCurrentGiftFragment().loadDataIfNeeded(id, type, roomId);
}
}
private GiftTwoDetailsFragment getCurrentGiftFragment() {
int currentPosition = mBinding.viewPager.getCurrentItem();
// 使用 ViewPager 的 adapter 获取当前 fragment
@@ -251,10 +255,12 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
}
return null;
}
private int getSelectedGift() {
int currentItem = mBinding.viewPager.getCurrentItem();
return currentItem;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void userRefresh(GiftUserRefreshEvent event) {
if (event.addSelf) {
@@ -264,26 +270,27 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
private void giveGift(String num) {
getSelectedGift();
if (roonGiftModel == null) {
ToastUtils.show("请选择礼物");
return;
}
if (roonGiftModel == null) {
ToastUtils.show("请选择礼物");
return;
}
if (TextUtils.isEmpty(num)) {
ToastUtils.show("请选择打赏礼物数量");
return;
}
if (Integer.valueOf(num) <= 0) {
ToastUtils.show("请选择打赏礼物数量");
return;
}
if (TextUtils.isEmpty(num)) {
ToastUtils.show("请选择打赏礼物数量");
return;
}
if (Integer.valueOf(num) <= 0) {
ToastUtils.show("请选择打赏礼物数量");
return;
}
//礼物打赏
giftNumber = num;
MvpPre.reward_zone(circle_id, roonGiftModel.getGift_id(), num, "1");
//礼物打赏
giftNumber = num;
MvpPre.reward_zone(circle_id, roonGiftModel.getGift_id(), num, "1");
}
@Override
public void setGiftList(List<RoonGiftModel> roonGiftModels,int type) {
public void setGiftList(List<RoonGiftModel> roonGiftModels, int type) {
}
@@ -300,7 +307,7 @@ public class RewardGiftDialogFragment extends BaseMvpDialogFragment<RewardGiftPr
@Override
public void reward_zone() {
com.blankj.utilcode.util.ToastUtils.showShort("打赏成功");
EventBus.getDefault().post(new GiftRewardEvent(point,circle_id));
EventBus.getDefault().post(new GiftRewardEvent(point, circle_id));
dismiss();
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="2000"
android:fromYDelta="0"
android:toYDelta="-20"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:interpolator="@android:anim/accelerate_decelerate_interpolator" />
</set>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="180"
android:startColor="#C5FFC9"
android:centerColor="#F9E9FF"
android:endColor="#C7ECFA"
android:type="linear"
android:useLevel="true" />
<corners
android:bottomLeftRadius="12dp"
android:bottomRightRadius="12dp"
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
</shape>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="180"
android:centerColor="#fff9e9ff"
android:endColor="#ffc7d3fa"
android:startColor="#fffffac5"
android:type="linear"
android:useLevel="true" />
<corners
android:bottomLeftRadius="12dp"
android:bottomRightRadius="12dp"
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ff1b1926" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="14dp"
android:topRightRadius="14dp" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#2B2935"/>
<corners android:radius="@dimen/dp_16"/>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#3ABC6D"/>
<corners android:radius="@dimen/dp_16"/>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#3ABC6D" />
<corners android:radius="@dimen/dp_34"/>
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="@dimen/dp_48" />
<solid android:color="#FF8ACC" />
</shape>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="90"
android:startColor="#FFDAED"
android:centerColor="#ffd9ffe1"
android:endColor="#F3FF98"
android:type="linear"
android:useLevel="true" />
<corners
android:bottomLeftRadius="4dp"
android:bottomRightRadius="4dp"
android:topLeftRadius="4dp"
android:topRightRadius="4dp" />
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#73040404" />
<corners
android:bottomLeftRadius="53dp"
android:bottomRightRadius="53dp"
android:topLeftRadius="53dp"
android:topRightRadius="53dp" />
</shape>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="180"
android:startColor="#C2EBFF"
android:centerColor="#fff5d2f2"
android:endColor="#FFF6F0"
android:type="linear"
android:useLevel="true" />
<corners
android:bottomLeftRadius="6dp"
android:bottomRightRadius="6dp"
android:topLeftRadius="6dp"
android:topRightRadius="6dp" />
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#262431" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="14dp"
android:topRightRadius="14dp" />
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#AEEDFF"/>
<corners
android:topLeftRadius="8dp"
android:topRightRadius="8dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
</shape>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 背景填充颜色,如果你不需要内部填充颜色,可以设置为透明 -->
<solid android:color="@color/white" />
<!-- 边框设置 -->
<stroke
android:width="0.5dp"
android:color="#9FF9DF" />
<!-- 圆角设置 -->
<corners android:radius="99dp" /> <!-- 你可以根据需要调整圆角大小 -->
</shape>

View File

@@ -53,7 +53,10 @@
android:layout_alignParentStart="true"
android:layout_marginStart="@dimen/dp_20"
android:text="取消"
android:gravity="center"
android:textSize="@dimen/sp_14"
android:paddingHorizontal="@dimen/dp_20"
android:paddingVertical="@dimen/dp_10"
android:textColor="@color/color_FF999999"
android:background="@drawable/bg_r53_f3f3f3"
@@ -65,7 +68,11 @@
android:layout_height="@dimen/dp_42"
android:layout_centerInParent="true"
android:layout_alignParentEnd="true"
android:paddingHorizontal="@dimen/dp_20"
android:paddingVertical="@dimen/dp_10"
android:text="确认"
android:textSize="@dimen/sp_14"
android:gravity="center"
android:background="@drawable/cs"/>
</RelativeLayout>
</LinearLayout>

View File

@@ -40,7 +40,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_2"
android:textColor="#CCA882"
android:textColor="@color/white"
android:textSize="@dimen/sp_12"
app:isShine="false"
app:layout_constraintStart_toEndOf="@+id/avatar"

View File

@@ -21,7 +21,7 @@
android:gravity="center|left"
android:layout_margin="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_12"
android:text="全部评论(56)"
tools:text="全部评论(56)"
android:textColor="@color/color_FF333333"
android:textSize="@dimen/sp_16"
android:textStyle="bold" />

View File

@@ -86,6 +86,17 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/im_heartssss"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_heart"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:scaleType="fitCenter"
android:visibility="gone"
tools:visibility="visible"/>
<ImageView
android:id="@+id/iv_gift_select"
android:layout_width="match_parent"

View File

@@ -19,9 +19,44 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.8"
app:layout_constraintWidth_percent="0.95"
app:riv_oval="true" />
<com.xscm.moduleutil.widget.AvatarFrameView
android:id="@+id/iv_frame"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@null"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintWidth_percent="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.59" />
<ImageView
android:id="@+id/iv_frame_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:contentDescription="@null"
android:scaleType="fitXY"
app:layout_constraintHeight_default="spread"
app:layout_constraintTop_toTopOf="@+id/guideline"
app:layout_constraintWidth_default="spread"
tools:src="@mipmap/me_sj"
android:visibility="gone"/>
<ImageView
android:id="@+id/iv_sex"
android:layout_width="@dimen/dp_16"
@@ -32,35 +67,17 @@
app:layout_constraintEnd_toEndOf="@id/riv"
tools:visibility="visible" />
<com.xscm.moduleutil.widget.AvatarFrameView
android:id="@+id/iv_frame"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@null"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<ImageView
android:id="@+id/iv_frame_bg"
android:id="@+id/iv_master_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:contentDescription="@null"
android:scaleType="fitXY"
android:scaleType="fitCenter"
app:layout_constraintHeight_default="spread"
app:layout_constraintTop_toTopOf="@+id/guideline"
app:layout_constraintWidth_default="spread"
tools:src="@mipmap/me_sj" />
tools:src="@mipmap/icon_master"
android:visibility="gone"/>
<ImageView
android:id="@+id/iv_online"

View File

@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false">
<com.tencent.qgame.animplayer.AnimView
android:id="@+id/anim_cp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.58" />
<LinearLayout
android:id="@+id/ll_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/guideline">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.xscm.moduleutil.widget.CircularImage
android:id="@+id/room_cp_head1"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@mipmap/ic_launcher_app"
app:riv_oval="true" />
<TextView
android:id="@+id/room_cp_name1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:enabled="true"
android:maxEms="5"
android:paddingLeft="10dp"
android:paddingTop="2dp"
android:paddingRight="10dp"
android:paddingBottom="2dp"
android:singleLine="true"
android:textColor="@color/color_999999"
android:textSize="8sp"
tools:text="" />
</LinearLayout>
<View
android:layout_width="@dimen/dp_40"
android:layout_height="0dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.xscm.moduleutil.widget.CircularImage
android:id="@+id/room_cp_head2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@mipmap/ic_launcher_app"
app:riv_oval="true" />
<TextView
android:id="@+id/room_cp_name2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:enabled="true"
android:maxEms="5"
android:paddingLeft="10dp"
android:paddingTop="2dp"
android:paddingRight="10dp"
android:paddingBottom="2dp"
android:singleLine="true"
android:textColor="@color/color_999999"
android:textSize="8sp"
tools:text="" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -207,6 +207,7 @@
android:layout_height="0dp"
android:background="@mipmap/room_ic_owner_offline"
android:visibility="gone"
android:tint="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"

View File

@@ -18,7 +18,7 @@
android:layout_centerInParent="true"
android:layout_alignParentStart="true"
android:layout_marginStart="@dimen/dp_3"
android:src="@mipmap/room_ic_wheat_charm" />
android:src="@mipmap/icon_heart_left_bg" />
<TextView
android:id="@+id/tv_value"
@@ -27,13 +27,12 @@
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:layout_toEndOf="@+id/im"
android:layout_marginStart="@dimen/dp_2"
android:ellipsize="none"
android:gravity="center"
android:text="0"
android:minWidth="@dimen/dp_40"
android:singleLine="true"
android:textColor="@color/white"
android:textSize="@dimen/sp_10" />
android:textSize="@dimen/sp_8" />
</RelativeLayout>
</layout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Some files were not shown because too many files have changed in this diff Show More