新版本 #10

Merged
px8tqwyol merged 1 commits from niefangkai_part into master 2 months ago

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="NullableNotNullManager">
@ -182,6 +183,13 @@
<component name="ProjectType">
<option name="id" value="Android" />
</component>
<component name="VisualizationToolProject">
<option name="state">
<ProjectState>
<option name="scale" value="0.24901855468749995" />
</ProjectState>
</option>
</component>
<component name="masterDetails">
<states>
<state key="ProjectJDKs.UI">

@ -0,0 +1,142 @@
package com.startsmake.llrisetabbardemo.activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.adapter.ChatMessageAdapter;
import com.startsmake.llrisetabbardemo.model.ChatMessage;
import java.util.ArrayList;
import java.util.List;
public class ChatActivity extends AppCompatActivity {
private TextView tvTitle;
private ImageView ivBack;
private RecyclerView rvChatMessages;
private EditText etMessage;
private ImageButton btnSend;
private ChatMessageAdapter chatAdapter;
private List<ChatMessage> messageList;
private String chatTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
// 获取传递过来的聊天标题
chatTitle = getIntent().getStringExtra("chat_title");
if (chatTitle == null) {
chatTitle = "聊天";
}
initView();
initData();
setupClickListeners();
}
private void initView() {
tvTitle = findViewById(R.id.tvTitle);
ivBack = findViewById(R.id.ivBack);
rvChatMessages = findViewById(R.id.rvChatMessages);
etMessage = findViewById(R.id.etMessage);
btnSend = findViewById(R.id.btnSend);
tvTitle.setText(chatTitle);
}
private void initData() {
messageList = new ArrayList<>();
// 添加一些初始消息
if ("通知消息".equals(chatTitle)) {
messageList.add(new ChatMessage("系统", "红包到账提醒", "10:30", false));
messageList.add(new ChatMessage("我", "收到了,谢谢!", "10:31", true));
} else if ("刑事组之虎".equals(chatTitle)) {
messageList.add(new ChatMessage("刑事组之虎", "快给ta一个评价吧", "04-19 14:20", false));
messageList.add(new ChatMessage("我", "已经评价了,商品很不错!", "04-19 14:25", true));
} else {
messageList.add(new ChatMessage(chatTitle, "你好!", "刚刚", false));
}
chatAdapter = new ChatMessageAdapter(this, messageList);
rvChatMessages.setLayoutManager(new LinearLayoutManager(this));
rvChatMessages.setAdapter(chatAdapter);
// 滚动到底部
rvChatMessages.scrollToPosition(messageList.size() - 1);
}
private void setupClickListeners() {
// 返回按钮
ivBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
// 发送按钮
btnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendMessage();
}
});
}
private void sendMessage() {
String message = etMessage.getText().toString().trim();
if (!TextUtils.isEmpty(message)) {
// 添加新消息到列表
ChatMessage newMessage = new ChatMessage("我", message, "刚刚", true);
messageList.add(newMessage);
chatAdapter.notifyItemInserted(messageList.size() - 1);
// 清空输入框
etMessage.setText("");
// 滚动到底部
rvChatMessages.scrollToPosition(messageList.size() - 1);
// 模拟对方回复(可选)
simulateReply(message);
}
}
private void simulateReply(String userMessage) {
// 延迟模拟回复
rvChatMessages.postDelayed(new Runnable() {
@Override
public void run() {
String reply = generateReply(userMessage);
ChatMessage replyMessage = new ChatMessage(chatTitle, reply, "刚刚", false);
messageList.add(replyMessage);
chatAdapter.notifyItemInserted(messageList.size() - 1);
rvChatMessages.scrollToPosition(messageList.size() - 1);
}
}, 1000);
}
private String generateReply(String userMessage) {
// 简单的回复逻辑
if (userMessage.contains("你好") || userMessage.contains("在吗")) {
return "在的,有什么可以帮您?";
} else if (userMessage.contains("价格") || userMessage.contains("多少钱")) {
return "这个商品价格是xxx元";
} else if (userMessage.contains("谢谢")) {
return "不客气!";
} else {
return "收到您的消息了!";
}
}
}

@ -0,0 +1,74 @@
package com.startsmake.llrisetabbardemo.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.model.ChatMessage;
import java.util.List;
public class ChatMessageAdapter extends RecyclerView.Adapter<ChatMessageAdapter.ViewHolder> {
private Context context;
private List<ChatMessage> messageList;
public ChatMessageAdapter(Context context, List<ChatMessage> messageList) {
this.context = context;
this.messageList = messageList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_chat_message, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ChatMessage message = messageList.get(position);
if (message.isMe()) {
// 自己发送的消息 - 右侧显示
holder.layoutLeft.setVisibility(View.GONE);
holder.layoutRight.setVisibility(View.VISIBLE);
holder.tvRightMessage.setText(message.getContent());
holder.tvRightTime.setText(message.getTime());
} else {
// 对方发送的消息 - 左侧显示
holder.layoutRight.setVisibility(View.GONE);
holder.layoutLeft.setVisibility(View.VISIBLE);
holder.tvLeftMessage.setText(message.getContent());
holder.tvLeftTime.setText(message.getTime());
}
}
@Override
public int getItemCount() {
return messageList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout layoutLeft;
LinearLayout layoutRight;
TextView tvLeftMessage;
TextView tvRightMessage;
TextView tvLeftTime;
TextView tvRightTime;
public ViewHolder(@NonNull View itemView) {
super(itemView);
layoutLeft = itemView.findViewById(R.id.layoutLeft);
layoutRight = itemView.findViewById(R.id.layoutRight);
tvLeftMessage = itemView.findViewById(R.id.tvLeftMessage);
tvRightMessage = itemView.findViewById(R.id.tvRightMessage);
tvLeftTime = itemView.findViewById(R.id.tvLeftTime);
tvRightTime = itemView.findViewById(R.id.tvRightTime);
}
}
}

@ -0,0 +1,102 @@
package com.startsmake.llrisetabbardemo.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.model.MessageItem;
import java.util.List;
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHolder> {
private Context context;
private List<MessageItem> messageList;
private OnItemClickListener onItemClickListener;
public MessageAdapter(Context context, List<MessageItem> messageList) {
this.context = context;
this.messageList = messageList;
}
// 添加点击监听接口
public interface OnItemClickListener {
void onItemClick(MessageItem item);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.onItemClickListener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_message, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
MessageItem item = messageList.get(position);
// 设置默认白色头像背景
holder.ivAvatar.setBackgroundResource(R.drawable.bg_avatar_placeholder);
holder.tvTitle.setText(item.getTitle());
holder.tvContent.setText(item.getContent());
holder.tvTime.setText(item.getTime());
// 未读消息数量
if (item.getUnreadCount() > 0) {
holder.tvUnreadCount.setVisibility(View.VISIBLE);
holder.tvUnreadCount.setText(String.valueOf(item.getUnreadCount()));
} else {
holder.tvUnreadCount.setVisibility(View.GONE);
}
// 官方标识
if (item.isOfficial()) {
holder.ivOfficial.setVisibility(View.VISIBLE);
} else {
holder.ivOfficial.setVisibility(View.GONE);
}
// 添加点击事件
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(item);
}
}
});
}
@Override
public int getItemCount() {
return messageList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView ivAvatar;
TextView tvTitle;
TextView tvContent;
TextView tvTime;
TextView tvUnreadCount;
ImageView ivOfficial;
public ViewHolder(@NonNull View itemView) {
super(itemView);
ivAvatar = itemView.findViewById(R.id.ivAvatar);
tvTitle = itemView.findViewById(R.id.tvTitle);
tvContent = itemView.findViewById(R.id.tvContent);
tvTime = itemView.findViewById(R.id.tvTime);
tvUnreadCount = itemView.findViewById(R.id.tvUnreadCount);
ivOfficial = itemView.findViewById(R.id.ivOfficial);
}
}
}

