zhibo/android-app/app/src/main/java/com/example/livestreaming/WaterfallRoomsAdapter.java
2026-01-03 17:01:58 +08:00

239 lines
9.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.example.livestreaming;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.example.livestreaming.net.Room;
import java.util.Random;
public class WaterfallRoomsAdapter extends ListAdapter<Room, WaterfallRoomsAdapter.RoomVH> {
public interface OnRoomClickListener {
void onRoomClick(Room room);
}
private final OnRoomClickListener onRoomClick;
// 预定义的图片高度比例,模拟瀑布流效果
private static final float[] HEIGHT_RATIOS = {1.0f, 1.2f, 0.9f, 1.3f, 1.1f, 0.85f, 1.15f, 1.25f};
public WaterfallRoomsAdapter(OnRoomClickListener onRoomClick) {
super(DIFF);
this.onRoomClick = onRoomClick;
}
@NonNull
@Override
public RoomVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_room_waterfall, parent, false);
return new RoomVH(view, onRoomClick);
}
@Override
public void onBindViewHolder(@NonNull RoomVH holder, int position) {
holder.bind(getItem(position), position);
}
static class RoomVH extends RecyclerView.ViewHolder {
private final ImageView coverImage;
private final TextView liveBadge;
private final LinearLayout viewerCountLayout;
private final TextView viewerCount;
private final TextView roomTitle;
private final ImageView streamerAvatar;
private final TextView streamerName;
private final ImageView likeIcon;
private final TextView likeCount;
private final TextView hotBadge;
private final ImageView playIcon;
private final OnRoomClickListener onRoomClick;
RoomVH(View itemView, OnRoomClickListener onRoomClick) {
super(itemView);
this.onRoomClick = onRoomClick;
coverImage = itemView.findViewById(R.id.coverImage);
liveBadge = itemView.findViewById(R.id.liveBadge);
viewerCountLayout = itemView.findViewById(R.id.viewerCountLayout);
viewerCount = itemView.findViewById(R.id.viewerCount);
roomTitle = itemView.findViewById(R.id.roomTitle);
streamerAvatar = itemView.findViewById(R.id.streamerAvatar);
streamerName = itemView.findViewById(R.id.streamerName);
likeIcon = itemView.findViewById(R.id.likeIcon);
likeCount = itemView.findViewById(R.id.likeCount);
hotBadge = itemView.findViewById(R.id.hotBadge);
playIcon = itemView.findViewById(R.id.playIcon);
}
void bind(Room room, int position) {
if (room == null) return;
// 设置标题
String title = room.getTitle();
if (title == null || title.isEmpty()) {
title = generateRandomTitle(position);
}
roomTitle.setText(title);
// 设置主播名称
String name = room.getStreamerName();
if (name == null || name.isEmpty()) {
name = generateRandomName(position);
}
streamerName.setText(name);
// 计算随机高度,实现瀑布流效果
String seed = room.getId() != null ? room.getId() : String.valueOf(position);
int h = Math.abs(seed.hashCode());
float ratio = HEIGHT_RATIOS[h % HEIGHT_RATIOS.length];
int baseHeight = (int) (itemView.getContext().getResources().getDisplayMetrics().density * 150);
int imageHeight = (int) (baseHeight * ratio);
ViewGroup.LayoutParams params = coverImage.getLayoutParams();
params.height = imageHeight;
coverImage.setLayoutParams(params);
// 加载封面图片 - 使用更真实的图片
loadCoverImage(room, position, h);
// 加载主播头像
loadAvatarImage(position);
// 设置点赞数 - 使用真实数据
Integer roomLikeCount = room.getLikeCount();
if (roomLikeCount != null && roomLikeCount > 0) {
likeCount.setText(formatNumber(roomLikeCount));
likeIcon.setVisibility(View.VISIBLE);
likeCount.setVisibility(View.VISIBLE);
} else {
// 如果没有点赞数显示0
likeCount.setText("0");
likeIcon.setVisibility(View.VISIBLE);
likeCount.setVisibility(View.VISIBLE);
}
// 设置直播状态
if (room.isLive()) {
liveBadge.setVisibility(View.VISIBLE);
viewerCountLayout.setVisibility(View.VISIBLE);
int viewers = (h % 380) + 5;
viewerCount.setText(formatNumber(viewers));
playIcon.setVisibility(View.GONE);
// 热门标签
if (viewers > 200) {
hotBadge.setVisibility(View.VISIBLE);
} else {
hotBadge.setVisibility(View.GONE);
}
} else {
liveBadge.setVisibility(View.GONE);
viewerCountLayout.setVisibility(View.GONE);
playIcon.setVisibility(View.VISIBLE);
hotBadge.setVisibility(View.GONE);
}
// 点击事件
itemView.setOnClickListener(v -> {
if (onRoomClick != null) {
onRoomClick.onRoomClick(room);
}
});
}
private void loadCoverImage(Room room, int position, int hash) {
// 使用多种图片源,让内容更丰富
String[] imageUrls = {
"https://picsum.photos/seed/" + (hash % 1000) + "/400/500",
"https://picsum.photos/seed/" + ((hash + 100) % 1000) + "/400/600",
"https://picsum.photos/seed/" + ((hash + 200) % 1000) + "/400/450",
};
String imageUrl = imageUrls[position % imageUrls.length];
Glide.with(coverImage.getContext())
.load(imageUrl)
.apply(new RequestOptions()
.placeholder(R.drawable.bg_cover_placeholder)
.error(R.drawable.bg_cover_placeholder)
.centerCrop())
.into(coverImage);
}
private void loadAvatarImage(int position) {
String avatarUrl = "https://i.pravatar.cc/100?img=" + ((position % 70) + 1);
Glide.with(streamerAvatar.getContext())
.load(avatarUrl)
.apply(new RequestOptions()
.placeholder(R.drawable.ic_account_circle_24)
.error(R.drawable.ic_account_circle_24)
.circleCrop())
.into(streamerAvatar);
}
private String generateRandomTitle(int position) {
String[] titles = {
"#健身穿搭 #一万种健与美 #健身女孩 #完美身材",
"避雷秀厢附近租房",
"找线下收U换现 可长期合作 有实力的私面聊",
"我提笔不为离愁 只为你转身回眸",
"今日穿搭分享 #日常穿搭 #时尚",
"周末vlog #生活记录 #美好生活",
"美食探店 #吃货日常 #美食推荐",
"旅行日记 #风景 #旅行攻略",
"护肤心得分享 #护肤 #美妆",
"读书笔记 #好书推荐 #阅读"
};
return titles[position % titles.length];
}
private String generateRandomName(int position) {
String[] names = {
"小桃兔兔", "别管我了", "火火", "RicLei",
"甜甜圈", "小确幸", "追光者", "星河漫步",
"清风徐来", "月光宝盒"
};
return names[position % names.length];
}
private String formatNumber(int num) {
if (num >= 10000) {
return String.format("%.1fw", num / 10000.0);
} else if (num >= 1000) {
return String.format("%.1fk", num / 1000.0);
}
return String.valueOf(num);
}
}
private static final DiffUtil.ItemCallback<Room> DIFF = new DiffUtil.ItemCallback<Room>() {
@Override
public boolean areItemsTheSame(@NonNull Room oldItem, @NonNull Room newItem) {
String o = oldItem.getId();
String n = newItem.getId();
return o != null && o.equals(n);
}
@Override
public boolean areContentsTheSame(@NonNull Room oldItem, @NonNull Room newItem) {
return oldItem.equals(newItem);
}
};
}