2025-08-26 19:34:44 +08:00
|
|
|
|
package com.xscm.moduleutil.activity;
|
|
|
|
|
|
|
2025-09-05 21:39:42 +08:00
|
|
|
|
import static androidx.core.content.ContextCompat.getSystemService;
|
|
|
|
|
|
|
2025-09-24 00:30:40 +08:00
|
|
|
|
import static com.xscm.moduleutil.base.CommonAppContext.postDelayed;
|
|
|
|
|
|
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import android.animation.Animator;
|
|
|
|
|
|
import android.animation.AnimatorListenerAdapter;
|
2025-09-23 14:39:49 +08:00
|
|
|
|
import android.animation.AnimatorSet;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import android.animation.ObjectAnimator;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import android.content.BroadcastReceiver;
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
|
import android.content.IntentFilter;
|
|
|
|
|
|
import android.content.res.Resources;
|
|
|
|
|
|
import android.graphics.drawable.Drawable;
|
2025-09-05 21:39:42 +08:00
|
|
|
|
import android.net.Uri;
|
|
|
|
|
|
import android.os.Build;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import android.os.Bundle;
|
2025-10-09 09:26:16 +08:00
|
|
|
|
import android.os.Handler;
|
2025-09-05 21:39:42 +08:00
|
|
|
|
import android.provider.Settings;
|
2025-09-30 10:20:26 +08:00
|
|
|
|
import android.text.Spannable;
|
|
|
|
|
|
import android.text.SpannableStringBuilder;
|
|
|
|
|
|
import android.text.style.ForegroundColorSpan;
|
2025-09-23 14:39:49 +08:00
|
|
|
|
import android.util.DisplayMetrics;
|
2025-09-09 19:18:06 +08:00
|
|
|
|
import android.view.Gravity;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import android.view.LayoutInflater;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import android.view.MotionEvent;
|
|
|
|
|
|
import android.view.View;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import android.view.ViewGroup;
|
2025-09-23 14:39:49 +08:00
|
|
|
|
import android.view.animation.AccelerateInterpolator;
|
2025-09-24 00:30:40 +08:00
|
|
|
|
import android.view.animation.Animation;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import android.view.animation.DecelerateInterpolator;
|
2025-09-24 00:30:40 +08:00
|
|
|
|
import android.view.animation.TranslateAnimation;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import android.view.inputmethod.InputMethodManager;
|
|
|
|
|
|
import android.widget.EditText;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
|
import android.widget.ImageView;
|
|
|
|
|
|
import android.widget.TextView;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.Nullable;
|
2025-09-05 21:39:42 +08:00
|
|
|
|
import androidx.appcompat.app.AlertDialog;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
2025-09-30 10:20:26 +08:00
|
|
|
|
import androidx.core.content.ContextCompat;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import androidx.databinding.DataBindingUtil;
|
|
|
|
|
|
import androidx.databinding.ViewDataBinding;
|
|
|
|
|
|
|
|
|
|
|
|
import com.alibaba.android.arouter.launcher.ARouter;
|
|
|
|
|
|
import com.blankj.utilcode.util.ActivityUtils;
|
|
|
|
|
|
import com.blankj.utilcode.util.BarUtils;
|
2025-09-09 19:18:06 +08:00
|
|
|
|
import com.blankj.utilcode.util.LogUtils;
|
2025-09-05 21:39:42 +08:00
|
|
|
|
import com.hjq.toast.ToastUtils;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo;
|
|
|
|
|
|
import com.xscm.moduleutil.R;
|
|
|
|
|
|
import com.xscm.moduleutil.base.CommonAppContext;
|
2025-09-23 14:39:49 +08:00
|
|
|
|
import com.xscm.moduleutil.base.RoomManager;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import com.xscm.moduleutil.bean.XLHBean;
|
2025-09-30 10:20:26 +08:00
|
|
|
|
import com.xscm.moduleutil.event.HourlyBean;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import com.xscm.moduleutil.event.MqttBean;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import com.xscm.moduleutil.utils.ARouteConstants;
|
|
|
|
|
|
import com.xscm.moduleutil.utils.BackgroundManager;
|
|
|
|
|
|
import com.xscm.moduleutil.utils.ColorManager;
|
|
|
|
|
|
import com.xscm.moduleutil.utils.DisplayUtil;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
import com.xscm.moduleutil.utils.ImageUtils;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import com.xscm.moduleutil.utils.SpUtil;
|
2025-09-24 00:30:40 +08:00
|
|
|
|
import com.xscm.moduleutil.utils.SystemUtils;
|
|
|
|
|
|
import com.xscm.moduleutil.widget.QXGiftDriftView;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
|
|
|
|
|
|
import org.greenrobot.eventbus.EventBus;
|
|
|
|
|
|
import org.greenrobot.eventbus.Subscribe;
|
|
|
|
|
|
import org.greenrobot.eventbus.ThreadMode;
|
|
|
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
|
|
import java.util.ArrayList;
|
2025-09-30 10:20:26 +08:00
|
|
|
|
import java.util.HashMap;
|
2025-08-26 19:34:44 +08:00
|
|
|
|
import java.util.List;
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
|
|
public abstract class BaseAppCompatActivity<VDB extends ViewDataBinding> extends AppCompatActivity
|
|
|
|
|
|
implements BackgroundManager.BackgroundUpdateListener, ColorManager.ColorChangeListener {
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
protected void attachBaseContext(Context newBase) {
|
2025-09-06 14:19:23 +08:00
|
|
|
|
// 设置字体缩放比例为1.0f,即不跟随系统字体大小变化
|
|
|
|
|
|
super.attachBaseContext(DisplayUtil.attachBaseContext(newBase, 1.0f));
|
2025-08-26 19:34:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected VDB mBinding;
|
|
|
|
|
|
private static final List<BaseMvpActivity> activityList = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// private LoadingDialog mLoadingDialog;
|
|
|
|
|
|
// 添加广播接收器成员变量
|
|
|
|
|
|
private BroadcastReceiver mLogoutReceiver = new BroadcastReceiver() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
|
|
if ("com.xscm.moduleutil.ACTION_USER_LOGOUT".equals(intent.getAction())) {
|
|
|
|
|
|
// 在这里处理用户登出后的UI更新
|
|
|
|
|
|
// 例如:隐藏需要登录才能显示的控件
|
|
|
|
|
|
// 或者跳转到登录状态的页面
|
|
|
|
|
|
handleUserLogout();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 处理用户登出的方法
|
|
|
|
|
|
protected void handleUserLogout() {
|
|
|
|
|
|
// 子类可以重写此方法处理具体的登出逻辑
|
|
|
|
|
|
// 例如:更新UI状态、清除本地数据等
|
|
|
|
|
|
|
|
|
|
|
|
ActivityUtils.finishAllActivities();
|
|
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-24 00:30:40 +08:00
|
|
|
|
QXGiftDriftView qxGiftDriftView;
|
2025-10-09 09:26:16 +08:00
|
|
|
|
|
2025-08-26 19:34:44 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
|
getWindow().getDecorView().setBackgroundResource(R.mipmap.log_bj);
|
|
|
|
|
|
setContentView(getLayoutId());
|
|
|
|
|
|
// 隐藏标题栏
|
|
|
|
|
|
if (getSupportActionBar() != null) {
|
|
|
|
|
|
getSupportActionBar().hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
mBinding = DataBindingUtil.setContentView(this, getLayoutId());
|
|
|
|
|
|
mBinding.setLifecycleOwner(this);
|
|
|
|
|
|
ARouter.getInstance().inject(this);
|
|
|
|
|
|
BarUtils.setStatusBarLightMode(this, isLightMode());
|
|
|
|
|
|
BarUtils.transparentStatusBar(this);
|
|
|
|
|
|
initView();
|
|
|
|
|
|
initData();
|
|
|
|
|
|
initCompleted();
|
|
|
|
|
|
|
|
|
|
|
|
// 注册背景更新监听器
|
|
|
|
|
|
BackgroundManager.getInstance().addListener(this);
|
|
|
|
|
|
// 尝试加载网络背景
|
|
|
|
|
|
loadNetworkBackground();
|
|
|
|
|
|
// 注册颜色变化监听器
|
|
|
|
|
|
ColorManager.getInstance().addColorChangeListener(this);
|
|
|
|
|
|
|
|
|
|
|
|
// 注册登出广播接收器
|
|
|
|
|
|
IntentFilter filter = new IntentFilter("com.xscm.moduleutil.ACTION_USER_LOGOUT");
|
|
|
|
|
|
registerReceiver(mLogoutReceiver, filter);
|
|
|
|
|
|
|
|
|
|
|
|
// 动态判断是否包含 @Subscribe 注解的方法
|
|
|
|
|
|
boolean hasSubscribeMethods = false;
|
|
|
|
|
|
for (Method method : getClass().getDeclaredMethods()) {
|
|
|
|
|
|
if (method.isAnnotationPresent(Subscribe.class)) {
|
|
|
|
|
|
hasSubscribeMethods = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (hasSubscribeMethods) {
|
|
|
|
|
|
EventBus.getDefault().register(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-09 09:26:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 启动定时器
|
|
|
|
|
|
// startTimer();
|
|
|
|
|
|
|
2025-09-05 21:39:42 +08:00
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-05 21:39:42 +08:00
|
|
|
|
// 在Activity中
|
|
|
|
|
|
private static final int REQUEST_OVERLAY_PERMISSION = 1001;
|
|
|
|
|
|
|
|
|
|
|
|
private void checkAndRequestOverlayPermission() {
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
|
|
|
|
if (!Settings.canDrawOverlays(this)) {
|
|
|
|
|
|
new AlertDialog.Builder(this)
|
|
|
|
|
|
.setTitle("需要悬浮窗权限")
|
|
|
|
|
|
.setMessage("应用需要悬浮窗权限才能显示飘屏效果")
|
|
|
|
|
|
.setPositiveButton("去设置", (dialog, which) -> {
|
|
|
|
|
|
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
|
|
|
|
|
Uri.parse("package:" + getPackageName()));
|
|
|
|
|
|
startActivityForResult(intent, REQUEST_OVERLAY_PERMISSION);
|
|
|
|
|
|
})
|
|
|
|
|
|
.setNegativeButton("取消", null)
|
|
|
|
|
|
.show();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
|
|
if (requestCode == REQUEST_OVERLAY_PERMISSION) {
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
|
|
|
|
if (Settings.canDrawOverlays(this)) {
|
|
|
|
|
|
ToastUtils.show("已获得悬浮窗权限");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ToastUtils.show("未获得悬浮窗权限");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-26 19:34:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void finishAll() {
|
|
|
|
|
|
for (BaseMvpActivity activity : activityList) {
|
|
|
|
|
|
if (!activity.isFinishing()) {
|
|
|
|
|
|
activity.finish();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onColorChanged() {
|
|
|
|
|
|
// 在主线程中更新UI
|
|
|
|
|
|
runOnUiThread(this::updateUIColors);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 子类可以重写此方法来更新UI颜色
|
|
|
|
|
|
protected void updateUIColors() {
|
|
|
|
|
|
// 默认实现,子类可以覆盖
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-09 09:26:16 +08:00
|
|
|
|
//在类中添加以下成员变量
|
|
|
|
|
|
private Handler timerHandler = new Handler();
|
|
|
|
|
|
private Runnable timerRunnable = new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
// 调用你要执行的方法
|
|
|
|
|
|
// executePeriodicTask();
|
|
|
|
|
|
|
|
|
|
|
|
// 每10秒执行一次
|
|
|
|
|
|
timerHandler.postDelayed(this, 10000);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 启动定时器的方法
|
|
|
|
|
|
private void startTimer() {
|
|
|
|
|
|
timerHandler.postDelayed(timerRunnable, 10000);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 你需要定期执行的方法
|
|
|
|
|
|
private void executePeriodicTask() {
|
|
|
|
|
|
// 在这里实现你的业务逻辑
|
|
|
|
|
|
LogUtils.d("定时任务执行中...");
|
|
|
|
|
|
List<HourlyBean> hourlyBeans = new ArrayList<>();
|
|
|
|
|
|
HourlyBean hourlyBean = new HourlyBean();
|
|
|
|
|
|
hourlyBean.setText("nihao");
|
|
|
|
|
|
hourlyBean.setRank_number("1");
|
|
|
|
|
|
hourlyBean.setRoom_name("夏末");
|
|
|
|
|
|
hourlyBean.setRoom_id("1");
|
|
|
|
|
|
hourlyBeans.add(hourlyBean);
|
|
|
|
|
|
onMessageReceived(hourlyBeans);
|
|
|
|
|
|
}
|
2025-08-26 19:34:44 +08:00
|
|
|
|
|
|
|
|
|
|
protected void loadNetworkBackground() {
|
|
|
|
|
|
// 只有当已经有背景URL时才加载
|
|
|
|
|
|
String backgroundUrl = BackgroundManager.getInstance().getBackgroundUrl();
|
|
|
|
|
|
if (backgroundUrl != null && !backgroundUrl.isEmpty()) {
|
|
|
|
|
|
// 检查是否有已加载的drawable
|
|
|
|
|
|
Drawable cachedDrawable = BackgroundManager.getInstance().getBackgroundDrawable();
|
|
|
|
|
|
if (cachedDrawable != null) {
|
|
|
|
|
|
getWindow().getDecorView().setBackground(cachedDrawable);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 加载网络背景
|
|
|
|
|
|
BackgroundManager.getInstance().loadBackgroundDrawable(this, new BackgroundManager.BackgroundLoadCallback() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onLoadSuccess(Drawable drawable) {
|
|
|
|
|
|
getWindow().getDecorView().setBackground(drawable);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onLoadFailed() {
|
|
|
|
|
|
// 加载失败时使用默认背景
|
|
|
|
|
|
getWindow().getDecorView().setBackgroundResource(R.mipmap.activity_bj);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onBackgroundUpdated(Drawable drawable) {
|
|
|
|
|
|
// 当背景更新时,更新当前Activity的背景
|
|
|
|
|
|
if (drawable != null) {
|
|
|
|
|
|
getWindow().getDecorView().setBackground(drawable);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提供一个方法供子类调用,用于设置背景URL
|
|
|
|
|
|
protected void setNetworkBackgroundUrl(String url) {
|
|
|
|
|
|
BackgroundManager.getInstance().setBackgroundUrl(url);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public Resources getResources() {//禁止app字体大小跟随系统字体大小调节
|
|
|
|
|
|
Resources resources = super.getResources();
|
|
|
|
|
|
if (resources != null && resources.getConfiguration().fontScale != 1.0f) {
|
|
|
|
|
|
android.content.res.Configuration configuration = resources.getConfiguration();
|
|
|
|
|
|
configuration.fontScale = 1.0f;
|
|
|
|
|
|
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
|
|
|
|
|
|
}
|
|
|
|
|
|
return resources;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float fontScale = 1f;
|
|
|
|
|
|
|
|
|
|
|
|
// @Override
|
|
|
|
|
|
// public Resources getResources() {
|
|
|
|
|
|
// Resources resources = super.getResources();
|
|
|
|
|
|
// return DisplayUtil.getResources(this,resources,fontScale);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
public void setFontScale(float fontScale) {
|
|
|
|
|
|
this.fontScale = fontScale;
|
|
|
|
|
|
DisplayUtil.recreate(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public boolean isLightMode() {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected abstract void initData();
|
|
|
|
|
|
|
|
|
|
|
|
protected abstract void initView();
|
|
|
|
|
|
|
|
|
|
|
|
protected void initCompleted() {
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected abstract int getLayoutId();
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
protected void onDestroy() {
|
2025-09-09 19:18:06 +08:00
|
|
|
|
|
|
|
|
|
|
// 清理MQTT相关资源
|
|
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
|
mqttMessageQueue.clear();
|
|
|
|
|
|
isMqttPlaying = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 清理XLH相关资源
|
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
|
xlhMessageQueue.clear();
|
|
|
|
|
|
isXlhPlaying = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 移除当前显示的视图
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (currentMqttView != null && currentMqttView.getParent() != null) {
|
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentMqttView.getParent();
|
|
|
|
|
|
parent.removeView(currentMqttView);
|
|
|
|
|
|
}
|
|
|
|
|
|
currentMqttView = null;
|
|
|
|
|
|
|
|
|
|
|
|
if (currentXlhView != null && currentXlhView.getParent() != null) {
|
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentXlhView.getParent();
|
|
|
|
|
|
parent.removeView(currentXlhView);
|
|
|
|
|
|
}
|
|
|
|
|
|
currentXlhView = null;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
LogUtils.e("清理飘屏视图失败", e);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-26 19:34:44 +08:00
|
|
|
|
// 移除背景更新监听器
|
|
|
|
|
|
BackgroundManager.getInstance().removeListener(this);
|
|
|
|
|
|
// 移除颜色变化监听器
|
|
|
|
|
|
ColorManager.getInstance().removeColorChangeListener(this);
|
|
|
|
|
|
if (mBinding != null) {
|
|
|
|
|
|
mBinding.unbind();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (EventBus.getDefault().isRegistered(this)) {
|
|
|
|
|
|
EventBus.getDefault().unregister(this);
|
|
|
|
|
|
}
|
2025-09-09 19:18:06 +08:00
|
|
|
|
try {
|
|
|
|
|
|
unregisterReceiver(mLogoutReceiver);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
// 忽略异常
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-26 19:34:44 +08:00
|
|
|
|
try {
|
|
|
|
|
|
unregisterReceiver(mLogoutReceiver);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
// 忽略异常
|
|
|
|
|
|
}
|
|
|
|
|
|
super.onDestroy();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void showLoading(String content) {
|
|
|
|
|
|
// if (mLoadingDialog == null) {
|
|
|
|
|
|
// mLoadingDialog = new LoadingDialog(this);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// if (!mLoadingDialog.isShowing()) {
|
|
|
|
|
|
// mLoadingDialog.show();
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void showLoading() {
|
|
|
|
|
|
// if (mLoadingDialog == null) {
|
|
|
|
|
|
// mLoadingDialog = new LoadingDialog(this);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// if (!mLoadingDialog.isShowing()) {
|
|
|
|
|
|
// mLoadingDialog.show();
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void disLoading() {
|
|
|
|
|
|
// if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
|
|
|
|
|
|
// mLoadingDialog.dismiss();
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public boolean dispatchTouchEvent(MotionEvent ev) {
|
|
|
|
|
|
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
|
|
|
|
|
View view = getCurrentFocus();
|
|
|
|
|
|
if (isShouldHideInput(view, ev)) {
|
|
|
|
|
|
InputMethodManager Object = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
|
|
|
|
if (Object != null) {
|
|
|
|
|
|
Object.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
|
|
|
return super.dispatchTouchEvent(ev);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//判断是否隐藏键盘
|
|
|
|
|
|
public boolean isShouldHideInput(View v, MotionEvent event) {
|
|
|
|
|
|
if (v != null && (v instanceof EditText)) {
|
|
|
|
|
|
int[] leftTop = {0, 0};
|
|
|
|
|
|
//获取输入框当前的location位置
|
|
|
|
|
|
v.getLocationInWindow(leftTop);
|
|
|
|
|
|
int left = leftTop[0];
|
|
|
|
|
|
int top = leftTop[1];
|
|
|
|
|
|
int bottom = top + v.getHeight();
|
|
|
|
|
|
int right = left + v.getWidth();
|
|
|
|
|
|
if (event.getX() > left && event.getX() < right
|
|
|
|
|
|
&& event.getY() > top && event.getY() < bottom) {
|
|
|
|
|
|
// 点击的是输入框区域,保留点击EditText的事件
|
|
|
|
|
|
return false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-06 19:28:18 +08:00
|
|
|
|
|
|
|
|
|
|
/// 礼物特效
|
2025-09-09 19:18:06 +08:00
|
|
|
|
// 在类中添加以下成员变量
|
2025-09-19 02:28:02 +08:00
|
|
|
|
private final List<MqttBean.ListBean> mqttMessageQueue = new ArrayList<>(); // MQTT消息队列
|
2025-09-09 19:18:06 +08:00
|
|
|
|
private final List<XLHBean> xlhMessageQueue = new ArrayList<>(); // XLH消息队列
|
|
|
|
|
|
private boolean isMqttPlaying = false; // MQTT播放状态标志
|
|
|
|
|
|
private boolean isXlhPlaying = false; // XLH播放状态标志
|
|
|
|
|
|
private final Object mqttQueueLock = new Object(); // MQTT队列同步锁
|
|
|
|
|
|
private final Object xlhQueueLock = new Object(); // XLH队列同步锁
|
|
|
|
|
|
private View currentMqttView = null; // 当前正在播放的MQTT视图
|
|
|
|
|
|
private View currentXlhView = null; // 当前正在播放的XLH视图
|
|
|
|
|
|
|
2025-09-30 10:20:26 +08:00
|
|
|
|
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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-09 09:26:16 +08:00
|
|
|
|
} else {
|
2025-09-30 10:20:26 +08:00
|
|
|
|
hourlyMessageQueue.clear();
|
|
|
|
|
|
clearAllHourlyViews();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void processHourlyMessages() {
|
|
|
|
|
|
List<HourlyBean> messagesToProcess;
|
|
|
|
|
|
synchronized (hourlyQueueLock) {
|
|
|
|
|
|
if (hourlyMessageQueue.isEmpty()) {
|
|
|
|
|
|
isHourlyProcessing = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-09-30 19:52:56 +08:00
|
|
|
|
// 每次只处理1条数据
|
|
|
|
|
|
messagesToProcess = new ArrayList<>();
|
|
|
|
|
|
messagesToProcess.add(hourlyMessageQueue.remove(0));
|
2025-09-30 10:20:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-30 19:52:56 +08:00
|
|
|
|
// 只展示一条数据
|
|
|
|
|
|
HourlyBean bean = messagesToProcess.get(0);
|
|
|
|
|
|
showHourlyFloatingMessage(bean, 0);
|
2025-09-30 10:20:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
2025-09-30 19:52:56 +08:00
|
|
|
|
// 设置固定的垂直位置
|
2025-09-30 10:20:26 +08:00
|
|
|
|
int baseMargin = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 70);
|
2025-09-30 19:52:56 +08:00
|
|
|
|
layoutParams.topMargin = baseMargin;
|
2025-09-30 10:20:26 +08:00
|
|
|
|
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) {
|
2025-09-30 19:52:56 +08:00
|
|
|
|
if (hourlyMessageQueue.isEmpty()) {
|
2025-09-30 10:20:26 +08:00
|
|
|
|
isHourlyProcessing = false;
|
2025-09-30 19:52:56 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 当前视图消失后处理下一条消息
|
2025-09-30 10:20:26 +08:00
|
|
|
|
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:
|
2025-10-09 09:26:16 +08:00
|
|
|
|
tvName.setVisibility(View.GONE);
|
|
|
|
|
|
ivAvatar.setVisibility(View.GONE);
|
2025-09-30 10:20:26 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-09 09:26:16 +08:00
|
|
|
|
}
|
2025-09-30 10:20:26 +08:00
|
|
|
|
}
|
2025-10-09 09:26:16 +08:00
|
|
|
|
|
2025-09-30 10:20:26 +08:00
|
|
|
|
// 设置带颜色的文本
|
|
|
|
|
|
// 设置带颜色的文本
|
|
|
|
|
|
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();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
/// 礼物特效 - MQTT消息处理
|
2025-09-06 14:19:23 +08:00
|
|
|
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
|
|
|
public void onMessageReceived(MqttBean mqttBean) {
|
2025-09-09 19:18:06 +08:00
|
|
|
|
LogUtils.e("收到MQTT", mqttBean);
|
|
|
|
|
|
if (mqttBean == null) return;
|
2025-09-23 14:39:49 +08:00
|
|
|
|
if (SpUtil.getFloatingScreen() == 1) {
|
|
|
|
|
|
synchronized (mqttQueueLock) {
|
2025-09-09 19:18:06 +08:00
|
|
|
|
|
2025-09-23 14:39:49 +08:00
|
|
|
|
mqttMessageQueue.addAll(mqttBean.getList());
|
2025-09-24 00:30:40 +08:00
|
|
|
|
// if (!isMqttPlaying) {
|
|
|
|
|
|
// isMqttPlaying = true;
|
2025-10-09 09:26:16 +08:00
|
|
|
|
processNextMqttMessage();
|
2025-09-24 00:30:40 +08:00
|
|
|
|
// }
|
2025-09-09 19:18:06 +08:00
|
|
|
|
}
|
2025-10-09 09:26:16 +08:00
|
|
|
|
} else {
|
2025-09-23 14:39:49 +08:00
|
|
|
|
mqttMessageQueue.clear();
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
2025-09-09 19:18:06 +08:00
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
/// XLH消息处理
|
|
|
|
|
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
|
|
|
public void onEvent(XLHBean event) {
|
|
|
|
|
|
LogUtils.e("收到XLH", event);
|
|
|
|
|
|
if (event == null) return;
|
2025-09-23 14:39:49 +08:00
|
|
|
|
if (SpUtil.getFloatingScreen() == 1) {
|
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
|
xlhMessageQueue.add(event);
|
|
|
|
|
|
if (!isXlhPlaying) {
|
|
|
|
|
|
isXlhPlaying = true;
|
|
|
|
|
|
processNextXlhMessage();
|
|
|
|
|
|
}
|
2025-09-09 19:18:06 +08:00
|
|
|
|
}
|
2025-09-23 14:39:49 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
xlhMessageQueue.clear();
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
// 处理下一个MQTT消息
|
|
|
|
|
|
private void processNextMqttMessage() {
|
2025-09-19 02:28:02 +08:00
|
|
|
|
MqttBean.ListBean mqttBean;
|
2025-09-09 19:18:06 +08:00
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
|
if (mqttMessageQueue.isEmpty()) {
|
|
|
|
|
|
isMqttPlaying = false;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-09-09 19:18:06 +08:00
|
|
|
|
mqttBean = mqttMessageQueue.remove(0);
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
2025-09-09 19:18:06 +08:00
|
|
|
|
showFloatingMessage(mqttBean);
|
|
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
// 处理下一个XLH消息
|
|
|
|
|
|
private void processNextXlhMessage() {
|
|
|
|
|
|
XLHBean xlhBean;
|
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
|
if (xlhMessageQueue.isEmpty()) {
|
|
|
|
|
|
isXlhPlaying = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
xlhBean = xlhMessageQueue.remove(0);
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
2025-09-09 19:18:06 +08:00
|
|
|
|
showPiaoPingMessageXlh(xlhBean);
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
ViewGroup decorView;
|
|
|
|
|
|
ViewGroup decorView1;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-19 02:28:02 +08:00
|
|
|
|
private void showFloatingMessage(MqttBean.ListBean mqttBean) {
|
2025-09-24 00:30:40 +08:00
|
|
|
|
|
|
|
|
|
|
// QXGiftDriftView.getInstance( this).addGiftModel(mqttBean);
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 清理之前的视图(如果存在)
|
|
|
|
|
|
if (currentMqttView != null && currentMqttView.getParent() != null) {
|
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentMqttView.getParent();
|
|
|
|
|
|
parent.removeView(currentMqttView);
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
if (decorView == null) {
|
|
|
|
|
|
decorView = (ViewGroup) getWindow().getDecorView();
|
|
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
currentMqttView = LayoutInflater.from(this).inflate(R.layout.item_piaoping, null);
|
|
|
|
|
|
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
|
|
|
|
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
|
|
|
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
|
layoutParams.topMargin = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 70);
|
|
|
|
|
|
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
|
|
|
|
|
currentMqttView.setLayoutParams(layoutParams);
|
|
|
|
|
|
decorView.addView(currentMqttView);
|
|
|
|
|
|
|
|
|
|
|
|
updateFloatingViewData(currentMqttView, mqttBean);
|
|
|
|
|
|
resetAndStartMqttAnimation(currentMqttView, () -> {
|
|
|
|
|
|
// 清理当前视图
|
|
|
|
|
|
if (currentMqttView != null && currentMqttView.getParent() != null) {
|
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentMqttView.getParent();
|
|
|
|
|
|
parent.removeView(currentMqttView);
|
|
|
|
|
|
}
|
|
|
|
|
|
currentMqttView = null;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
// 处理队列中的下一条消息
|
|
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
|
isMqttPlaying = false;
|
|
|
|
|
|
processNextMqttMessage();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
LogUtils.e("显示MQTT飘屏失败", e);
|
|
|
|
|
|
// 出现异常时继续处理队列
|
|
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
|
isMqttPlaying = false;
|
|
|
|
|
|
processNextMqttMessage();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
private void showPiaoPingMessageXlh(XLHBean event) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 清理之前的视图(如果存在)
|
|
|
|
|
|
if (currentXlhView != null && currentXlhView.getParent() != null) {
|
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentXlhView.getParent();
|
|
|
|
|
|
parent.removeView(currentXlhView);
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
if (decorView1 == null) {
|
|
|
|
|
|
decorView1 = (ViewGroup) getWindow().getDecorView();
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
currentXlhView = LayoutInflater.from(this).inflate(R.layout.item_piaoping_xlh, null);
|
|
|
|
|
|
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
|
|
|
|
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
|
|
|
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
|
layoutParams.topMargin = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 100);
|
|
|
|
|
|
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
|
|
|
|
|
currentXlhView.setLayoutParams(layoutParams);
|
|
|
|
|
|
decorView1.addView(currentXlhView);
|
|
|
|
|
|
|
|
|
|
|
|
updateXlhFloatingViewData(currentXlhView, event);
|
|
|
|
|
|
resetAndStartXlhAnimation(currentXlhView, () -> {
|
|
|
|
|
|
// 清理当前视图
|
|
|
|
|
|
if (currentXlhView != null && currentXlhView.getParent() != null) {
|
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentXlhView.getParent();
|
|
|
|
|
|
parent.removeView(currentXlhView);
|
|
|
|
|
|
}
|
|
|
|
|
|
currentXlhView = null;
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
// 处理队列中的下一条消息
|
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
|
isXlhPlaying = false;
|
|
|
|
|
|
processNextXlhMessage();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
LogUtils.e("显示XLH飘屏失败", e);
|
|
|
|
|
|
// 出现异常时继续处理队列
|
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
|
isXlhPlaying = false;
|
|
|
|
|
|
processNextXlhMessage();
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-09 09:26:16 +08:00
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
private void resetAndStartMqttAnimation(View view, Runnable onAnimationEnd) {
|
|
|
|
|
|
try {
|
2025-09-23 14:39:49 +08:00
|
|
|
|
int screenWidth = getScreenWidth();
|
|
|
|
|
|
// 设置初始位置:在屏幕右侧外部(完全不可见)
|
|
|
|
|
|
view.setTranslationX(screenWidth);
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-24 00:30:40 +08:00
|
|
|
|
TranslateAnimation enterAnim = new TranslateAnimation(
|
|
|
|
|
|
Animation.ABSOLUTE, screenWidth,
|
|
|
|
|
|
Animation.ABSOLUTE, (screenWidth - SystemUtils.getWidth(316)) / 2,
|
|
|
|
|
|
Animation.ABSOLUTE, 0,
|
|
|
|
|
|
Animation.ABSOLUTE, 0
|
|
|
|
|
|
);
|
|
|
|
|
|
enterAnim.setDuration(1500);
|
|
|
|
|
|
enterAnim.setAnimationListener(new Animation.AnimationListener() {
|
|
|
|
|
|
@Override
|
2025-10-09 09:26:16 +08:00
|
|
|
|
public void onAnimationStart(Animation animation) {
|
|
|
|
|
|
}
|
2025-09-24 00:30:40 +08:00
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onAnimationEnd(Animation animation) {
|
|
|
|
|
|
// 停留后退出
|
|
|
|
|
|
postDelayed(() -> {
|
|
|
|
|
|
TranslateAnimation exitAnim = new TranslateAnimation(
|
|
|
|
|
|
Animation.ABSOLUTE, (screenWidth - SystemUtils.getWidth(316)) / 2,
|
|
|
|
|
|
Animation.ABSOLUTE, -screenWidth,
|
|
|
|
|
|
Animation.ABSOLUTE, 0,
|
|
|
|
|
|
Animation.ABSOLUTE, 0
|
|
|
|
|
|
);
|
|
|
|
|
|
exitAnim.setDuration(2000);
|
|
|
|
|
|
exitAnim.setAnimationListener(new Animation.AnimationListener() {
|
|
|
|
|
|
@Override
|
2025-10-09 09:26:16 +08:00
|
|
|
|
public void onAnimationStart(Animation animation) {
|
|
|
|
|
|
}
|
2025-09-24 00:30:40 +08:00
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onAnimationEnd(Animation animation) {
|
|
|
|
|
|
// 移除视图并处理下一个
|
|
|
|
|
|
// ViewGroup rootView = (ViewGroup) getParent();
|
|
|
|
|
|
// if (rootView != null) {
|
|
|
|
|
|
// rootView.removeView(QXGiftDriftView.this);
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// if (!dataArray.isEmpty()) {
|
|
|
|
|
|
// dataArray.remove(0);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// isPlaying = false;
|
|
|
|
|
|
//
|
|
|
|
|
|
// if (!dataArray.isEmpty()) {
|
|
|
|
|
|
// giftAction();
|
|
|
|
|
|
// }
|
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-10-09 09:26:16 +08:00
|
|
|
|
public void onAnimationRepeat(Animation animation) {
|
|
|
|
|
|
}
|
2025-09-24 00:30:40 +08:00
|
|
|
|
});
|
|
|
|
|
|
view.startAnimation(exitAnim);
|
|
|
|
|
|
}, 3000); // 停留1秒
|
2025-09-09 19:18:06 +08:00
|
|
|
|
}
|
2025-09-24 00:30:40 +08:00
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-10-09 09:26:16 +08:00
|
|
|
|
public void onAnimationRepeat(Animation animation) {
|
|
|
|
|
|
}
|
2025-09-24 00:30:40 +08:00
|
|
|
|
});
|
|
|
|
|
|
view.startAnimation(enterAnim);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", view.getWidth(), 0f);
|
|
|
|
|
|
// animator1.setDuration(1500);
|
|
|
|
|
|
// animator1.setInterpolator(new DecelerateInterpolator(1f));
|
|
|
|
|
|
// animator1.start();
|
|
|
|
|
|
|
|
|
|
|
|
// view.postDelayed(() -> {
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "translationX", 0f, -view.getWidth());
|
|
|
|
|
|
// animator2.setDuration(3000);
|
|
|
|
|
|
// animator2.setInterpolator(new DecelerateInterpolator(2.0f));
|
|
|
|
|
|
// animator2.addListener(new AnimatorListenerAdapter() {
|
|
|
|
|
|
// @Override
|
|
|
|
|
|
// public void onAnimationEnd(Animator animation) {
|
|
|
|
|
|
// onAnimationEnd.run();
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Override
|
|
|
|
|
|
// public void onAnimationCancel(Animator animation) {
|
|
|
|
|
|
// onAnimationEnd.run();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
// animator2.start();
|
|
|
|
|
|
// } catch (Exception e) {
|
|
|
|
|
|
// LogUtils.e("MQTT动画执行失败", e);
|
|
|
|
|
|
// onAnimationEnd.run();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }, 3000);
|
2025-09-09 19:18:06 +08:00
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
LogUtils.e("MQTT动画启动失败", e);
|
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
2025-10-09 09:26:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 添加获取屏幕宽度的方法
|
2025-09-23 14:39:49 +08:00
|
|
|
|
private int getScreenWidth() {
|
|
|
|
|
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
|
|
|
|
|
if (getWindowManager() != null) {
|
|
|
|
|
|
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
|
|
|
|
|
return displayMetrics.widthPixels;
|
|
|
|
|
|
}
|
|
|
|
|
|
return getResources().getDisplayMetrics().widthPixels;
|
|
|
|
|
|
}
|
2025-10-09 09:26:16 +08:00
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
private void resetAndStartXlhAnimation(View view, Runnable onAnimationEnd) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
view.setTranslationX(view.getWidth());
|
|
|
|
|
|
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", view.getWidth(), 0f);
|
|
|
|
|
|
animator1.setDuration(1500);
|
|
|
|
|
|
animator1.setInterpolator(new DecelerateInterpolator(2.0f));
|
|
|
|
|
|
animator1.start();
|
|
|
|
|
|
|
|
|
|
|
|
view.postDelayed(() -> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "translationX", 0f, -view.getWidth());
|
|
|
|
|
|
animator2.setDuration(1500);
|
|
|
|
|
|
animator2.setInterpolator(new DecelerateInterpolator(2.0f));
|
2025-09-06 14:19:23 +08:00
|
|
|
|
animator2.addListener(new AnimatorListenerAdapter() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
2025-09-09 19:18:06 +08:00
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onAnimationCancel(Animator animation) {
|
|
|
|
|
|
onAnimationEnd.run();
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
animator2.start();
|
2025-09-09 19:18:06 +08:00
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
LogUtils.e("XLH动画执行失败", e);
|
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
LogUtils.e("XLH动画启动失败", e);
|
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-19 02:28:02 +08:00
|
|
|
|
private void updateFloatingViewData(View view, MqttBean.ListBean mqttBean) {
|
2025-09-09 19:18:06 +08:00
|
|
|
|
TextView textView = view.findViewById(R.id.tv_name);
|
|
|
|
|
|
TextView textView2 = view.findViewById(R.id.tv_to_name);
|
|
|
|
|
|
TextView tv_time = view.findViewById(R.id.tv_num);
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-19 02:28:02 +08:00
|
|
|
|
if (mqttBean != null) {
|
|
|
|
|
|
textView2.setText("送给" + (mqttBean.getToUserName() != null ? mqttBean.getToUserName() : ""));
|
|
|
|
|
|
textView.setText(mqttBean.getFromUserName() != null ? mqttBean.getFromUserName() : "");
|
|
|
|
|
|
if (mqttBean.getGift_picture() != null) {
|
|
|
|
|
|
ImageUtils.loadHeadCC(mqttBean.getGift_picture(), view.findViewById(R.id.iv_piaoping));
|
2025-09-09 19:18:06 +08:00
|
|
|
|
}
|
2025-09-19 02:28:02 +08:00
|
|
|
|
tv_time.setText("x" + (mqttBean.getNumber() != null ? mqttBean.getNumber() : "1"));
|
2025-09-09 19:18:06 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
textView2.setText("送给");
|
|
|
|
|
|
textView.setText("");
|
|
|
|
|
|
tv_time.setText("x1");
|
|
|
|
|
|
}
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
private void updateXlhFloatingViewData(View view, XLHBean xlhBean) {
|
|
|
|
|
|
TextView textView = view.findViewById(R.id.tv_name);
|
|
|
|
|
|
ImageView xlh_image = view.findViewById(R.id.im_xlh);
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-09-06 19:28:18 +08:00
|
|
|
|
if (xlhBean != null) {
|
2025-09-09 19:18:06 +08:00
|
|
|
|
xlh_image.setImageDrawable(xlhBean.getFrom_type() == 1 ?
|
|
|
|
|
|
getResources().getDrawable(R.mipmap.xlh_jjks) :
|
|
|
|
|
|
getResources().getDrawable(R.mipmap.xlh_zsks));
|
2025-09-06 14:19:23 +08:00
|
|
|
|
textView.setText(xlhBean.getText());
|
|
|
|
|
|
} else {
|
|
|
|
|
|
textView.setText("");
|
|
|
|
|
|
}
|
2025-09-09 19:18:06 +08:00
|
|
|
|
|
|
|
|
|
|
view.setOnClickListener(v -> {
|
|
|
|
|
|
// 点击时执行跳转操作
|
|
|
|
|
|
handleItemClick(xlhBean);
|
|
|
|
|
|
});
|
2025-09-06 14:19:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-09 19:18:06 +08:00
|
|
|
|
private void handleItemClick(XLHBean xlhBean) {
|
|
|
|
|
|
// 这里可以根据实际需求实现跳转逻辑
|
|
|
|
|
|
// 例如:跳转到礼物详情页面、用户主页等
|
2025-09-23 14:39:49 +08:00
|
|
|
|
// 使用缓存数据进入房间
|
|
|
|
|
|
RoomManager.getInstance().fetchRoomDataAndEnter(getApplicationContext(), xlhBean.getRoom_id(), "");
|
|
|
|
|
|
// ARouter.getInstance().build(ARouteConstants.ROOM_DETAILS).withString("from", "我的界面").withString("roomId", xlhBean.getRoom_id()).navigation();
|
2025-09-09 19:18:06 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-08-26 19:34:44 +08:00
|
|
|
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
|
|
|
public void onEvent(ChatInfo event) {
|
|
|
|
|
|
String id = event.getId().replace("g", "");
|
2025-09-26 14:32:35 +08:00
|
|
|
|
Intent intent = new Intent(this, WebViewActivity.class);
|
|
|
|
|
|
intent.putExtra("url", CommonAppContext.getInstance().getCurrentEnvironment().getH5Url() + "/web/index.html#/pages/union/setGroup?id=" + SpUtil.getToken() + "&guildId=" + id);
|
2025-10-09 09:26:16 +08:00
|
|
|
|
startActivity(intent);
|
2025-09-26 14:32:35 +08:00
|
|
|
|
// ARouter.getInstance().build(ARouteConstants.H5).withString("url", CommonAppContext.getInstance().getCurrentEnvironment().getH5Url() + "/web/index.html#/pages/union/setGroup?id=" + SpUtil.getToken() + "&guildId=" + id).navigation();
|
2025-08-26 19:34:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-06 14:19:23 +08:00
|
|
|
|
|
2025-08-26 19:34:44 +08:00
|
|
|
|
}
|