@ -0,0 +1,28 @@
package com.startsmake.llrisetabbardemo.model;
public class ChatMessage {
private String sender;
private String content;
private String time;
private boolean isMe;
public ChatMessage(String sender, String content, String time, boolean isMe) {
this.sender = sender;
this.content = content;
this.time = time;
this.isMe = isMe;
}
// Getter and Setter methods
public String getSender() { return sender; }
public void setSender(String sender) { this.sender = sender; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public String getTime() { return time; }
public void setTime(String time) { this.time = time; }
public boolean isMe() { return isMe; }
public void setMe(boolean me) { isMe = me; }
}

@ -0,0 +1,33 @@
package com.startsmake.llrisetabbardemo.model;
public class MessageItem {
private String title;
private String content;
private String time;
private int unreadCount;
private boolean isOfficial;
public MessageItem(String title, String content, String time, int unreadCount, boolean isOfficial) {
this.title = title;
this.content = content;
this.time = time;
this.unreadCount = unreadCount;
this.isOfficial = isOfficial;
}
// Getter and Setter methods
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public String getTime() { return time; }
public void setTime(String time) { this.time = time; }
public int getUnreadCount() { return unreadCount; }
public void setUnreadCount(int unreadCount) { this.unreadCount = unreadCount; }
public boolean isOfficial() { return isOfficial; }
public void setOfficial(boolean official) { isOfficial = official; }
}

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
<stroke
android:width="1dp"
android:color="#e0e0e0" />
<corners android:radius="4dp" />
</shape>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#f5f5f5" />
<corners android:radius="24dp" />
<stroke
android:width="1dp"
android:color="#e0e0e0" />
</shape>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
<corners
android:topLeftRadius="0dp"
android:topRightRadius="16dp"
android:bottomLeftRadius="16dp"
android:bottomRightRadius="16dp" />
<stroke
android:width="1dp"
android:color="#e0e0e0" />
</shape>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#07C160" />
<corners
android:topLeftRadius="16dp"
android:topRightRadius="0dp"
android:bottomLeftRadius="16dp"
android:bottomRightRadius="16dp" />
</shape>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#f5f5f5" />
<corners android:radius="18dp" />
</shape>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF5000" />
<corners android:radius="9dp" />
</shape>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF5000"
android:pathData="M12,2L4,5v6.09c0,5.05 3.41,9.76 8,10.91c4.59,-1.15 8,-5.86 8,-10.91V5L12,2z"/>
</vector>

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#f5f5f5">
<!-- 标题栏 -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@android:color/white"
android:elevation="2dp">
<ImageView
android:id="@+id/ivBack"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@android:drawable/ic_menu_close_clear_cancel"
android:layout_centerVertical="true"
android:layout_marginStart="16dp" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="聊天"
android:textSize="18sp"
android:textStyle="bold"
android:layout_centerInParent="true" />
</RelativeLayout>
<!-- 聊天消息列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvChatMessages"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<!-- 输入框区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="horizontal"
android:padding="8dp"
android:elevation="4dp">
<EditText
android:id="@+id/etMessage"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/bg_chat_input"
android:hint="输入消息..."
android:maxLines="3"
android:padding="12dp"
android:textSize="14sp" />
<ImageButton
android:id="@+id/btnSend"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?android:attr/selectableItemBackground"
android:src="@android:drawable/ic_menu_send"
android:layout_marginStart="8dp" />
</LinearLayout>
</LinearLayout>

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<!-- 对方消息(左侧) -->
<LinearLayout
android:id="@+id/layoutLeft"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingHorizontal="16dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingEnd="48dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_chat_message_left"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:id="@+id/tvLeftMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="对方消息"
android:textColor="@android:color/black"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tvLeftTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时间"
android:textColor="#999999"
android:textSize="10sp"
android:layout_marginTop="4dp"
android:layout_marginStart="12dp" />
</LinearLayout>
</LinearLayout>
<!-- 自己消息(右侧) -->
<LinearLayout
android:id="@+id/layoutRight"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingHorizontal="16dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="end"
android:paddingStart="48dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_chat_message_right"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:id="@+id/tvRightMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我的消息"
android:textColor="@android:color/white"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tvRightTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时间"
android:textColor="#999999"
android:textSize="10sp"
android:layout_marginTop="4dp"
android:layout_gravity="end"
android:layout_marginEnd="12dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@android:color/white"
android:padding="12dp">
<!-- 白色头像占位 -->
<ImageView
android:id="@+id/ivAvatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/bg_avatar_placeholder" />
<!-- 官方标识 -->
<ImageView
android:id="@+id/ivOfficial"
android:layout_width="12dp"
android:layout_height="12dp"
android:src="@drawable/ic_official"
android:layout_alignTop="@id/ivAvatar"
android:layout_alignEnd="@id/ivAvatar" />
<!-- 标题 -->
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题"
android:textSize="16sp"
android:textStyle="bold"
android:layout_toEndOf="@id/ivAvatar"
android:layout_marginStart="12dp"
android:layout_alignTop="@id/ivAvatar" />
<!-- 内容 -->
<TextView
android:id="@+id/tvContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="内容"
android:textSize="14sp"
android:textColor="#666666"
android:maxLines="1"
android:ellipsize="end"
android:layout_toEndOf="@id/ivAvatar"
android:layout_below="@id/tvTitle"
android:layout_marginStart="12dp"
android:layout_marginTop="4dp" />
<!-- 时间 -->
<TextView
android:id="@+id/tvTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时间"
android:textSize="12sp"
android:textColor="#999999"
android:layout_alignParentEnd="true"
android:layout_alignTop="@id/tvTitle" />
<!-- 未读消息计数 -->
<TextView
android:id="@+id/tvUnreadCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="18dp"
android:background="@drawable/bg_unread_count"
android:textColor="@android:color/white"
android:textSize="10sp"
android:gravity="center"
android:layout_alignParentEnd="true"
android:layout_below="@id/tvTime"
android:layout_marginTop="4dp" />
</RelativeLayout>
Loading…
Cancel
Save