@ -0,0 +1,3 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
@ -0,0 +1,380 @@
|
||||
package com.startsmake.llrisetabbardemo.activity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import manager.DataManager;
|
||||
|
||||
import com.startsmake.llrisetabbardemo.model.Item;
|
||||
import com.startsmake.llrisetabbardemo.R;
|
||||
import com.startsmake.llrisetabbardemo.model.Product;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
public class SearchActivity extends AppCompatActivity {
|
||||
|
||||
private EditText searchEditText;
|
||||
private ImageButton backButton;
|
||||
private ImageButton cameraButton;
|
||||
private com.google.android.flexbox.FlexboxLayout historyContainer;
|
||||
private com.google.android.flexbox.FlexboxLayout recommendContainer;
|
||||
private TextView clearHistoryText;
|
||||
private TextView expandHistoryText;
|
||||
|
||||
private SharedPreferences sharedPreferences;
|
||||
private static final String SEARCH_HISTORY = "search_history";
|
||||
private static final int MAX_HISTORY_COUNT = 6; // 最大存储6条
|
||||
private static final int VISIBLE_HISTORY_COUNT = 4; // 默认显示4条
|
||||
private boolean isHistoryExpanded = false;
|
||||
|
||||
// 相机相关变量
|
||||
private static final int CAMERA_REQUEST_CODE = 1001;
|
||||
private static final int CAMERA_PERMISSION_REQUEST_CODE = 1002;
|
||||
private String currentPhotoPath;
|
||||
|
||||
private List<Product> allProducts;
|
||||
private List<String> recommendKeywords;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_search);
|
||||
|
||||
initViews();
|
||||
initData();
|
||||
loadSearchHistory();
|
||||
setupRecommendations();
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
searchEditText = findViewById(R.id.search_edit_text);
|
||||
backButton = findViewById(R.id.back_button);
|
||||
cameraButton = findViewById(R.id.camera_button);
|
||||
historyContainer = findViewById(R.id.history_container);
|
||||
recommendContainer = findViewById(R.id.recommend_container);
|
||||
clearHistoryText = findViewById(R.id.clear_history_text);
|
||||
expandHistoryText = findViewById(R.id.expand_history_text);
|
||||
TextView searchButton = findViewById(R.id.search_button);
|
||||
|
||||
// 设置返回按钮
|
||||
backButton.setOnClickListener((View v) -> finish());
|
||||
|
||||
// 设置搜索按钮点击事件
|
||||
searchButton.setOnClickListener((View v) -> {
|
||||
performSearch();
|
||||
});
|
||||
|
||||
// 设置搜索页面的相机按钮
|
||||
cameraButton.setOnClickListener((View v) -> {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
|
||||
openCamera();
|
||||
} else {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
requestPermissions(new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
|
||||
} else {
|
||||
openCamera();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 设置搜索功能
|
||||
searchEditText.setOnEditorActionListener((v, actionId, event) -> {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
performSearch();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 清空历史记录
|
||||
clearHistoryText.setOnClickListener((View v) -> clearSearchHistory());
|
||||
|
||||
// 设置展开/收起按钮
|
||||
expandHistoryText.setOnClickListener((View v) -> {
|
||||
isHistoryExpanded = !isHistoryExpanded;
|
||||
loadSearchHistory();
|
||||
});
|
||||
}
|
||||
|
||||
// 修改 initData 方法
|
||||
private void initData() {
|
||||
sharedPreferences = getSharedPreferences("search_prefs", MODE_PRIVATE);
|
||||
|
||||
// 从 DataManager 获取所有商品数据
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
List<Item> allItems = dataManager.getAllItems();
|
||||
|
||||
// 转换为 Product 对象(为了保持兼容性)
|
||||
allProducts = new ArrayList<>();
|
||||
for (Item item : allItems) {
|
||||
Product product = dataManager.convertItemToProduct(item);
|
||||
allProducts.add(product);
|
||||
}
|
||||
|
||||
// 如果 DataManager 中没有数据,使用示例数据
|
||||
if (allProducts.isEmpty()) {
|
||||
allProducts.add(new Product("1", "Java编程思想", "计算机专业教材", "学习资料", 45.0, "", 0, "南校区", "卖家信用极好", true));
|
||||
allProducts.add(new Product("2", "高等数学教材", "大学数学课本", "学习资料", 30.0, "", 0, "北校区", "百分百好评", false));
|
||||
allProducts.add(new Product("3", "笔记本电脑", "二手联想笔记本", "数码产品", 1200.0, "", 0, "南校区", "卖家信用良好", true));
|
||||
// ... 其他示例数据
|
||||
}
|
||||
|
||||
// 初始化推荐关键词(保持不变)
|
||||
recommendKeywords = Arrays.asList(
|
||||
"Java编程教材", "Python入门书籍", "高等数学课本", "英语四级真题", "考研政治资料",
|
||||
"二手笔记本电脑", "机械键盘", "无线鼠标", "蓝牙耳机", "平板电脑",
|
||||
"台灯", "收纳箱", "穿衣镜", "瑜伽垫", "体重秤"
|
||||
);
|
||||
}
|
||||
|
||||
private void loadSearchHistory() {
|
||||
Set<String> historySet = sharedPreferences.getStringSet(SEARCH_HISTORY, new HashSet<>());
|
||||
List<String> historyList = new ArrayList<>(historySet);
|
||||
|
||||
// 按照搜索顺序排序(后搜索的在前)
|
||||
Collections.reverse(historyList);
|
||||
|
||||
historyContainer.removeAllViews();
|
||||
|
||||
if (historyList.isEmpty()) {
|
||||
findViewById(R.id.history_title).setVisibility(View.GONE);
|
||||
clearHistoryText.setVisibility(View.GONE);
|
||||
expandHistoryText.setVisibility(View.GONE);
|
||||
} else {
|
||||
findViewById(R.id.history_title).setVisibility(View.VISIBLE);
|
||||
clearHistoryText.setVisibility(View.VISIBLE);
|
||||
|
||||
// 计算要显示的历史记录数量
|
||||
int showCount = historyList.size();
|
||||
if (!isHistoryExpanded && historyList.size() > VISIBLE_HISTORY_COUNT) {
|
||||
showCount = VISIBLE_HISTORY_COUNT;
|
||||
}
|
||||
|
||||
// 显示历史记录标签
|
||||
for (int i = 0; i < showCount; i++) {
|
||||
String keyword = historyList.get(i);
|
||||
TextView historyTag = createTagView(keyword, true);
|
||||
historyContainer.addView(historyTag);
|
||||
}
|
||||
|
||||
// 显示展开/收起按钮
|
||||
if (historyList.size() > VISIBLE_HISTORY_COUNT) {
|
||||
expandHistoryText.setVisibility(View.VISIBLE);
|
||||
if (isHistoryExpanded) {
|
||||
expandHistoryText.setText("收起");
|
||||
} else {
|
||||
expandHistoryText.setText("展开更多(" + (historyList.size() - VISIBLE_HISTORY_COUNT) + ")");
|
||||
}
|
||||
} else {
|
||||
expandHistoryText.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveSearchHistory(String query) {
|
||||
Set<String> historySet = sharedPreferences.getStringSet(SEARCH_HISTORY, new HashSet<>());
|
||||
Set<String> newSet = new LinkedHashSet<>(); // 使用LinkedHashSet保持顺序
|
||||
|
||||
// 先添加新的搜索(确保在最前面)
|
||||
newSet.add(query);
|
||||
|
||||
// 添加其他历史记录(排除重复项)
|
||||
for (String item : historySet) {
|
||||
if (!item.equals(query)) {
|
||||
newSet.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果超过最大数量,移除最旧的
|
||||
if (newSet.size() > MAX_HISTORY_COUNT) {
|
||||
List<String> list = new ArrayList<>(newSet);
|
||||
// 保留最新的6条
|
||||
List<String> newList = list.subList(0, MAX_HISTORY_COUNT);
|
||||
newSet = new LinkedHashSet<>(newList);
|
||||
}
|
||||
|
||||
sharedPreferences.edit().putStringSet(SEARCH_HISTORY, newSet).apply();
|
||||
}
|
||||
|
||||
// 相机相关方法保持不变
|
||||
private void openCamera() {
|
||||
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
|
||||
File photoFile = null;
|
||||
try {
|
||||
photoFile = createImageFile();
|
||||
} catch (IOException ex) {
|
||||
Toast.makeText(this, "创建文件失败", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
if (photoFile != null) {
|
||||
currentPhotoPath = photoFile.getAbsolutePath();
|
||||
Uri photoURI = FileProvider.getUriForFile(this,
|
||||
getPackageName() + ".fileprovider",
|
||||
photoFile);
|
||||
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
|
||||
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, "未找到相机应用", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private File createImageFile() throws IOException {
|
||||
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
|
||||
String imageFileName = "JPEG_" + timeStamp + "_";
|
||||
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
|
||||
return File.createTempFile(
|
||||
imageFileName,
|
||||
".jpg",
|
||||
storageDir
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
|
||||
if (currentPhotoPath != null) {
|
||||
Toast.makeText(this, "拍照成功,开始搜索...", Toast.LENGTH_SHORT).show();
|
||||
searchEditText.setText("图片搜索中...");
|
||||
performImageSearch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
openCamera();
|
||||
} else {
|
||||
Toast.makeText(this, "需要相机权限才能拍照搜索", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 图片搜索功能
|
||||
private void performImageSearch() {
|
||||
List<Product> similarProducts = findSimilarProducts();
|
||||
|
||||
if (similarProducts.isEmpty()) {
|
||||
searchEditText.setText("未找到相似商品");
|
||||
Toast.makeText(this, "未找到相似商品", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Intent intent = new Intent(this, SearchResultsActivity.class);
|
||||
intent.putExtra("search_type", "image");
|
||||
intent.putExtra("search_query", "图片搜索结果");
|
||||
ArrayList<Product> productList = new ArrayList<>(similarProducts);
|
||||
intent.putExtra("similar_products", productList);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Product> findSimilarProducts() {
|
||||
List<Product> similarProducts = new ArrayList<>();
|
||||
Collections.shuffle(allProducts);
|
||||
similarProducts = allProducts.subList(0, Math.min(5, allProducts.size()));
|
||||
return similarProducts;
|
||||
}
|
||||
|
||||
private void setupRecommendations() {
|
||||
List<String> randomRecommends = new ArrayList<>(recommendKeywords);
|
||||
Collections.shuffle(randomRecommends);
|
||||
List<String> selectedRecommends = randomRecommends.subList(0, Math.min(6, randomRecommends.size()));
|
||||
|
||||
recommendContainer.removeAllViews();
|
||||
|
||||
for (String keyword : selectedRecommends) {
|
||||
TextView recommendTag = createTagView(keyword, false);
|
||||
recommendContainer.addView(recommendTag);
|
||||
}
|
||||
}
|
||||
|
||||
private TextView createTagView(String keyword, boolean isHistory) {
|
||||
TextView tagView = new TextView(this);
|
||||
com.google.android.flexbox.FlexboxLayout.LayoutParams params = new com.google.android.flexbox.FlexboxLayout.LayoutParams(
|
||||
com.google.android.flexbox.FlexboxLayout.LayoutParams.WRAP_CONTENT,
|
||||
com.google.android.flexbox.FlexboxLayout.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
params.setMargins(0, 0, 16, 16);
|
||||
tagView.setLayoutParams(params);
|
||||
|
||||
tagView.setPadding(32, 16, 32, 16);
|
||||
tagView.setText(keyword);
|
||||
tagView.setTextSize(14);
|
||||
tagView.setBackgroundResource(R.drawable.tag_background);
|
||||
tagView.setTextColor(getResources().getColor(android.R.color.darker_gray));
|
||||
|
||||
tagView.setOnClickListener(v -> {
|
||||
searchEditText.setText(keyword);
|
||||
performSearch();
|
||||
});
|
||||
|
||||
return tagView;
|
||||
}
|
||||
|
||||
// 修改 performSearch 方法,确保使用统一的数据源
|
||||
private void performSearch() {
|
||||
String query = searchEditText.getText().toString().trim();
|
||||
if (!TextUtils.isEmpty(query)) {
|
||||
saveSearchHistory(query);
|
||||
|
||||
// 使用 DataManager 进行搜索
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
List<Item> searchResults = dataManager.searchItems(query);
|
||||
|
||||
// 转换为 Product 对象
|
||||
List<Product> productResults = new ArrayList<>();
|
||||
for (Item item : searchResults) {
|
||||
productResults.add(dataManager.convertItemToProduct(item));
|
||||
}
|
||||
|
||||
Intent intent = new Intent(this, SearchResultsActivity.class);
|
||||
intent.putExtra("search_query", query);
|
||||
intent.putExtra("search_results", new ArrayList<>(productResults)); // 传递搜索结果
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearSearchHistory() {
|
||||
sharedPreferences.edit().remove(SEARCH_HISTORY).apply();
|
||||
loadSearchHistory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
loadSearchHistory();
|
||||
}
|
||||
}
|
||||
@ -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,136 @@
|
||||
package com.startsmake.llrisetabbardemo.adapter;
|
||||
|
||||
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.Product;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder> {
|
||||
private List<Product> productList;
|
||||
private OnProductClickListener listener;
|
||||
|
||||
public interface OnProductClickListener {
|
||||
void onProductClick(Product product);
|
||||
void onWantClick(Product product);
|
||||
}
|
||||
|
||||
// 单参数构造函数 - 用于不需要点击监听的情况
|
||||
public SearchAdapter(List<Product> productList) {
|
||||
this.productList = productList;
|
||||
this.listener = null;
|
||||
}
|
||||
|
||||
// 双参数构造函数 - 用于需要点击监听的情况
|
||||
public SearchAdapter(List<Product> productList, OnProductClickListener listener) {
|
||||
this.productList = productList;
|
||||
this.listener = listener;
|
||||
}
|
||||
// 添加局部更新方法
|
||||
public void notifyProductChanged(String productId) {
|
||||
if (productList != null) {
|
||||
for (int i = 0; i < productList.size(); i++) {
|
||||
if (productList.get(i).getId().equals(productId)) {
|
||||
notifyItemChanged(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateData(List<Product> newList) {
|
||||
this.productList = newList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_product, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Product product = productList.get(position);
|
||||
|
||||
// 设置商品名称
|
||||
holder.productName.setText(product.getName());
|
||||
|
||||
// 设置价格
|
||||
holder.productPrice.setText(String.format("¥%.2f", product.getPrice()));
|
||||
|
||||
// 设置想要人数(使用真实数据)
|
||||
holder.productWantCount.setText(product.getWantCount() + "人想要");
|
||||
|
||||
// 设置卖家信用(使用真实数据)
|
||||
holder.sellerRating.setText(product.getSellerRating());
|
||||
|
||||
// 设置地区(使用真实数据)
|
||||
holder.productLocation.setText(product.getLocation());
|
||||
|
||||
// 设置包邮标签
|
||||
holder.freeShippingTag.setVisibility(product.isFreeShipping() ? View.VISIBLE : View.GONE);
|
||||
|
||||
// 设置想要按钮点击事件
|
||||
holder.wantButton.setOnClickListener(v -> {
|
||||
if (listener != null) {
|
||||
listener.onWantClick(product);
|
||||
}
|
||||
});
|
||||
// 在 onBindViewHolder 中添加
|
||||
if (product.isFreeShipping()) {
|
||||
holder.freeShippingTag.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.freeShippingTag.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// 设置整个商品项点击事件
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (listener != null) {
|
||||
listener.onProductClick(product);
|
||||
}
|
||||
});
|
||||
|
||||
// 这里可以设置商品图片,目前使用默认图片
|
||||
// 实际项目中应该使用图片加载库如Glide来加载网络图片
|
||||
// Glide.with(holder.itemView.getContext()).load(product.getImageUrl()).into(holder.productImage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return productList.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ImageView productImage;
|
||||
TextView productName;
|
||||
TextView productPrice;
|
||||
TextView productWantCount;
|
||||
TextView sellerRating;
|
||||
TextView productLocation;
|
||||
TextView freeShippingTag;
|
||||
TextView wantButton;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
productImage = itemView.findViewById(R.id.product_image);
|
||||
productName = itemView.findViewById(R.id.product_name);
|
||||
productPrice = itemView.findViewById(R.id.product_price);
|
||||
productWantCount = itemView.findViewById(R.id.product_want_count);
|
||||
sellerRating = itemView.findViewById(R.id.seller_rating);
|
||||
productLocation = itemView.findViewById(R.id.product_location);
|
||||
freeShippingTag = itemView.findViewById(R.id.free_shipping_tag);
|
||||
wantButton = itemView.findViewById(R.id.want_button);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.startsmake.llrisetabbardemo.api;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ApiClient {
|
||||
private static final String BASE_URL = "http://localhost:8080/";
|
||||
private static Retrofit retrofit = null;
|
||||
|
||||
public static Retrofit getClient() {
|
||||
if (retrofit == null) {
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.writeTimeout(30, TimeUnit.SECONDS)
|
||||
.build();
|
||||
|
||||
retrofit = new Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build();
|
||||
}
|
||||
return retrofit;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.startsmake.llrisetabbardemo.api;
|
||||
|
||||
import com.startsmake.llrisetabbardemo.api.response.BaseResponse;
|
||||
import com.startsmake.llrisetabbardemo.api.response.ProductResponse;
|
||||
import com.startsmake.llrisetabbardemo.api.response.UserResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Field;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface ApiService {
|
||||
// 获取API状态
|
||||
@GET("api")
|
||||
Call<BaseResponse> getApiStatus();
|
||||
|
||||
// 用户登录
|
||||
@FormUrlEncoded
|
||||
@POST("api/login")
|
||||
Call<UserResponse> login(@Field("phone") String phone, @Field("password") String password);
|
||||
|
||||
// 用户注册
|
||||
@FormUrlEncoded
|
||||
@POST("api/register")
|
||||
Call<UserResponse> register(@Field("phone") String phone, @Field("password") String password,
|
||||
@Field("username") String username);
|
||||
|
||||
// 获取商品列表
|
||||
@GET("api/products")
|
||||
Call<BaseResponse<List<ProductResponse>>> getProducts();
|
||||
|
||||
// 搜索商品
|
||||
@GET("api/products/search")
|
||||
Call<BaseResponse<List<ProductResponse>>> searchProducts(@Query("keyword") String keyword);
|
||||
|
||||
// 获取商品详情
|
||||
@GET("api/products/detail")
|
||||
Call<BaseResponse<ProductResponse>> getProductDetail(@Query("id") String productId);
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.startsmake.llrisetabbardemo.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class BaseResponse<T> {
|
||||
@SerializedName("status")
|
||||
private String status;
|
||||
|
||||
@SerializedName("message")
|
||||
private String message;
|
||||
|
||||
@SerializedName("data")
|
||||
private T data;
|
||||
|
||||
// Getters and Setters
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return "success".equals(status);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
package com.startsmake.llrisetabbardemo.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ProductResponse {
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("title")
|
||||
private String title;
|
||||
|
||||
@SerializedName("description")
|
||||
private String description;
|
||||
|
||||
@SerializedName("category")
|
||||
private String category;
|
||||
|
||||
@SerializedName("price")
|
||||
private double price;
|
||||
|
||||
@SerializedName("image_urls")
|
||||
private List<String> imageUrls;
|
||||
|
||||
@SerializedName("contact")
|
||||
private String contact;
|
||||
|
||||
@SerializedName("publish_time")
|
||||
private long publishTime;
|
||||
|
||||
@SerializedName("seller_id")
|
||||
private String sellerId;
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public List<String> getImageUrls() {
|
||||
return imageUrls;
|
||||
}
|
||||
|
||||
public void setImageUrls(List<String> imageUrls) {
|
||||
this.imageUrls = imageUrls;
|
||||
}
|
||||
|
||||
public String getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
public void setContact(String contact) {
|
||||
this.contact = contact;
|
||||
}
|
||||
|
||||
public long getPublishTime() {
|
||||
return publishTime;
|
||||
}
|
||||
|
||||
public void setPublishTime(long publishTime) {
|
||||
this.publishTime = publishTime;
|
||||
}
|
||||
|
||||
public String getSellerId() {
|
||||
return sellerId;
|
||||
}
|
||||
|
||||
public void setSellerId(String sellerId) {
|
||||
this.sellerId = sellerId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.startsmake.llrisetabbardemo.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class UserResponse extends BaseResponse<UserResponse.UserInfo> {
|
||||
public static class UserInfo {
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("username")
|
||||
private String username;
|
||||
|
||||
@SerializedName("phone")
|
||||
private String phone;
|
||||
|
||||
@SerializedName("token")
|
||||
private String token;
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.startsmake.llrisetabbardemo.decoration;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private int spanCount;
|
||||
private int spacing;
|
||||
private boolean includeEdge;
|
||||
|
||||
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
|
||||
this.spanCount = spanCount;
|
||||
this.spacing = spacing;
|
||||
this.includeEdge = includeEdge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||
int position = parent.getChildAdapterPosition(view);
|
||||
int column = position % spanCount;
|
||||
|
||||
if (includeEdge) {
|
||||
outRect.left = spacing - column * spacing / spanCount;
|
||||
outRect.right = (column + 1) * spacing / spanCount;
|
||||
|
||||
if (position < spanCount) {
|
||||
outRect.top = spacing;
|
||||
}
|
||||
outRect.bottom = spacing;
|
||||
} else {
|
||||
outRect.left = column * spacing / spanCount;
|
||||
outRect.right = spacing - (column + 1) * spacing / spanCount;
|
||||
if (position >= spanCount) {
|
||||
outRect.top = spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,121 @@
|
||||
package com.startsmake.llrisetabbardemo.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Item implements Serializable {
|
||||
private String id;
|
||||
private String title;
|
||||
private String description;
|
||||
private int wantCount;
|
||||
private double price;
|
||||
private List<String> imageUrls;
|
||||
private String category;
|
||||
private String location;
|
||||
private String contact;
|
||||
private String contactQQ; // 新增QQ联系方式
|
||||
private String contactWechat; // 新增微信联系方式
|
||||
private long publishTime;
|
||||
private String userId;
|
||||
private int viewCount; // 浏览数
|
||||
private int likeCount; // 点赞数
|
||||
|
||||
public Item() {
|
||||
imageUrls = new ArrayList<>();
|
||||
viewCount = 0;
|
||||
likeCount = 0;
|
||||
}
|
||||
|
||||
// Getter 和 Setter
|
||||
public int getWantCount() {
|
||||
return wantCount;
|
||||
}
|
||||
|
||||
public void setWantCount(int wantCount) {
|
||||
this.wantCount = wantCount;
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
public Item(String title, String description, double price, String category, String location, String contact) {
|
||||
this();
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.price = price;
|
||||
this.category = category;
|
||||
this.location = location;
|
||||
this.contact = contact;
|
||||
this.publishTime = System.currentTimeMillis();
|
||||
this.userId = "user_" + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// Getter 和 Setter 方法
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public double getPrice() { return price; }
|
||||
public void setPrice(double price) { this.price = price; }
|
||||
|
||||
public List<String> getImageUrls() { return imageUrls; }
|
||||
public void setImageUrls(List<String> imageUrls) { this.imageUrls = imageUrls; }
|
||||
public void addImageUrl(String imageUrl) { this.imageUrls.add(imageUrl); }
|
||||
|
||||
public String getCategory() { return category; }
|
||||
public void setCategory(String category) { this.category = category; }
|
||||
|
||||
public String getLocation() { return location; }
|
||||
public void setLocation(String location) { this.location = location; }
|
||||
|
||||
public String getContact() { return contact; }
|
||||
public void setContact(String contact) { this.contact = contact; }
|
||||
|
||||
public String getContactQQ() { return contactQQ; }
|
||||
public void setContactQQ(String contactQQ) { this.contactQQ = contactQQ; }
|
||||
|
||||
public String getContactWechat() { return contactWechat; }
|
||||
public void setContactWechat(String contactWechat) { this.contactWechat = contactWechat; }
|
||||
|
||||
public long getPublishTime() { return publishTime; }
|
||||
public void setPublishTime(long publishTime) { this.publishTime = publishTime; }
|
||||
|
||||
public String getUserId() { return userId; }
|
||||
public void setUserId(String userId) { this.userId = userId; }
|
||||
|
||||
public int getViewCount() { return viewCount; }
|
||||
public void setViewCount(int viewCount) { this.viewCount = viewCount; }
|
||||
|
||||
public int getLikeCount() { return likeCount; }
|
||||
public void setLikeCount(int likeCount) { this.likeCount = likeCount; }
|
||||
|
||||
/**
|
||||
* 增加浏览数
|
||||
*/
|
||||
public void incrementViewCount() {
|
||||
this.viewCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加点赞数
|
||||
*/
|
||||
public void incrementLikeCount() {
|
||||
this.likeCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Item{" +
|
||||
"id='" + id + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", price=" + price +
|
||||
", category='" + category + '\'' +
|
||||
", location='" + location + '\'' +
|
||||
", publishTime=" + publishTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -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,27 @@
|
||||
package com.startsmake.llrisetabbardemo.model;
|
||||
|
||||
public class User {
|
||||
private String phone;
|
||||
private String password;
|
||||
private String username;
|
||||
private long registerTime;
|
||||
|
||||
public User(String phone, String password) {
|
||||
this.phone = phone;
|
||||
this.password = password;
|
||||
this.username = "用户_" + phone.substring(7);
|
||||
this.registerTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getPhone() { return phone; }
|
||||
public void setPhone(String phone) { this.phone = phone; }
|
||||
|
||||
public String getPassword() { return password; }
|
||||
public void setPassword(String password) { this.password = password; }
|
||||
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
|
||||
public long getRegisterTime() { return registerTime; }
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
package model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Item implements Serializable {
|
||||
private String id;
|
||||
private String title;
|
||||
private String description;
|
||||
private double price;
|
||||
private List<String> imageUrls;
|
||||
private String category;
|
||||
private String location;
|
||||
private String contact;
|
||||
private long publishTime;
|
||||
private String userId;
|
||||
|
||||
public Item() {
|
||||
imageUrls = new ArrayList<>();
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public double getPrice() { return price; }
|
||||
public void setPrice(double price) { this.price = price; }
|
||||
|
||||
public List<String> getImageUrls() { return imageUrls; }
|
||||
public void setImageUrls(List<String> imageUrls) { this.imageUrls = imageUrls; }
|
||||
|
||||
public String getCategory() { return category; }
|
||||
public void setCategory(String category) { this.category = category; }
|
||||
|
||||
public String getLocation() { return location; }
|
||||
public void setLocation(String location) { this.location = location; }
|
||||
|
||||
public String getContact() { return contact; }
|
||||
public void setContact(String contact) { this.contact = contact; }
|
||||
|
||||
public long getPublishTime() { return publishTime; }
|
||||
public void setPublishTime(long publishTime) { this.publishTime = publishTime; }
|
||||
|
||||
public String getUserId() { return userId; }
|
||||
public void setUserId(String userId) { this.userId = userId; }
|
||||
}
|
||||
@ -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>
|
||||
@ -1,8 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<solid android:color="#FFFFFF" />
|
||||
<stroke android:width="1dp" android:color="#E0E0E0" />
|
||||
<corners android:radius="8dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#e0e0e0" />
|
||||
</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,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#87CEEB"/>
|
||||
<corners android:radius="12dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?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,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#2196F3"/>
|
||||
<corners android:radius="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="#2196F3"/>
|
||||
<corners android:radius="12dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f8f9fa" />
|
||||
<corners android:radius="8dp" />
|
||||
<stroke android:width="1dp" android:color="#dee2e6" />
|
||||
</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="#FFFFFF"/>
|
||||
<corners android:radius="12dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="#FFFFFFFF" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#FFE0E0E0" />
|
||||
|
||||
<!-- 添加阴影效果 -->
|
||||
<padding
|
||||
android:left="2dp"
|
||||
android:top="2dp"
|
||||
android:right="2dp"
|
||||
android:bottom="2dp" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="12dp" />
|
||||
<solid android:color="#FF00BCD4" />
|
||||
<stroke
|
||||
android:width="0.5dp"
|
||||
android:color="#FF0097A7" />
|
||||
<padding
|
||||
android:left="8dp"
|
||||
android:top="2dp"
|
||||
android:right="8dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#F5F5F5"
|
||||
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,6 @@
|
||||
<?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:radius="16dp" />
|
||||
<stroke android:width="1dp" android:color="#f0f0f0" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?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,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f8f9fa" />
|
||||
<corners android:radius="20dp" />
|
||||
<stroke android:width="1dp" android:color="#e9ecef" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#fff2f2" />
|
||||
<corners android:radius="20dp" />
|
||||
<stroke android:width="1dp" android:color="#ff6b35" />
|
||||
</shape>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:startColor="#E3F2FD"
|
||||
android:endColor="#BBDEFB"
|
||||
android:angle="90"/>
|
||||
</shape>
|
||||
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z M12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M12,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6 6,-2.69 6,-6 -2.69,-6 -6,-6z M12,16c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M12,9.5c-1.38,0 -2.5,1.12 -2.5,2.5s1.12,2.5 2.5,2.5 2.5,-1.12 2.5,-2.5 -1.12,-2.5 -2.5,-2.5z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="@color/white">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
|
||||
</vector>
|
||||
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:strokeColor="#FF666666"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="@android:color/transparent"
|
||||
android:pathData="M9,6l6,6l-6,6"/>
|
||||
</vector>
|
||||
|
After Width: | Height: | Size: 39 KiB |
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z M12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12.5,7H11v6l5.25,3.15l0.75,-1.23l-4.5,-2.67z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M7,12.5h10v-1H7z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M20,6h-2.18c0.11,-0.31 0.18,-0.65 0.18,-1c0,-1.66 -1.34,-3 -3,-3c-1.05,0 -1.96,0.54 -2.5,1.35C12.96,2.54 12.05,2 11,2C9.34,2 8,3.34 8,5c0,0.35 0.07,0.69 0.18,1H4c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2V8C22,6.89 21.11,6 20,6z M15,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S14.45,4 15,4z M11,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S10.45,4 11,4z M4,19v-6h6v6H4z M14,19v-6h6v6H14z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF757575"
|
||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF4CAF50"
|
||||
android:pathData="M20,2H4C2.9,2 2,2.9 2,4v12c0,1.1 0.9,2 2,2h4v3c0,0.55 0.45,1 1,1h0.5c0.25,0 0.49,-0.09 0.67,-0.26L13.9,18H20c1.1,0 2,-0.9 2,-2V4C22,2.9 21.1,2 20,2z M20,16h-6.09c-0.18,0 -0.35,0.06 -0.49,0.17l-1.42,1.42V16H4V4h16V16z"/>
|
||||
<path
|
||||
android:fillColor="#FF4CAF50"
|
||||
android:pathData="M11,11h2v2h-2z M11,7h2v2h-2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z M12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M11,16h2v2h-2z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5C16,7.79 14.21,6 12,6z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3S14.34,11 16,11z M8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8S6.34,11 8,11z M8,13c-2.33,0 -7,1.17 -7,3.5V19h14v-2.5C15,14.17 10.33,13 8,13z M16,13c-0.29,0 -0.62,0.02 -0.97,0.05c1.16,0.84 1.97,1.97 1.97,3.45V19h6v-2.5C23,14.17 18.33,13 16,13z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M20,2H4C2.9,2 2,2.9 2,4v12c0,1.1 0.9,2 2,2h4v-2H4V4h16v12h-4v2h4c1.1,0 2,-0.9 2,-2V4C22,2.9 21.1,2 20,2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M17,7l-1.41,1.41L18.17,11H8v2h10.17l-2.58,2.58L17,17l5,-5L17,7z M4,5h8V3H4C2.9,3 2,3.9 2,5v14c0,1.1 0.9,2 2,2h8v-2H4V5z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z M18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z M12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM19,19H5V5h14V19z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M8.5,15H6.5l4,-7 4,7h-2l-1.5,-2.5L8.5,15z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M17,12.5h-4V11h4V12.5z"/>
|
||||
</vector>
|
||||
@ -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,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z M18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1L18,16z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M15,9H9v2h1v3h4v-3h1V9z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#BDBDBD"
|
||||
android:pathData="M19,5v14H5V5h14m0-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
<path
|
||||
android:fillColor="#BDBDBD"
|
||||
android:pathData="M12,12c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM14,16v2h-4v-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9H1l3.89,3.89l0.07,0.14L9,12H6c0,-3.87 3.13,-7 7,-7s7,3.13 7,7s-3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,8v5l4.25,2.52l0.77,-1.28l-3.52,-2.09V8z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,39 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M3,11h8V3H3V11zM5,5h4v4H5V5z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M3,21h8v-8H3V21zM5,15h4v4H5V15z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M13,3v8h8V3H13zM19,9h-4V5h4V9z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M21,19h-2v2h2V19z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M13,13h2v2h-2V13z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M15,15h2v2h-2V15z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M13,17h2v2h-2V17z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M15,19h2v2h-2V19z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M17,17h2v2h-2V17z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M19,15h2v2h-2V15z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M17,13h2v2h-2V13z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.82,11.69 4.82,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#2196F3"
|
||||
android:pathData="M19,6h-2c0,-2.8 -2.2,-5 -5,-5S7,3.2 7,6H5C3.9,6 3,6.9 3,8v12c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V8C21,6.9 20.1,6 19,6z M12,3c1.7,0 3,1.3 3,3H9C9,4.3 10.3,3 12,3z M19,20H5V8h2v2c0,0.6 0.4,1 1,1s1,-0.4 1,-1V8h6v2c0,0.6 0.4,1 1,1s1,-0.4 1,-1V8h2V20z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#F5F5F5"/>
|
||||
<corners android:radius="8dp"/>
|
||||
<stroke android:width="1dp" android:color="#E3F2FD"/>
|
||||
</shape>
|
||||
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="12dp" />
|
||||
|
||||
<!-- 银白色渐变 -->
|
||||
<gradient
|
||||
android:type="linear"
|
||||
android:startColor="#FFE8E8E8"
|
||||
android:centerColor="#FFD6D6D6"
|
||||
android:endColor="#FFC0C0C0"
|
||||
android:angle="45" />
|
||||
|
||||
<stroke
|
||||
android:width="0.8dp"
|
||||
android:color="#FFA0A0A0" />
|
||||
|
||||
<padding
|
||||
android:left="8dp"
|
||||
android:top="2dp"
|
||||
android:right="8dp"
|
||||
android:bottom="2dp" />
|
||||
</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="#2196F3" />
|
||||
<corners android:radius="8dp" />
|
||||
</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="@android:color/white" />
|
||||
<corners android:radius="@dimen/product_card_corner_radius" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#E3F2FD" />
|
||||
</shape>
|
||||
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- 阴影 -->
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#E3F2FD" />
|
||||
<corners android:radius="@dimen/product_card_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<!-- 内容 -->
|
||||
<item android:top="2dp" android:bottom="2dp" android:left="2dp" android:right="2dp">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="@dimen/product_card_corner_radius" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#BBDEFB" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
@ -1,6 +1,11 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<!-- 设置圆角半径 -->
|
||||
<corners android:radius="20dp"/>
|
||||
<!-- 背景颜色 -->
|
||||
<solid android:color="@android:color/white"/>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<!-- 设置圆角半径 -->
|
||||
<corners android:radius="20dp" />
|
||||
|
||||
<!-- 背景颜色 -->
|
||||
<solid android:color="@android:color/white" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="25dp" />
|
||||
|
||||
<!-- 渐变背景 -->
|
||||
<gradient
|
||||
android:type="linear"
|
||||
android:startColor="#FFFFFF"
|
||||
android:endColor="#F8F9FA"
|
||||
android:angle="90" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#E0E0E0" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF"/>
|
||||
<corners android:radius="24dp"/>
|
||||
<stroke android:width="1dp" android:color="#E3F2FD"/>
|
||||
</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="@android:color/transparent" />
|
||||
<stroke
|
||||
android:width="0.8dp"
|
||||
android:color="#999999" />
|
||||
<corners android:radius="18dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF"/>
|
||||
<corners android:radius="18dp"/>
|
||||
<stroke android:width="1dp" android:color="#E0E0E0"/>
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#E3F2FD"/>
|
||||
<corners android:radius="18dp"/>
|
||||
<stroke android:width="1dp" android:color="#2196F3"/>
|
||||
</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="20dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#e0e0e0" />
|
||||
</shape>
|
||||
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<!-- 圆角 -->
|
||||
<corners android:radius="16dp" />
|
||||
|
||||
<!-- 背景色 - 白色 -->
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
<!-- 灰色边框 -->
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/gray_300" />
|
||||
|
||||
<!-- 内边距 -->
|
||||
<padding
|
||||
android:left="8dp"
|
||||
android:top="4dp"
|
||||
android:right="8dp"
|
||||
android:bottom="4dp" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f5f5f5" />
|
||||
<stroke android:width="1dp" android:color="#e0e0e0" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="16dp" />
|
||||
|
||||
<!-- 渐变背景 -->
|
||||
<gradient
|
||||
android:type="linear"
|
||||
android:startColor="@color/primary_blue_light"
|
||||
android:endColor="@color/primary_blue"
|
||||
android:angle="90" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/primary_blue_dark" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#fff2f2" />
|
||||
<stroke android:width="1dp" android:color="#ff6b35" />
|
||||
<corners android:radius="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="#E3F2FD"/>
|
||||
<corners android:radius="10dp"/>
|
||||
</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="#E3F2FD" />
|
||||
<corners android:radius="6dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#2196F3" />
|
||||
</shape>
|
||||
@ -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,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue