修改名称。

This commit is contained in:
2025-11-07 09:22:39 +08:00
parent d9cf55b053
commit a8dcfbb6a7
2203 changed files with 3 additions and 4 deletions

View File

@@ -0,0 +1,254 @@
package com.xscm.moduleutil.utils.roomview;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.xscm.moduleutil.bean.GiftBean;
import com.xscm.moduleutil.bean.RoonGiftModel;
import java.lang.ref.WeakReference;
import java.util.*;
public class GiftDisplayManager {
private static GiftDisplayManager instance;
private WeakReference<ViewGroup> containerRef;
private List<GiftDisplayView> displayViews;
private Queue<GiftBean> giftQueue;
private Map<String, GiftBean> accumulatedGifts;
private boolean isProcessingQueue = false;
private Handler mainHandler = new Handler(Looper.getMainLooper());
public static GiftDisplayManager getInstance() {
if (instance == null) {
synchronized (GiftDisplayManager.class) {
if (instance == null) {
instance = new GiftDisplayManager();
}
}
}
return instance;
}
private GiftDisplayManager() {
displayViews = new ArrayList<>();
giftQueue = new LinkedList<>();
accumulatedGifts = new HashMap<>();
}
public void setupDisplayView(ViewGroup container) {
this.containerRef = new WeakReference<>(container);
createDisplayViews();
}
private void createDisplayViews() {
if (displayViews.size() > 0 || containerRef == null || containerRef.get() == null) {
return;
}
ViewGroup container = containerRef.get();
int viewHeight = dpToPx(40);
int spacing = dpToPx(10);
int topMargin = dpToPx(100);
int width = dpToPx(270);
for (int i = 0; i < 3; i++) {
int y = topMargin + (viewHeight + spacing) * i;
GiftDisplayView displayView = new GiftDisplayView(container.getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, viewHeight);
params.setMargins(0, y, 0, 0);
displayView.setLayoutParams(params);
displayView.setTag(1000 + i);
final int finalI = i;
displayView.setGiftAnimationListener(view -> {
Log.d("GiftDisplayManager", "Gift animation ended on view: " + finalI);
onGiftAnimationEnd(view);
});
container.addView(displayView);
displayViews.add(displayView);
Log.d("GiftDisplayManager", "Created display view " + i);
}
}
public void receiveGift(GiftBean gift) {
if (isInBackground){
return;
}
if (gift == null) return;
Log.d("GiftDisplayManager", "Received gift: " + gift.getSenderName() +
" - " + gift.getGift_name() + " x" + gift.getNumber());
mainHandler.post(() -> internalReceiveGift(gift));
}
private void internalReceiveGift(GiftBean gift) {
// 查找正在显示的同类型礼物
GiftDisplayView displayingView = findDisplayingViewForGift(gift);
if (displayingView != null) {
// 找到正在显示的视图,直接累加
String key = gift.getGiftKey();
GiftBean accumulatedGift = accumulatedGifts.get(key);
if (accumulatedGift != null) {
accumulatedGift.setNumber(accumulatedGift.getNumber() + gift.getNumber());
displayingView.updateGiftCount(accumulatedGift.getNumber());
Log.d("GiftDisplayManager", "Gift accumulated: " + gift.getGift_name() +
" x" + accumulatedGift.getNumber());
}
} else {
// 新礼物,检查是否可以立即显示
GiftDisplayView availableView = findAvailableDisplayView();
if (availableView != null) {
// 有可用视图,立即显示
String key = gift.getGiftKey();
accumulatedGifts.put(key, gift.clone());
availableView.showGift(gift);
Log.d("GiftDisplayManager", "Immediately display gift on view: " + availableView.getTag());
} else {
// 没有可用视图,加入队列
giftQueue.offer(gift);
Log.d("GiftDisplayManager", "Added to queue, current queue size: " + giftQueue.size());
}
}
// 处理队列
processGiftQueue();
// 确保每次接收礼物后都处理队列
mainHandler.postDelayed(this::processGiftQueue, 50);
}
private GiftDisplayView findDisplayingViewForGift(GiftBean gift) {
for (GiftDisplayView view : displayViews) {
if (view.isAnimating() && view.getCurrentGift() != null &&
view.getCurrentGift().isSameGiftFromSameSender(gift)) {
return view;
}
}
return null;
}
private GiftDisplayView findAvailableDisplayView() {
for (GiftDisplayView view : displayViews) {
if (!view.isAnimating()) {
return view;
}
}
return null;
}
private void processGiftQueue() {
if (isProcessingQueue) {
Log.d("GiftDisplayManager", "Already processing queue, skip");
return;
}
isProcessingQueue = true;
Log.d("GiftDisplayManager", "Start processing queue, size: " + giftQueue.size());
// 循环处理队列直到队列为空或没有可用视图
while (!giftQueue.isEmpty()) {
GiftDisplayView availableView = findAvailableDisplayView();
if (availableView == null) {
break;
}
GiftBean gift = giftQueue.poll();
if (gift == null) continue;
// 检查是否已经有同类型礼物在显示
GiftDisplayView displayingView = findDisplayingViewForGift(gift);
if (displayingView == null) {
String key = gift.getGiftKey();
accumulatedGifts.put(key, gift.clone());
availableView.showGift(gift);
Log.d("GiftDisplayManager", "Display gift from queue: " + gift.getGift_name());
} else {
// 如果已经在显示,累加到现有视图
String key = gift.getGiftKey();
GiftBean accumulatedGift = accumulatedGifts.get(key);
if (accumulatedGift != null) {
accumulatedGift.setNumber(accumulatedGift.getNumber() + gift.getNumber());
displayingView.updateGiftCount(accumulatedGift.getNumber());
Log.d("GiftDisplayManager", "Queue gift accumulated to existing: " +
gift.getNickname() + " x" + accumulatedGift.getNumber());
}
}
}
isProcessingQueue = false;
// 打印队列状态
if (!giftQueue.isEmpty()) {
Log.d("GiftDisplayManager", "Still " + giftQueue.size() + " gifts waiting in queue");
}
}
private void onGiftAnimationEnd(GiftDisplayView view) {
Log.d("GiftDisplayManager", "Gift animation end on view: " + view.getTag());
// 从累加记录中移除
if (view.getCurrentGift() != null) {
String key = view.getCurrentGift().getGiftKey();
accumulatedGifts.remove(key);
Log.d("GiftDisplayManager", "Removed accumulated record: " + key);
}
// 延迟一下再处理队列,确保视图状态完全重置
// 立即处理队列,而不是延迟
mainHandler.post(this::processGiftQueue);
}
private boolean isInBackground=false;
public void isBackGround(){
for (GiftDisplayView view : displayViews) {
view.finishAnimationImmediately();
}
giftQueue.clear();
accumulatedGifts.clear();
isProcessingQueue = false;
isInBackground=true;
}
public void becomeFront(){
isInBackground=false;
}
public void clearAll() {
Log.d("GiftDisplayManager", "Clear all gifts and queue");
for (GiftDisplayView view : displayViews) {
view.finishAnimationImmediately();
}
containerRef.clear();
displayViews.clear();
giftQueue.clear();
accumulatedGifts.clear();
isProcessingQueue = false;
}
// 调试方法
public void printDebugInfo() {
Log.d("GiftDisplayManager", "=== Gift Display Manager Status ===");
Log.d("GiftDisplayManager", "Queue size: " + giftQueue.size());
Log.d("GiftDisplayManager", "Accumulated records: " + accumulatedGifts.size());
for (int i = 0; i < displayViews.size(); i++) {
GiftDisplayView view = displayViews.get(i);
Log.d("GiftDisplayManager", "View " + i + ": Animating=" + view.isAnimating() +
", Gift=" + (view.getCurrentGift() != null ? view.getCurrentGift().getGift_name() : "None"));
}
Log.d("GiftDisplayManager", "===================================");
}
private int dpToPx(int dp) {
if (containerRef == null || containerRef.get() == null) return dp;
float density = containerRef.get().getResources().getDisplayMetrics().density;
return Math.round(dp * density);
}
}

