1:添加小时榜

2:添加小时榜飘屏
This commit is contained in:
2025-09-30 10:20:26 +08:00
parent 855555e9af
commit 3b117060d3
34 changed files with 1579 additions and 789 deletions

View File

@@ -18,6 +18,9 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -37,6 +40,7 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
@@ -50,6 +54,7 @@ import com.xscm.moduleutil.R;
import com.xscm.moduleutil.base.CommonAppContext;
import com.xscm.moduleutil.base.RoomManager;
import com.xscm.moduleutil.bean.XLHBean;
import com.xscm.moduleutil.event.HourlyBean;
import com.xscm.moduleutil.event.MqttBean;
import com.xscm.moduleutil.utils.ARouteConstants;
import com.xscm.moduleutil.utils.BackgroundManager;
@@ -66,6 +71,7 @@ import org.greenrobot.eventbus.ThreadMode;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -410,6 +416,232 @@ public abstract class BaseAppCompatActivity<VDB extends ViewDataBinding> extends
private View currentMqttView = null; // 当前正在播放的MQTT视图
private View currentXlhView = null; // 当前正在播放的XLH视图
private final List<HourlyBean> hourlyMessageQueue = new ArrayList<>(); // 小时榜消息队列
private final Map<Integer, View> currentHourlyViews = new HashMap<>(); // 当前显示的小时榜视图
private final Object hourlyQueueLock = new Object(); // 小时榜队列同步锁
private boolean isHourlyProcessing = false; // 小时榜处理状态标志
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageReceived(List<HourlyBean> hourlyBean) {
LogUtils.e("收到小时榜", hourlyBean);
if (hourlyBean == null) return;
if (SpUtil.getFloatingScreen() == 1) {
synchronized (hourlyQueueLock) {
hourlyMessageQueue.addAll(hourlyBean);
if (!isHourlyProcessing) {
isHourlyProcessing = true;
processHourlyMessages();
}
}
}else {
hourlyMessageQueue.clear();
clearAllHourlyViews();
}
}
private void processHourlyMessages() {
List<HourlyBean> messagesToProcess;
synchronized (hourlyQueueLock) {
if (hourlyMessageQueue.isEmpty()) {
isHourlyProcessing = false;
return;
}
// 最多处理3条数据
int processCount = Math.min(3, hourlyMessageQueue.size());
messagesToProcess = new ArrayList<>(hourlyMessageQueue.subList(0, processCount));
// 从队列中移除已处理的数据
for (int i = 0; i < processCount; i++) {
hourlyMessageQueue.remove(0);
}
}
// 同时展示多条数据
for (int i = 0; i < messagesToProcess.size(); i++) {
HourlyBean bean = messagesToProcess.get(i);
showHourlyFloatingMessage(bean, i);
}
}
private void showHourlyFloatingMessage(HourlyBean hourlyBean, int positionIndex) {
try {
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
// 创建新的视图
View hourlyView = LayoutInflater.from(this).inflate(R.layout.item_hourly_floating, null);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
// 根据位置设置不同的垂直间距
int baseMargin = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 70);
int verticalSpacing = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 50);
layoutParams.topMargin = baseMargin + (positionIndex * verticalSpacing);
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
hourlyView.setLayoutParams(layoutParams);
decorView.addView(hourlyView);
// 保存视图引用
currentHourlyViews.put(positionIndex, hourlyView);
// 更新视图数据
updateHourlyFloatingViewData(hourlyView, hourlyBean);
// 根据类型获取展示时间
long displayDuration = getDisplayDurationByType(Integer.parseInt(hourlyBean.getRank_number()));
// 启动动画
resetAndStartHourlyAnimation(hourlyView, displayDuration, () -> {
// 动画结束后清理视图
if (hourlyView.getParent() != null) {
decorView.removeView(hourlyView);
}
currentHourlyViews.remove(positionIndex);
// 检查是否还有更多消息需要处理
synchronized (hourlyQueueLock) {
if (hourlyMessageQueue.isEmpty() && currentHourlyViews.isEmpty()) {
isHourlyProcessing = false;
} else if (!hourlyMessageQueue.isEmpty() && currentHourlyViews.isEmpty()) {
// 所有当前视图都已消失,处理下一批消息
processHourlyMessages();
}
}
});
} catch (Exception e) {
LogUtils.e("显示小时榜飘屏失败", e);
}
}
private long getDisplayDurationByType(int type) {
// 根据不同类型设置不同的展示时间(毫秒)
switch (type) {
case 1: // 第一名
return 5000; // 5秒
case 2: // 第二名
return 4000; // 4秒
case 3: // 第三名
return 3000; // 3秒
default:
return 3000; // 默认3秒
}
}
private void updateHourlyFloatingViewData(View view, HourlyBean hourlyBean) {
TextView tvName = view.findViewById(R.id.tv_name);
ImageView ivAvatar = view.findViewById(R.id.im_h_t);
if (hourlyBean != null) {
// 根据排名设置不同的显示
switch (hourlyBean.getRank_number()) {
case "1":
// tvName.setText("新科状元! ["+hourlyBean.getRoom_name()+"] 独占鳌头!");
setColoredText(tvName, "新科状元! [", hourlyBean.getRoom_name(), "] 独占鳌头!", R.color.color_FFFA63);
ivAvatar.setImageResource(R.mipmap.hourl_top1);
break;
case "2":
// tvName.setText("金榜榜眼! ["+hourlyBean.getRoom_name()+"] 才气逼人!");
setColoredText(tvName, "金榜榜眼! [", hourlyBean.getRoom_name(), "] 才气逼人!", R.color.color_FFFA63);
ivAvatar.setImageResource(R.mipmap.hourl_top2);
break;
case "3":
setColoredText(tvName, "风采探花! [", hourlyBean.getRoom_name(), "] 实力绽放!", R.color.color_1FFFE5);
// tvName.setText("风采探花! ["+hourlyBean.getRoom_name()+"] 实力绽放!");
ivAvatar.setImageResource(R.mipmap.hourl_top3);
break;
default:
break;
}
}
}
// 设置带颜色的文本
// 设置带颜色的文本
private void setColoredText(TextView textView, String prefix, String roomName, String suffix, int colorRes) {
String fullText = prefix + roomName + suffix;
SpannableStringBuilder builder = new SpannableStringBuilder(fullText);
// 先为整个文本设置白色
builder.setSpan(
new ForegroundColorSpan(ContextCompat.getColor(this, R.color.white)),
0,
fullText.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
// 查找房间名在文本中的位置
int start = fullText.indexOf("[");
int end = fullText.indexOf("]") + 1;
if (start >= 0 && end > start) {
// 为房间名部分设置指定颜色
builder.setSpan(
new ForegroundColorSpan(ContextCompat.getColor(this, colorRes)),
start,
end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
textView.setText(builder);
}
private void resetAndStartHourlyAnimation(View view, long displayDuration, Runnable onAnimationEnd) {
try {
int screenWidth = getScreenWidth();
// 设置初始位置:在屏幕右侧外部
view.setTranslationX(screenWidth);
// 进入动画
ObjectAnimator enterAnimator = ObjectAnimator.ofFloat(view, "translationX", screenWidth, 0f);
enterAnimator.setDuration(500);
enterAnimator.setInterpolator(new DecelerateInterpolator());
enterAnimator.start();
// 停留后退出动画
view.postDelayed(() -> {
try {
ObjectAnimator exitAnimator = ObjectAnimator.ofFloat(view, "translationX", 0f, -screenWidth);
exitAnimator.setDuration(500);
exitAnimator.setInterpolator(new AccelerateInterpolator());
exitAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
onAnimationEnd.run();
}
@Override
public void onAnimationCancel(Animator animation) {
onAnimationEnd.run();
}
});
exitAnimator.start();
} catch (Exception e) {
LogUtils.e("小时榜退出动画执行失败", e);
onAnimationEnd.run();
}
}, displayDuration); // 根据类型设置的展示时间
} catch (Exception e) {
LogUtils.e("小时榜动画启动失败", e);
onAnimationEnd.run();
}
}
private void clearAllHourlyViews() {
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
for (View view : currentHourlyViews.values()) {
if (view.getParent() != null) {
decorView.removeView(view);
}
}
currentHourlyViews.clear();
}
/// 礼物特效 - MQTT消息处理
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageReceived(MqttBean mqttBean) {