修改名称。
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user