View File

@@ -0,0 +1,265 @@
package com.xscm.moduleutil.utils.roomview;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.bean.GiftBean;
import com.xscm.moduleutil.utils.ImageUtils;
import java.util.Random;
public class GiftDisplayView extends FrameLayout {
private ImageView avatarImageView;
private TextView senderTextView;
private TextView giftTextView;
private TextView countTextView;
private ImageView giftImageView;
private LinearLayout ll;
private GiftBean currentGift;
private boolean isAnimating = false;
private GiftAnimationListener listener;
private Handler handler = new Handler();
private Runnable hideRunnable;
public interface GiftAnimationListener {
void onGiftAnimationEnd(GiftDisplayView view);
}
public GiftDisplayView(Context context) {
super(context);
initView();
}
public GiftDisplayView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
LayoutInflater.from(getContext()).inflate(R.layout.gift_display_layout, this, true);
avatarImageView = findViewById(R.id.iv_avatar);
senderTextView = findViewById(R.id.tv_sender);
giftTextView = findViewById(R.id.tv_gift);
countTextView = findViewById(R.id.tv_count);
giftImageView = findViewById(R.id.iv_gift);
// ll = findViewById(R.id.ll);
// setBackgroundResource(R.drawable.gift_background);
setAlpha(0f);
}
public void showGift(GiftBean gift) {
if (isAnimating) {
Log.w("GiftDisplayView", "View is animating, cannot show new gift");
return;
}
this.currentGift = gift;
this.isAnimating = true;
Log.d("GiftDisplayView", "Start showing gift: " + gift.getGift_name());
// 更新UI
updateUIWithGift(gift);
// 重置位置
setTranslationX(-getWidth());
setAlpha(1f);
// 从左往右进入动画
animate()
.translationX(0)
.setDuration(500)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Log.d("GiftDisplayView", "Enter animation completed: " + gift.getGift_name());
startHideTimer();
}
})
.start();
}
private void updateUIWithGift(GiftBean gift) {
if (gift == null) return;
senderTextView.setText(gift.getNickname()!=null ? gift.getNickname() : "未知用户");
// 更新发送者名称
// senderTextView.setText(gift.getSenderName() != null ? gift.getSenderName() : "未知用户");
// 更新礼物信息
giftTextView.setText("送给 "+(gift.getSenderName() != null ? gift.getSenderName() : "未知用户") + (gift.getGift_name() != null ? gift.getGift_name() : "礼物"));
// 更新礼物数量
countTextView.setText("x" + gift.getNumber());
// 加载头像图片这里可以使用Glide、Picasso等图片加载库
loadAvatarImage(gift.getUserAvatar());
// 加载礼物图片
loadGiftImage(gift.getBase_image());
Log.d("GiftDisplayView", "Update UI: " + gift.getSenderName() + " - " +
gift.getGift_name() + " x" + gift.getNumber());
}
private void loadAvatarImage(String avatarUrl) {
if (avatarUrl != null && !avatarUrl.isEmpty()) {
// 使用图片加载库,例如:
// Glide.with(getContext()).load(avatarUrl).into(avatarImageView);
// 临时用颜色代替
// avatarImageView.setBackgroundColor(getRandomColor());
if (avatarImageView!=null&&avatarImageView.getContext()!=null) {
ImageUtils.loadHeadCC(avatarUrl, avatarImageView);
}
} else {
avatarImageView.setBackgroundColor(Color.LTGRAY);
}
}
private void loadGiftImage(String giftImageUrl) {
if (giftImageUrl != null && !giftImageUrl.isEmpty()) {
// 使用图片加载库
// Glide.with(getContext()).load(giftImageUrl).into(giftImageView);
// 临时用颜色代替
// giftImageView.setBackgroundColor(getRandomColor());
ImageUtils.loadHeadCC(giftImageUrl, giftImageView);
} else {
giftImageView.setBackgroundColor(Color.parseColor("#FFA500"));
}
}
private int getRandomColor() {
Random random = new Random();
return Color.argb(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));
}
public void updateGiftCount(int count) {
if (!isAnimating) {
Log.w("GiftDisplayView", "View is not animating, cannot update count");
return;
}
Log.d("GiftDisplayView", "Update gift count: " + count);
// 更新数量显示
countTextView.setText("x" + count);
// 数量更新动画
countTextView.animate()
.scaleX(1.5f)
.scaleY(1.5f)
.setDuration(200)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
countTextView.animate()
.scaleX(1f)
.scaleY(1f)
.setDuration(200)
.start();
}
})
.start();
// 重置计时器
resetHideTimer();
}
private void startHideTimer() {
// 移除之前的任务
if (hideRunnable != null) {
handler.removeCallbacks(hideRunnable);
}
hideRunnable = this::hideAnimation;
handler.postDelayed(hideRunnable, 3000);
}
private void resetHideTimer() {
startHideTimer();
}
private void hideAnimation() {
if (!isAnimating) {
return;
}
Log.d("GiftDisplayView", "Start hide animation: " + currentGift.getGift_name());
// 从右往左消失动画
animate()
.translationX(-getWidth())
.alpha(0f)
.setDuration(500)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Log.d("GiftDisplayView", "Hide animation completed: " + currentGift.getGift_name());
isAnimating = false;
if (listener != null) {
listener.onGiftAnimationEnd(GiftDisplayView.this);
}
currentGift = null;
}
})
.start();
}
public void finishAnimationImmediately() {
Log.d("GiftDisplayView", "Finish animation immediately");
// 移除计时任务
if (hideRunnable != null) {
handler.removeCallbacks(hideRunnable);
hideRunnable = null;
}
// 清除动画
clearAnimation();
animate().cancel();
isAnimating = false;
currentGift = null;
setAlpha(0f);
setTranslationX(-getWidth());
}
public boolean isAnimating() {
return isAnimating;
}
public GiftBean getCurrentGift() {
return currentGift;
}
public void setGiftAnimationListener(GiftAnimationListener listener) {
this.listener = listener;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (hideRunnable != null) {
handler.removeCallbacks(hideRunnable);
}
}
}