liuqirui_part
刘骐瑞 6 months ago
parent 5b3b5c1923
commit d86c0e6c70

@ -4,7 +4,7 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-10-22T09:46:12.826144800Z">
<DropdownSelection timestamp="2025-10-22T14:13:58.701426800Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\asus\.android\avd\Pixel.avd" />

@ -52,6 +52,8 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.8.20"
implementation 'com.google.android.flexbox:flexbox:3.0.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
//gson
implementation 'com.google.code.gson:gson:2.10.1'
//
implementation project(':mainnavigatetabbar')

@ -2,6 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.startsmake.llrisetabbardemo">
<!-- 添加相机权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
@ -33,9 +39,33 @@
<activity
android:name=".activity.ForgotPasswordActivity"
android:exported="false" />
<!-- 聊天页面 -->
<activity
android:name=".activity.ChatActivity"
android:exported="false" />
<!-- 搜索页面 -->
<activity
android:name=".activity.SearchActivity"
android:exported="false" />
<!-- 搜索结果页面 -->
<activity
android:name=".activity.SearchResultsActivity"
android:exported="false" />
<!-- 添加FileProvider支持用于摄像头功能 -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

@ -0,0 +1,76 @@
package adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.model.Item;
import java.util.List;
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ViewHolder> {
private Context context;
private List<Item> itemList;
private OnItemClickListener listener;
public interface OnItemClickListener {
void onItemClick(Item item);
}
public ProductAdapter(Context context, List<Item> itemList, OnItemClickListener listener) {
this.context = context;
this.itemList = itemList;
this.listener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_product, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Item item = itemList.get(position);
holder.tvTitle.setText(item.getTitle());
holder.tvDescription.setText(item.getDescription());
holder.tvPrice.setText(String.format("¥%.2f", item.getPrice()));
holder.tvCategory.setText(item.getCategory());
// 设置点击事件
holder.itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onItemClick(item);
}
});
}
@Override
public int getItemCount() {
return itemList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvTitle;
TextView tvDescription;
TextView tvCategory;
TextView tvPrice;
public ViewHolder(@NonNull View itemView) {
super(itemView);
tvTitle = itemView.findViewById(R.id.product_name);
tvDescription = itemView.findViewById(R.id.product_description);
tvCategory = itemView.findViewById(R.id.product_category);
tvPrice = itemView.findViewById(R.id.product_price);
}
}
}

@ -12,6 +12,9 @@ import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.textfield.TextInputEditText;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.manager.UserManager;
import java.util.Random;
public class ForgotPasswordActivity extends AppCompatActivity {
@ -22,12 +25,15 @@ public class ForgotPasswordActivity extends AppCompatActivity {
private CountDownTimer countDownTimer;
private boolean isCounting = false;
private String verificationCode = "";
private UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_forgot_password);
userManager = UserManager.getInstance(this);
initViews();
setupClickListeners();
}
@ -63,21 +69,54 @@ public class ForgotPasswordActivity extends AppCompatActivity {
private void sendVerificationCode() {
String phone = etPhone.getText().toString().trim();
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
if (!validatePhone(phone)) {
return;
}
if (phone.length() != 11) {
etPhone.setError("手机号格式不正确");
// 检查用户是否存在
if (!userManager.isPhoneRegistered(phone)) {
etPhone.setError("该手机号未注册");
etPhone.requestFocus();
Toast.makeText(this, "该手机号未注册,请先注册", Toast.LENGTH_SHORT).show();
return;
}
if (!isCounting) {
// 生成随机验证码
verificationCode = generateVerificationCode();
startCountDown();
Toast.makeText(this, "验证码已发送", Toast.LENGTH_SHORT).show();
// 这里应该调用后端API发送验证码
// 模拟发送验证码(在实际应用中应该通过短信发送)
Toast.makeText(this, "验证码已发送: " + verificationCode, Toast.LENGTH_LONG).show();
}
}
private boolean validatePhone(String phone) {
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
etPhone.requestFocus();
return false;
}
if (phone.length() != 11) {
etPhone.setError("手机号格式不正确");
etPhone.requestFocus();
return false;
}
if (!phone.startsWith("1")) {
etPhone.setError("手机号格式不正确");
etPhone.requestFocus();
return false;
}
return true;
}
private String generateVerificationCode() {
Random random = new Random();
int code = 100000 + random.nextInt(900000);
return String.valueOf(code);
}
private void startCountDown() {
@ -95,6 +134,8 @@ public class ForgotPasswordActivity extends AppCompatActivity {
isCounting = false;
btnSendCode.setEnabled(true);
btnSendCode.setText("发送验证码");
// 验证码过期
verificationCode = "";
}
}.start();
}
@ -104,43 +145,144 @@ public class ForgotPasswordActivity extends AppCompatActivity {
String code = etVerificationCode.getText().toString().trim();
String newPassword = etNewPassword.getText().toString().trim();
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
if (!validateResetInput(phone, code, newPassword)) {
return;
}
if (code.isEmpty()) {
etVerificationCode.setError("请输入验证码");
// 验证验证码
if (!code.equals(verificationCode)) {
etVerificationCode.setError("验证码错误");
etVerificationCode.requestFocus();
Toast.makeText(this, "请输入正确的验证码", Toast.LENGTH_SHORT).show();
return;
}
if (newPassword.isEmpty()) {
etNewPassword.setError("请输入新密码");
// 检查验证码是否过期
if (verificationCode.isEmpty()) {
etVerificationCode.setError("验证码已过期,请重新获取");
etVerificationCode.requestFocus();
Toast.makeText(this, "验证码已过期,请重新获取", Toast.LENGTH_SHORT).show();
return;
}
// 重置密码
boolean success = userManager.resetPassword(phone, newPassword);
if (success) {
performResetSuccess(phone);
} else {
Toast.makeText(this, "重置密码失败,请检查手机号是否正确", Toast.LENGTH_SHORT).show();
etPhone.setError("手机号未注册或不存在");
etPhone.requestFocus();
}
}
private boolean validateResetInput(String phone, String code, String newPassword) {
// 验证手机号
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
etPhone.requestFocus();
return false;
}
if (phone.length() != 11) {
etPhone.setError("手机号格式不正确");
return;
etPhone.requestFocus();
return false;
}
if (!phone.startsWith("1")) {
etPhone.setError("手机号格式不正确");
etPhone.requestFocus();
return false;
}
// 验证验证码
if (code.isEmpty()) {
etVerificationCode.setError("请输入验证码");
etVerificationCode.requestFocus();
return false;
}
if (code.length() != 6) {
etVerificationCode.setError("验证码格式不正确");
etVerificationCode.requestFocus();
return false;
}
// 验证新密码
if (newPassword.isEmpty()) {
etNewPassword.setError("请输入新密码");
etNewPassword.requestFocus();
return false;
}
if (newPassword.length() < 6) {
etNewPassword.setError("密码至少6位");
return;
etNewPassword.requestFocus();
return false;
}
if (newPassword.length() > 20) {
etNewPassword.setError("密码最多20位");
etNewPassword.requestFocus();
return false;
}
// 模拟重置密码成功
performResetPassword();
// 检查密码强度(可选增强)
if (!isPasswordStrong(newPassword)) {
etNewPassword.setError("密码过于简单,建议包含字母和数字");
etNewPassword.requestFocus();
return false;
}
return true;
}
private boolean isPasswordStrong(String password) {
// 简单的密码强度检查:至少包含字母和数字
boolean hasLetter = false;
boolean hasDigit = false;
for (char c : password.toCharArray()) {
if (Character.isLetter(c)) {
hasLetter = true;
} else if (Character.isDigit(c)) {
hasDigit = true;
}
// 如果已经满足条件,提前返回
if (hasLetter && hasDigit) {
return true;
}
}
return hasLetter && hasDigit;
}
private void performResetPassword() {
private void performResetSuccess(String phone) {
Toast.makeText(this, "密码重置成功!", Toast.LENGTH_SHORT).show();
// 重置成功后跳转到登录页面
// 重置成功后跳转到登录页面,并传递手机号方便用户登录
Intent intent = new Intent(ForgotPasswordActivity.this, LoginActivity.class);
intent.putExtra("phone", phone);
intent.putExtra("from_forgot_password", true);
startActivity(intent);
finish();
}
@Override
protected void onResume() {
super.onResume();
// 如果从Intent中获取到手机号自动填充
Intent intent = getIntent();
if (intent != null && intent.hasExtra("phone")) {
String phone = intent.getStringExtra("phone");
if (phone != null && !phone.isEmpty()) {
etPhone.setText(phone);
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
@ -148,4 +290,4 @@ public class ForgotPasswordActivity extends AppCompatActivity {
countDownTimer.cancel();
}
}
}
}

@ -1,6 +1,7 @@
package com.startsmake.llrisetabbardemo.activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
@ -10,20 +11,35 @@ import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.textfield.TextInputEditText;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.manager.UserManager;
import com.startsmake.llrisetabbardemo.model.User;
public class LoginActivity extends AppCompatActivity {
private TextInputEditText etPhone, etPassword;
private Button btnLogin, btnSkipLogin;
private TextView tvForgotPassword, tvRegister;
private UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// 初始化用户管理器
userManager = UserManager.getInstance(this);
// 移除自动登录检查,让用户手动登录
// if (userManager.isLoggedIn()) {
// navigateToMain();
// return;
// }
initViews();
setupClickListeners();
// 检查是否有从其他页面传递过来的手机号
handleIntentData();
}
private void initViews() {
@ -55,36 +71,97 @@ public class LoginActivity extends AppCompatActivity {
});
}
private void handleIntentData() {
Intent intent = getIntent();
if (intent != null && intent.hasExtra("phone")) {
String phone = intent.getStringExtra("phone");
if (phone != null && !phone.isEmpty()) {
etPhone.setText(phone);
// 自动聚焦到密码输入框
etPassword.requestFocus();
}
}
}
private void attemptLogin() {
String phone = etPhone.getText().toString().trim();
String password = etPassword.getText().toString().trim();
if (!validateInput(phone, password)) {
return;
}
// 使用 UserManager 进行登录验证
User user = userManager.loginUser(phone, password);
if (user != null) {
// 登录成功
performLoginSuccess(user);
} else {
// 登录失败
showLoginError();
}
}
private boolean validateInput(String phone, String password) {
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
return;
etPhone.requestFocus();
return false;
}
if (password.isEmpty()) {
etPassword.setError("请输入密码");
return;
etPassword.requestFocus();
return false;
}
if (phone.length() != 11) {
etPhone.setError("手机号格式不正确");
return;
etPhone.requestFocus();
return false;
}
if (!phone.startsWith("1")) {
etPhone.setError("手机号格式不正确");
etPhone.requestFocus();
return false;
}
if (password.length() < 6) {
etPassword.setError("密码至少6位");
etPassword.requestFocus();
return false;
}
// 模拟登录成功(因为没有后端)
performLogin();
return true;
}
private void performLogin() {
private void performLoginSuccess(User user) {
// 保存登录状态和用户信息
saveLoginState(user);
Toast.makeText(this, "登录成功!", Toast.LENGTH_SHORT).show();
navigateToMain();
}
private void saveLoginState(User user) {
SharedPreferences sp = getSharedPreferences("user_info", MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean("is_logged_in", true);
editor.putString("user_phone", user.getPhone());
editor.putString("user_name", user.getUsername());
editor.putString("user_token", "mock_token_" + System.currentTimeMillis());
editor.apply();
}
private void showLoginError() {
Toast.makeText(this, "手机号或密码错误", Toast.LENGTH_SHORT).show();
etPassword.setError("密码错误");
etPassword.requestFocus();
}
private void skipToMain() {
Toast.makeText(this, "跳过登录,进入主界面", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "游客模式进入", Toast.LENGTH_SHORT).show();
navigateToMain();
}
@ -93,4 +170,10 @@ public class LoginActivity extends AppCompatActivity {
startActivity(intent);
finish();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 清理资源
}
}

@ -4,27 +4,24 @@ import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
// 改为 AndroidX
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import com.startsmake.llrisetabbardemo.fragment.PublishFragment;
import com.startsmake.llrisetabbardemo.fragment.HomeFragment;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.fragment.CityFragment;
import com.startsmake.llrisetabbardemo.fragment.HomeFragment;
import com.startsmake.llrisetabbardemo.fragment.MessageFragment;
import com.startsmake.llrisetabbardemo.fragment.PersonFragment;
import com.startsmake.llrisetabbardemo.fragment.PublishFragment;
import com.startsmake.mainnavigatetabbar.widget.MainNavigateTabBar;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG_PAGE_HOME = "首页";
private static final String TAG_PAGE_CITY = "同城";
private static final String TAG_PAGE_CITY = "集市";
private static final String TAG_PAGE_PUBLISH = "发布";
private static final String TAG_PAGE_MESSAGE = "消息";
private static final String TAG_PAGE_PERSON = "我的";
@ -36,24 +33,56 @@ public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigateTabBar = (MainNavigateTabBar) findViewById(R.id.mainTabBar);
// 初始化视图,传递 savedInstanceState
initViews(savedInstanceState);
// 检查登录状态(可选)
checkLoginStatus();
}
private void initViews(Bundle savedInstanceState) {
try {
mNavigateTabBar = findViewById(R.id.mainTabBar);
mNavigateTabBar.onRestoreInstanceState(savedInstanceState);
if (mNavigateTabBar == null) {
Toast.makeText(this, "底部导航栏初始化失败", Toast.LENGTH_SHORT).show();
return;
}
mNavigateTabBar.addTab(HomeFragment.class, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_home, R.mipmap.comui_tab_home_selected, TAG_PAGE_HOME));
mNavigateTabBar.addTab(CityFragment.class, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_city, R.mipmap.comui_tab_city_selected, TAG_PAGE_CITY));
mNavigateTabBar.onRestoreInstanceState(savedInstanceState);
// 修正:移除重复的发布标签,只保留一个
mNavigateTabBar.addTab(null, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_post, R.mipmap.comui_tab_post, TAG_PAGE_PUBLISH));
// 添加Tab
mNavigateTabBar.addTab(HomeFragment.class, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_home, R.mipmap.comui_tab_home_selected, TAG_PAGE_HOME));
mNavigateTabBar.addTab(CityFragment.class, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_city, R.mipmap.comui_tab_city_selected, TAG_PAGE_CITY));
mNavigateTabBar.addTab(null, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_post, R.mipmap.comui_tab_post, TAG_PAGE_PUBLISH)); // 发布按钮
mNavigateTabBar.addTab(MessageFragment.class, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_message, R.mipmap.comui_tab_message_selected, TAG_PAGE_MESSAGE));
mNavigateTabBar.addTab(PersonFragment.class, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_person, R.mipmap.comui_tab_person_selected, TAG_PAGE_PERSON));
mNavigateTabBar.addTab(MessageFragment.class, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_message, R.mipmap.comui_tab_message_selected, TAG_PAGE_MESSAGE));
mNavigateTabBar.addTab(PersonFragment.class, new MainNavigateTabBar.TabParam(R.mipmap.comui_tab_person, R.mipmap.comui_tab_person_selected, TAG_PAGE_PERSON));
} catch (Exception e) {
Toast.makeText(this, "界面初始化失败", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mNavigateTabBar.onSaveInstanceState(outState);
if (mNavigateTabBar != null) {
mNavigateTabBar.onSaveInstanceState(outState);
}
}
private void checkLoginStatus() {
// 这里可以根据需要决定是否强制登录
// 如果应用要求必须登录,可以在这里跳转到登录页面
/*
SharedPreferences sp = getSharedPreferences("user_info", MODE_PRIVATE);
if (!sp.getBoolean("is_logged_in", false)) {
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
finish();
}
*/
}
// 发布按钮点击事件
@ -64,48 +93,129 @@ public class MainActivity extends AppCompatActivity {
// 切换到发布Fragment
public void switchToPublishFragment() {
PublishFragment publishFragment = new PublishFragment();
try {
PublishFragment publishFragment = new PublishFragment();
// 使用FragmentTransaction来显示发布页面
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// 使用FragmentTransaction来显示发布页面
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// 替换当前显示的Fragment
transaction.replace(R.id.container, publishFragment, "PublishFragment");
transaction.addToBackStack("publish"); // 允许用户按返回键回到之前的Fragment
transaction.commit();
// 替换当前显示的Fragment
transaction.replace(R.id.main_container, publishFragment, "PublishFragment");
transaction.addToBackStack("publish"); // 允许用户按返回键回到之前的Fragment
transaction.commit();
} catch (Exception e) {
Toast.makeText(this, "打开发布页面失败", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
// 切换回首页Fragment
public void switchToHomeFragment() {
// 返回到首页
getSupportFragmentManager().popBackStackImmediate();
// 确保底部导航栏选中首页
if (mNavigateTabBar != null) {
mNavigateTabBar.setCurrentSelectedTab(0); // 0 是首页的索引
try {
// 返回到首页
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
} else {
// 如果后退栈为空,直接切换到首页
HomeFragment homeFragment = new HomeFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.main_container, homeFragment, TAG_PAGE_HOME);
transaction.commit();
}
// 确保底部导航栏选中首页
if (mNavigateTabBar != null) {
mNavigateTabBar.setCurrentSelectedTab(0); // 0 是首页的索引
}
} catch (Exception e) {
Toast.makeText(this, "返回首页失败", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
// 获取HomeFragment实例的方法
public HomeFragment getHomeFragment() {
// 这里根据您的实际情况获取HomeFragment
// 如果HomeFragment是当前显示的Fragment可以通过Tag获取
Fragment fragment = getSupportFragmentManager().findFragmentByTag("home");
if (fragment instanceof HomeFragment) {
return (HomeFragment) fragment;
try {
// 方法1通过Tag查找
Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_PAGE_HOME);
if (fragment instanceof HomeFragment) {
return (HomeFragment) fragment;
}
// 方法2遍历所有Fragment找到HomeFragment实例
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragmentItem : fragments) {
if (fragmentItem instanceof HomeFragment && fragmentItem.isVisible()) {
return (HomeFragment) fragmentItem;
}
}
}
// 方法3查找当前显示的Fragment
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.main_container);
if (currentFragment instanceof HomeFragment) {
return (HomeFragment) currentFragment;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 获取HomeFragment实例的方法
public HomeFragment getHomeFragment() {
// 这里根据您的实际情况获取HomeFragment
// 如果HomeFragment是当前显示的Fragment可以通过Tag获取
Fragment fragment = getSupportFragmentManager().findFragmentByTag("home");
if (fragment instanceof HomeFragment) {
return (HomeFragment) fragment;
@Override
public void onBackPressed() {
// 处理返回键
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
// 如果有Fragment在后退栈中先弹出
getSupportFragmentManager().popBackStack();
// 确保底部导航栏状态正确
if (mNavigateTabBar != null) {
mNavigateTabBar.setCurrentSelectedTab(0); // 回到首页
}
} else {
// 双击退出应用
if (isTaskRoot()) {
// 如果是应用的根Activity可以实现双击退出
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "再按一次退出应用", Toast.LENGTH_SHORT).show();
handler.postDelayed(() -> doubleBackToExitPressedOnce = false, 2000);
} else {
super.onBackPressed();
}
}
return null;
}
// 双击退出相关变量
private boolean doubleBackToExitPressedOnce = false;
private android.os.Handler handler = new android.os.Handler();
@Override
protected void onDestroy() {
super.onDestroy();
// 清理Handler防止内存泄漏
handler.removeCallbacksAndMessages(null);
}
// 切换到指定Tab的方法 - 简化版本
public void switchToTab(int tabIndex) {
if (mNavigateTabBar != null && tabIndex >= 0 && tabIndex <= 4) { // 假设有5个tab
mNavigateTabBar.setCurrentSelectedTab(tabIndex);
}
}
// 显示Toast的便捷方法
public void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}

@ -12,6 +12,10 @@ import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.textfield.TextInputEditText;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.manager.UserManager;
import com.startsmake.llrisetabbardemo.model.User;
import java.util.Random;
public class RegisterActivity extends AppCompatActivity {
@ -22,12 +26,15 @@ public class RegisterActivity extends AppCompatActivity {
private CountDownTimer countDownTimer;
private boolean isCounting = false;
private String verificationCode = "";
private UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
userManager = UserManager.getInstance(this);
initViews();
setupClickListeners();
}
@ -63,23 +70,55 @@ public class RegisterActivity extends AppCompatActivity {
private void sendVerificationCode() {
String phone = etPhone.getText().toString().trim();
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
if (!validatePhone(phone)) {
return;
}
if (phone.length() != 11) {
etPhone.setError("手机号格式不正确");
// 检查用户是否已存在
if (userManager.isPhoneRegistered(phone)) {
etPhone.setError("该手机号已注册");
etPhone.requestFocus();
return;
}
if (!isCounting) {
// 生成随机验证码
verificationCode = generateVerificationCode();
startCountDown();
Toast.makeText(this, "验证码已发送", Toast.LENGTH_SHORT).show();
// 这里应该调用后端API发送验证码
// 模拟发送验证码(在实际应用中应该通过短信发送)
Toast.makeText(this, "验证码已发送: " + verificationCode, Toast.LENGTH_LONG).show();
}
}
private boolean validatePhone(String phone) {
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
etPhone.requestFocus();
return false;
}
if (phone.length() != 11) {
etPhone.setError("手机号格式不正确");
etPhone.requestFocus();
return false;
}
if (!phone.startsWith("1")) {
etPhone.setError("手机号格式不正确");
etPhone.requestFocus();
return false;
}
return true;
}
private String generateVerificationCode() {
Random random = new Random();
int code = 100000 + random.nextInt(900000);
return String.valueOf(code);
}
private void startCountDown() {
isCounting = true;
btnSendCode.setEnabled(false);
@ -95,6 +134,8 @@ public class RegisterActivity extends AppCompatActivity {
isCounting = false;
btnSendCode.setEnabled(true);
btnSendCode.setText("发送验证码");
// 验证码过期
verificationCode = "";
}
}.start();
}
@ -104,41 +145,109 @@ public class RegisterActivity extends AppCompatActivity {
String code = etVerificationCode.getText().toString().trim();
String password = etPassword.getText().toString().trim();
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
if (!validateRegisterInput(phone, code, password)) {
return;
}
if (code.isEmpty()) {
etVerificationCode.setError("请输入验证码");
// 验证验证码
if (!code.equals(verificationCode)) {
etVerificationCode.setError("验证码错误");
etVerificationCode.requestFocus();
Toast.makeText(this, "请输入正确的验证码", Toast.LENGTH_SHORT).show();
return;
}
if (password.isEmpty()) {
etPassword.setError("请输入密码");
// 检查验证码是否过期
if (verificationCode.isEmpty()) {
etVerificationCode.setError("验证码已过期,请重新获取");
etVerificationCode.requestFocus();
Toast.makeText(this, "验证码已过期,请重新获取", Toast.LENGTH_SHORT).show();
return;
}
// 注册用户
boolean success = userManager.registerUser(phone, password);
if (success) {
performRegisterSuccess(phone, password);
} else {
Toast.makeText(this, "注册失败,该手机号已注册", Toast.LENGTH_SHORT).show();
etPhone.setError("该手机号已注册");
etPhone.requestFocus();
}
}
private boolean validateRegisterInput(String phone, String code, String password) {
// 验证手机号
if (phone.isEmpty()) {
etPhone.setError("请输入手机号");
etPhone.requestFocus();
return false;
}
if (phone.length() != 11) {
etPhone.setError("手机号格式不正确");
return;
etPhone.requestFocus();
return false;
}
if (!phone.startsWith("1")) {
etPhone.setError("手机号格式不正确");
etPhone.requestFocus();
return false;
}
// 验证验证码
if (code.isEmpty()) {
etVerificationCode.setError("请输入验证码");
etVerificationCode.requestFocus();
return false;
}
if (code.length() != 6) {
etVerificationCode.setError("验证码格式不正确");
etVerificationCode.requestFocus();
return false;
}
// 验证密码
if (password.isEmpty()) {
etPassword.setError("请输入密码");
etPassword.requestFocus();
return false;
}
if (password.length() < 6) {
etPassword.setError("密码至少6位");
return;
etPassword.requestFocus();
return false;
}
if (password.length() > 20) {
etPassword.setError("密码最多20位");
etPassword.requestFocus();
return false;
}
// 模拟注册成功
performRegister();
return true;
}
private void performRegister() {
private void performRegisterSuccess(String phone, String password) {
Toast.makeText(this, "注册成功!", Toast.LENGTH_SHORT).show();
// 注册成功后跳转到登录页面
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
startActivity(intent);
finish();
// 自动登录
User user = userManager.loginUser(phone, password);
if (user != null) {
// 跳转到主页面
Intent intent = new Intent(RegisterActivity.this, MainActivity.class);
startActivity(intent);
finish();
} else {
// 如果自动登录失败,跳转到登录页面
Toast.makeText(this, "注册成功,请登录", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
}
@Override

@ -0,0 +1,357 @@
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 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();
});
}
private void initData() {
sharedPreferences = getSharedPreferences("search_prefs", MODE_PRIVATE);
// 初始化商品数据
allProducts = new ArrayList<>();
allProducts.add(new Product("1", "Java编程思想", "计算机专业教材", "学习资料", 45.0, ""));
allProducts.add(new Product("2", "高等数学教材", "大学数学课本", "学习资料", 30.0, ""));
allProducts.add(new Product("3", "笔记本电脑", "二手联想笔记本", "数码产品", 1200.0, ""));
allProducts.add(new Product("4", "台灯", "护眼学习台灯", "生活用品", 25.0, ""));
allProducts.add(new Product("5", "Python入门", "编程学习书籍", "学习资料", 35.0, ""));
allProducts.add(new Product("6", "机械键盘", "客制化机械键盘", "数码产品", 150.0, ""));
allProducts.add(new Product("7", "电钢琴", "雅马哈电钢琴", "乐器", 800.0, ""));
allProducts.add(new Product("8", "笔记本", "八成新游戏本", "数码产品", 2000.0, ""));
allProducts.add(new Product("9", "电动车", "二手电动车", "交通工具", 600.0, ""));
allProducts.add(new Product("10", "厚外套", "冬季保暖外套", "服装", 80.0, ""));
// 初始化推荐关键词
recommendKeywords = Arrays.asList(
"Java编程教材", "Python入门书籍", "高等数学课本", "英语四级真题", "考研政治资料", "计算机专业课", "电路分析教程", "机械制图教材", "经济学原理", "心理学导论", "设计素描本", "专业课程笔记","二手笔记本电脑", "机械键盘", "无线鼠标", "蓝牙耳机", "平板电脑", "智能手机", "充电宝", "U盘硬盘", "显示器", "路由器", "相机镜头", "游戏手柄","台灯", "插排", "收纳箱", "穿衣镜",
"瑜伽垫", "体重秤", "电风扇", "暖手宝", "床上桌", "衣柜", "鞋架", "晾衣架","羽毛球拍", "篮球足球", "滑板轮滑", "吉他乐器",
"画笔画具", "围棋象棋", "游泳装备", "健身器材", "登山背包", "帐篷睡袋", "摄影三脚架", "书法字帖"
);
}
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;
}
private void performSearch() {
String query = searchEditText.getText().toString().trim();
if (!TextUtils.isEmpty(query)) {
saveSearchHistory(query);
Intent intent = new Intent(this, SearchResultsActivity.class);
intent.putExtra("search_query", query);
startActivity(intent);
}
}
private void clearSearchHistory() {
sharedPreferences.edit().remove(SEARCH_HISTORY).apply();
loadSearchHistory();
}
@Override
protected void onResume() {
super.onResume();
loadSearchHistory();
}
}

@ -0,0 +1,115 @@
package com.startsmake.llrisetabbardemo.activity;
import android.os.Bundle;
import android.view.View;
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.SearchAdapter;
import com.startsmake.llrisetabbardemo.model.Product;
import java.util.ArrayList;
import java.util.List;
public class SearchResultsActivity extends AppCompatActivity {
private RecyclerView resultsRecyclerView;
private TextView searchQueryText;
private SearchAdapter searchAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_results);
initViews();
loadSearchResults();
}
private void initViews() {
resultsRecyclerView = findViewById(R.id.results_recycler_view);
searchQueryText = findViewById(R.id.search_query_text);
String query = getIntent().getStringExtra("search_query");
searchQueryText.setText("搜索结果: " + query);
searchAdapter = new SearchAdapter(new ArrayList<>());
resultsRecyclerView.setLayoutManager(new LinearLayoutManager(this));
resultsRecyclerView.setAdapter(searchAdapter);
// 设置返回按钮 - 修复Lambda表达式参数类型
findViewById(R.id.back_button).setOnClickListener((View v) -> {
// 确保数据保存后再返回
finish();
});
}
// 在 loadSearchResults() 方法中添加对图片搜索的支持
private void loadSearchResults() {
String searchType = getIntent().getStringExtra("search_type");
String query = getIntent().getStringExtra("search_query");
if ("image".equals(searchType)) {
// 图片搜索结果
List<Product> similarProducts = (List<Product>) getIntent().getSerializableExtra("similar_products");
if (similarProducts != null && !similarProducts.isEmpty()) {
searchQueryText.setText("图片搜索结果");
searchAdapter.updateData(similarProducts);
findViewById(R.id.no_results_text).setVisibility(View.GONE);
resultsRecyclerView.setVisibility(View.VISIBLE);
} else {
searchQueryText.setText("图片搜索结果");
findViewById(R.id.no_results_text).setVisibility(View.VISIBLE);
resultsRecyclerView.setVisibility(View.GONE);
}
} else {
// 文本搜索结果(原有逻辑)
if (query != null) {
searchQueryText.setText("搜索结果: " + query);
List<Product> searchResults = searchProducts(query);
if (searchResults.isEmpty()) {
findViewById(R.id.no_results_text).setVisibility(View.VISIBLE);
resultsRecyclerView.setVisibility(View.GONE);
} else {
findViewById(R.id.no_results_text).setVisibility(View.GONE);
resultsRecyclerView.setVisibility(View.VISIBLE);
searchAdapter.updateData(searchResults);
}
} else {
// 处理没有查询参数的情况
searchQueryText.setText("搜索结果");
findViewById(R.id.no_results_text).setVisibility(View.VISIBLE);
resultsRecyclerView.setVisibility(View.GONE);
}
}
}
private List<Product> searchProducts(String keyword) {
List<Product> results = new ArrayList<>();
// 这里使用模拟数据,实际应该从数据库或网络加载
List<Product> allProducts = getMockProducts();
for (Product product : allProducts) {
if (product.getName().toLowerCase().contains(keyword.toLowerCase()) ||
product.getDescription().toLowerCase().contains(keyword.toLowerCase()) ||
product.getCategory().toLowerCase().contains(keyword.toLowerCase())) {
results.add(product);
}
}
return results;
}
private List<Product> getMockProducts() {
List<Product> products = new ArrayList<>();
products.add(new Product("1", "Java编程思想", "计算机专业教材", "学习资料", 45.0, ""));
products.add(new Product("2", "高等数学教材", "大学数学课本", "学习资料", 30.0, ""));
products.add(new Product("3", "笔记本电脑", "二手联想笔记本", "数码产品", 1200.0, ""));
products.add(new Product("4", "台灯", "护眼学习台灯", "生活用品", 25.0, ""));
products.add(new Product("5", "Python入门", "编程学习书籍", "学习资料", 35.0, ""));
return products;
}
}

@ -0,0 +1,84 @@
package com.startsmake.llrisetabbardemo.adapter;
import android.content.Context;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.startsmake.llrisetabbardemo.R;
import java.util.List;
public class ImageAdapter extends BaseAdapter {
private Context context;
private List<Uri> imageUris;
private static final int MAX_IMAGES = 9;
public ImageAdapter(Context context, List<Uri> imageUris) {
this.context = context;
this.imageUris = imageUris;
}
@Override
public int getCount() {
return Math.min(imageUris.size() + 1, MAX_IMAGES);
}
@Override
public Object getItem(int position) {
if (position < imageUris.size()) {
return imageUris.get(position);
}
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_image, parent, false);
holder = new ViewHolder();
holder.imageView = convertView.findViewById(R.id.imageView);
holder.deleteButton = convertView.findViewById(R.id.btnDelete);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (position < imageUris.size()) {
// 显示已选择的图片
Uri imageUri = imageUris.get(position);
Glide.with(context)
.load(imageUri)
.placeholder(android.R.drawable.ic_menu_gallery) // 使用系统图标作为占位符
.into(holder.imageView);
holder.deleteButton.setVisibility(View.VISIBLE);
holder.deleteButton.setOnClickListener(v -> {
imageUris.remove(position);
notifyDataSetChanged();
});
} else {
// 显示添加按钮
holder.imageView.setImageResource(android.R.drawable.ic_input_add); // 使用系统图标
holder.deleteButton.setVisibility(View.GONE);
}
return convertView;
}
static class ViewHolder {
ImageView imageView;
ImageView deleteButton;
}
}

@ -0,0 +1,64 @@
package com.startsmake.llrisetabbardemo.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
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;
public SearchAdapter(List<Product> productList) {
this.productList = productList;
}
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.productDescription.setText(product.getDescription());
holder.productCategory.setText(product.getCategory());
holder.productPrice.setText(String.format("¥%.2f", product.getPrice()));
}
@Override
public int getItemCount() {
return productList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView productName;
TextView productDescription;
TextView productCategory;
TextView productPrice;
public ViewHolder(@NonNull View itemView) {
super(itemView);
productName = itemView.findViewById(R.id.product_name);
productDescription = itemView.findViewById(R.id.product_description);
productCategory = itemView.findViewById(R.id.product_category);
productPrice = itemView.findViewById(R.id.product_price);
}
}
}

@ -10,6 +10,7 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -33,6 +34,7 @@ import com.startsmake.llrisetabbardemo.adapter.SearchAdapter;
import com.startsmake.llrisetabbardemo.activity.SearchActivity;
import com.startsmake.llrisetabbardemo.activity.SearchResultsActivity;
import com.startsmake.llrisetabbardemo.model.Product;
import com.startsmake.llrisetabbardemo.model.Item;
import java.io.File;
import java.io.IOException;
@ -50,6 +52,50 @@ import java.util.Locale;
* Description:
*/
public class HomeFragment extends Fragment {
private static final String TAG = "HomeFragment";
public void addNewItem(Item item) {
try {
Log.d(TAG, "开始添加新商品");
if (item == null) {
Log.e(TAG, "尝试添加空商品");
Toast.makeText(requireContext(), "商品信息无效", Toast.LENGTH_SHORT).show();
return;
}
if (productList == null) {
productList = new ArrayList<>();
}
// 将Item转换为Product根据你的数据结构调整
Product newProduct = new Product();
newProduct.setId(String.valueOf(System.currentTimeMillis()));
newProduct.setName(item.getTitle());
newProduct.setDescription(item.getDescription());
newProduct.setCategory(item.getCategory());
newProduct.setPrice(item.getPrice());
newProduct.setImageUrl(""); // 如果没有图片,设为空字符串
// 添加到列表顶部
productList.add(0, newProduct);
// 更新适配器
if (searchAdapter != null) {
searchAdapter.updateData(productList);
}
// 显示商品列表,隐藏空状态
if (homeProductsRecyclerView != null && homeNoProductsText != null) {
homeProductsRecyclerView.setVisibility(View.VISIBLE);
homeNoProductsText.setVisibility(View.GONE);
}
Toast.makeText(requireContext(), "商品发布成功!", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "添加新商品时出错", e);
Toast.makeText(requireContext(), "添加商品失败,请重试", Toast.LENGTH_SHORT).show();
}
}
private EditText searchEditText;
private ImageButton cameraButton;
@ -118,12 +164,25 @@ public class HomeFragment extends Fragment {
setupHomeProductsRecyclerView();
searchEditText.setOnClickListener(v -> {
Intent intent = new Intent(getActivity(), SearchActivity.class);
startActivity(intent);
try {
Log.d(TAG, "搜索框被点击");
// 使用requireActivity()确保Activity不为null
Intent intent = new Intent(requireActivity(), SearchActivity.class);
startActivity(intent);
} catch (Exception e) {
Log.e(TAG, "点击搜索框时出错", e);
Toast.makeText(requireContext(), "打开搜索页面失败,请重试", Toast.LENGTH_SHORT).show();
}
});
homeSearchButton.setOnClickListener(v -> {
performHomeSearch();
try {
Log.d(TAG, "搜索按钮被点击");
performHomeSearch();
} catch (Exception e) {
Log.e(TAG, "执行搜索时出错", e);
Toast.makeText(requireContext(), "搜索功能暂不可用,请稍后再试", Toast.LENGTH_SHORT).show();
}
});
cameraButton.setOnClickListener(v -> {
@ -325,16 +384,32 @@ public class HomeFragment extends Fragment {
// 首页搜索功能
private void performHomeSearch() {
String currentHint = searchEditText.getHint().toString();
String defaultHint = getResources().getString(R.string.search_hint);
if (!currentHint.equals(defaultHint) && randomKeywords.contains(currentHint)) {
Intent intent = new Intent(getActivity(), SearchResultsActivity.class);
intent.putExtra("search_query", currentHint);
startActivity(intent);
} else {
Intent intent = new Intent(getActivity(), SearchActivity.class);
startActivity(intent);
try {
if (searchEditText == null) {
Log.e(TAG, "搜索框对象为null");
Toast.makeText(requireContext(), "搜索组件初始化失败", Toast.LENGTH_SHORT).show();
return;
}
String currentHint = searchEditText.getHint().toString();
String defaultHint = getResources().getString(R.string.search_hint);
Log.d(TAG, "执行首页搜索,当前提示词: " + currentHint);
if (!currentHint.equals(defaultHint) && randomKeywords != null && randomKeywords.contains(currentHint)) {
// 使用requireActivity()确保Activity不为null
Intent intent = new Intent(requireActivity(), SearchResultsActivity.class);
intent.putExtra("search_query", currentHint);
startActivity(intent);
Log.d(TAG, "跳转到搜索结果页面,查询: " + currentHint);
} else {
// 使用requireActivity()确保Activity不为null
Intent intent = new Intent(requireActivity(), SearchActivity.class);
startActivity(intent);
Log.d(TAG, "跳转到搜索页面");
}
} catch (Exception e) {
Log.e(TAG, "执行首页搜索时出错", e);
Toast.makeText(requireContext(), "搜索功能暂不可用,请稍后再试", Toast.LENGTH_SHORT).show();
}
}

@ -0,0 +1,89 @@
package com.startsmake.llrisetabbardemo.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.bumptech.glide.Glide;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.model.Item;
public class ItemDetailFragment extends Fragment {
private static final String ARG_ITEM = "item";
private Item item;
public static ItemDetailFragment newInstance(Item item) {
ItemDetailFragment fragment = new ItemDetailFragment();
Bundle args = new Bundle();
args.putSerializable(ARG_ITEM, item);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
item = (Item) getArguments().getSerializable(ARG_ITEM);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_item_detail, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (item == null) {
Toast.makeText(getContext(), "商品信息加载失败", Toast.LENGTH_SHORT).show();
return;
}
// 初始化视图
ImageView ivItemImage = view.findViewById(R.id.ivItemImage);
TextView tvTitle = view.findViewById(R.id.tvTitle);
TextView tvPrice = view.findViewById(R.id.tvPrice);
TextView tvDescription = view.findViewById(R.id.tvDescription);
TextView tvCategory = view.findViewById(R.id.tvCategory);
TextView tvLocation = view.findViewById(R.id.tvLocation);
TextView tvContact = view.findViewById(R.id.tvContact);
TextView tvPublishTime = view.findViewById(R.id.tvPublishTime);
// 设置商品信息
tvTitle.setText(item.getTitle());
tvPrice.setText(String.format("¥%.2f", item.getPrice()));
tvDescription.setText(item.getDescription());
tvCategory.setText("分类:" + item.getCategory());
tvLocation.setText("位置:" + item.getLocation());
tvContact.setText("联系方式:" + item.getContact());
// 设置发布时间
String time = android.text.format.DateFormat.format("yyyy-MM-dd HH:mm", item.getPublishTime()).toString();
tvPublishTime.setText("发布时间:" + time);
// 加载图片(这里使用第一张图片作为主图)
if (item.getImageUrls() != null && !item.getImageUrls().isEmpty()) {
// 实际项目中这里应该加载网络图片,这里用占位符
ivItemImage.setImageResource(R.mipmap.ic_launcher);
}
// 联系卖家按钮
view.findViewById(R.id.btnContact).setOnClickListener(v -> {
Toast.makeText(getContext(), "联系卖家:" + item.getContact(), Toast.LENGTH_SHORT).show();
});
}
}

@ -1,26 +1,195 @@
package com.startsmake.llrisetabbardemo.fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
// 改为 AndroidX
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.activity.LoginActivity;
import com.startsmake.llrisetabbardemo.manager.UserManager;
/**
* User:Shine
* Date:2015-10-20
* Description:
*/
public class PersonFragment extends Fragment {
private View mLogoutLayout;
private TextView tvUsername, tvUserDesc, tvCreditScore, tvMemberLevel;
private TextView tvWantCount, tvSellingCount, tvSoldCount, tvSavedMoney;
private UserManager userManager;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_person, container, false);
View view = inflater.inflate(R.layout.fragment_person, container, false);
userManager = UserManager.getInstance(requireContext());
initView(view);
setListeners();
updateUI();
return view;
}
private void initView(View view) {
mLogoutLayout = view.findViewById(R.id.ll_logout);
tvUsername = view.findViewById(R.id.tv_username);
tvUserDesc = view.findViewById(R.id.tv_user_desc);
tvCreditScore = view.findViewById(R.id.tv_credit_score);
tvMemberLevel = view.findViewById(R.id.tv_member_level);
tvWantCount = view.findViewById(R.id.tv_want_count);
tvSellingCount = view.findViewById(R.id.tv_selling_count);
tvSoldCount = view.findViewById(R.id.tv_sold_count);
tvSavedMoney = view.findViewById(R.id.tv_saved_money);
}
private void setListeners() {
// 退出登录按钮
if (mLogoutLayout != null) {
mLogoutLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showLogoutDialog();
}
});
}
// 用户名点击登录
if (tvUsername != null) {
tvUsername.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isUserLoggedIn()) {
navigateToLogin();
}
}
});
}
// 用户描述点击登录
if (tvUserDesc != null) {
tvUserDesc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isUserLoggedIn()) {
navigateToLogin();
}
}
});
}
}
private void showLogoutDialog() {
if (!isUserLoggedIn()) {
Toast.makeText(getActivity(), "您还未登录", Toast.LENGTH_SHORT).show();
navigateToLogin();
return;
}
new AlertDialog.Builder(requireContext())
.setTitle("退出登录")
.setMessage("确定要退出登录吗?退出后可以使用原账号重新登录")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
performLogout();
}
})
.setNegativeButton("取消", null)
.show();
}
private void performLogout() {
// 只清除登录状态,不删除用户数据
clearLoginStatusOnly();
// 更新UI
updateUI();
Toast.makeText(getActivity(), "已退出登录", Toast.LENGTH_SHORT).show();
}
private void clearLoginStatusOnly() {
try {
// 方法1: 使用UserManager退出登录只清除登录状态
if (userManager != null) {
userManager.logout();
}
// 方法2: 只清除登录状态,保留用户数据
SharedPreferences spUser = requireActivity().getSharedPreferences("user_info", android.content.Context.MODE_PRIVATE);
SharedPreferences.Editor editorUser = spUser.edit();
// 只清除登录相关状态,不清除用户数据
editorUser.putBoolean("is_logged_in", false);
editorUser.remove("user_token");
// 注意:不要清除 user_phone 和 user_name这样用户重新登录时可以直接显示
editorUser.apply();
} catch (Exception e) {
Toast.makeText(getActivity(), "退出登录失败", Toast.LENGTH_SHORT).show();
}
}
private void updateUI() {
if (isUserLoggedIn()) {
// 用户已登录的状态
SharedPreferences sp = requireActivity().getSharedPreferences("user_info", android.content.Context.MODE_PRIVATE);
String username = sp.getString("user_name", "用户");
if (tvUsername != null) tvUsername.setText(username);
if (tvUserDesc != null) tvUserDesc.setText("省钱达人,精明购物");
if (tvCreditScore != null) tvCreditScore.setVisibility(View.VISIBLE);
if (tvMemberLevel != null) tvMemberLevel.setVisibility(View.VISIBLE);
if (tvWantCount != null) tvWantCount.setText("5");
if (tvSellingCount != null) tvSellingCount.setText("3");
if (tvSoldCount != null) tvSoldCount.setText("12");
if (tvSavedMoney != null) tvSavedMoney.setText("¥256");
} else {
// 用户未登录的状态
if (tvUsername != null) tvUsername.setText("点击登录");
if (tvUserDesc != null) tvUserDesc.setText("登录查看个人数据");
if (tvCreditScore != null) tvCreditScore.setVisibility(View.GONE);
if (tvMemberLevel != null) tvMemberLevel.setVisibility(View.GONE);
if (tvWantCount != null) tvWantCount.setText("0");
if (tvSellingCount != null) tvSellingCount.setText("0");
if (tvSoldCount != null) tvSoldCount.setText("0");
if (tvSavedMoney != null) tvSavedMoney.setText("¥0");
}
}
private boolean isUserLoggedIn() {
SharedPreferences sp = requireActivity().getSharedPreferences("user_info", android.content.Context.MODE_PRIVATE);
return sp.getBoolean("is_logged_in", false);
}
private void navigateToLogin() {
try {
Intent intent = new Intent(getActivity(), LoginActivity.class);
startActivity(intent);
if (getActivity() != null) {
getActivity().overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
} catch (Exception e) {
Toast.makeText(getActivity(), "跳转失败,请重试", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onResume() {
super.onResume();
updateUI();
}
}

@ -22,7 +22,7 @@ import com.startsmake.llrisetabbardemo.R;
import com.startsmake.llrisetabbardemo.activity.MainActivity;
import com.startsmake.llrisetabbardemo.adapter.ImageAdapter;
import model.Item;
import com.startsmake.llrisetabbardemo.model.Item;
import java.util.ArrayList;
import java.util.List;

@ -0,0 +1,188 @@
package com.startsmake.llrisetabbardemo.manager;
import android.content.SharedPreferences;
import android.content.Context;
import com.startsmake.llrisetabbardemo.model.User;
import com.google.gson.Gson;
import java.util.HashSet;
import java.util.Set;
public class UserManager {
private static final String PREF_NAME = "user_data";
private static final String KEY_USERS = "registered_users";
private static final String KEY_CURRENT_USER = "current_user";
private static UserManager instance;
private SharedPreferences preferences;
private Gson gson;
private UserManager(Context context) {
preferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
gson = new Gson();
}
public static synchronized UserManager getInstance(Context context) {
if (instance == null) {
instance = new UserManager(context);
}
return instance;
}
/**
*
*/
public boolean isLoggedIn() {
return preferences.getBoolean("is_logged_in", false);
}
/**
*
*/
public boolean isPhoneRegistered(String phone) {
Set<String> usersSet = preferences.getStringSet(KEY_USERS, new HashSet<>());
for (String userJson : usersSet) {
User user = gson.fromJson(userJson, User.class);
if (user.getPhone().equals(phone)) {
return true;
}
}
return false;
}
/**
*
*/
public boolean registerUser(String phone, String password) {
// 检查手机号是否已注册
if (isPhoneRegistered(phone)) {
return false;
}
// 创建新用户
User newUser = new User(phone, password);
String userJson = gson.toJson(newUser);
Set<String> usersSet = preferences.getStringSet(KEY_USERS, new HashSet<>());
Set<String> newUsersSet = new HashSet<>(usersSet);
newUsersSet.add(userJson);
return preferences.edit().putStringSet(KEY_USERS, newUsersSet).commit();
}
/**
*
*/
public User loginUser(String phone, String password) {
Set<String> usersSet = preferences.getStringSet(KEY_USERS, new HashSet<>());
for (String userJson : usersSet) {
User user = gson.fromJson(userJson, User.class);
if (user.getPhone().equals(phone) && user.getPassword().equals(password)) {
// 保存当前用户信息
saveCurrentUser(user);
return user;
}
}
return null;
}
/**
*
*/
public boolean resetPassword(String phone, String newPassword) {
Set<String> usersSet = preferences.getStringSet(KEY_USERS, new HashSet<>());
Set<String> newUsersSet = new HashSet<>();
boolean found = false;
for (String userJson : usersSet) {
User user = gson.fromJson(userJson, User.class);
if (user.getPhone().equals(phone)) {
// 更新密码
user.setPassword(newPassword);
found = true;
}
newUsersSet.add(gson.toJson(user));
}
if (found) {
boolean success = preferences.edit().putStringSet(KEY_USERS, newUsersSet).commit();
if (success) {
// 如果重置的是当前登录用户,更新当前用户信息
User currentUser = getCurrentUser();
if (currentUser != null && currentUser.getPhone().equals(phone)) {
currentUser.setPassword(newPassword);
saveCurrentUser(currentUser);
}
}
return success;
}
return false;
}
/**
*
*/
private void saveCurrentUser(User user) {
String userJson = gson.toJson(user);
preferences.edit()
.putString(KEY_CURRENT_USER, userJson)
.putBoolean("is_logged_in", true)
.putString("user_phone", user.getPhone())
.putString("user_name", user.getUsername())
.apply();
}
/**
*
*/
public User getCurrentUser() {
String userJson = preferences.getString(KEY_CURRENT_USER, null);
if (userJson != null) {
return gson.fromJson(userJson, User.class);
}
return null;
}
/**
*
*/
public void logout() {
preferences.edit()
.remove(KEY_CURRENT_USER)
.putBoolean("is_logged_in", false)
.remove("user_phone")
.remove("user_name")
.apply();
}
/**
*
*/
public void saveUserLogin(String phone, String password) {
User user = loginUser(phone, password);
if (user != null) {
saveCurrentUser(user);
}
}
/**
*
*/
public boolean validateLogin(String phone, String password) {
return loginUser(phone, password) != null;
}
/**
*
*/
public boolean isUserExists(String phone) {
return isPhoneRegistered(phone);
}
/**
*
*/
public boolean updatePassword(String phone, String newPassword) {
return resetPassword(phone, newPassword);
}
}

@ -1,4 +1,4 @@
package model;
package com.startsmake.llrisetabbardemo.model;
import java.io.Serializable;
import java.util.ArrayList;

@ -0,0 +1,69 @@
package com.startsmake.llrisetabbardemo.model;
import java.io.Serializable;
import java.util.Objects;
public class Product implements Serializable {
private String id;
private String name;
private String description;
private String category;
private double price;
private String imageUrl;
public Product() {
}
public Product(String id, String name, String description, String category, double price, String imageUrl) {
this.id = id;
this.name = name;
this.description = description;
this.category = category;
this.price = price;
this.imageUrl = imageUrl;
}
// Getter 和 Setter 方法
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
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 String getImageUrl() { return imageUrl; }
public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
// 添加 equals 和 hashCode 方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
return Objects.equals(id, product.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
// 可选:添加 toString 方法便于调试
@Override
public String toString() {
return "Product{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", category='" + category + '\'' +
", price=" + price +
'}';
}
}

@ -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; }
}

@ -0,0 +1,171 @@
package manager;
import com.startsmake.llrisetabbardemo.model.Item;
import java.util.ArrayList;
import java.util.List;
/**
* - 使
*
*/
public class DataManager {
// 单例实例
private static DataManager instance;
// 商品列表
private List<Item> itemList;
// 私有构造函数,防止外部创建实例
private DataManager() {
itemList = new ArrayList<>();
// 初始化时添加一些示例数据
initSampleData();
}
/**
*
* @return DataManager
*/
public static DataManager getInstance() {
if (instance == null) {
instance = new DataManager();
}
return instance;
}
/**
*
*/
private void initSampleData() {
// 示例商品1 - 数码产品
Item item1 = new Item();
item1.setId("item_001");
item1.setTitle("全新iPhone 13 Pro");
item1.setDescription("全新未拆封256GB远峰蓝色国行正品带发票");
item1.setPrice(6999.00);
item1.setCategory("数码产品");
item1.setLocation("北京");
item1.setContact("138****1234");
item1.setPublishTime(System.currentTimeMillis() - 2 * 60 * 60 * 1000); // 2小时前发布
itemList.add(item1);
// 示例商品2 - 数码产品
Item item2 = new Item();
item2.setId("item_002");
item2.setTitle("二手笔记本电脑");
item2.setDescription("联想小新i5处理器8GB内存256GB固态硬盘95成新");
item2.setPrice(2500.00);
item2.setCategory("数码产品");
item2.setLocation("上海");
item2.setContact("微信abc123");
item2.setPublishTime(System.currentTimeMillis() - 5 * 60 * 60 * 1000); // 5小时前发布
itemList.add(item2);
// 示例商品3 - 服装鞋帽
Item item3 = new Item();
item3.setId("item_003");
item3.setTitle("品牌运动鞋");
item3.setDescription("耐克运动鞋42码只穿过几次几乎全新原盒在");
item3.setPrice(299.00);
item3.setCategory("服装鞋帽");
item3.setLocation("广州");
item3.setContact("159****5678");
item3.setPublishTime(System.currentTimeMillis() - 24 * 60 * 60 * 1000); // 1天前发布
itemList.add(item3);
// 示例商品4 - 图书文具
Item item4 = new Item();
item4.setId("item_004");
item4.setTitle("Java编程思想");
item4.setDescription("Java编程思想第5版几乎全新无笔记无划痕");
item4.setPrice(45.00);
item4.setCategory("图书文具");
item4.setLocation("杭州");
item4.setContactQQ("123456789");
item4.setPublishTime(System.currentTimeMillis() - 3 * 24 * 60 * 60 * 1000); // 3天前发布
itemList.add(item4);
}
/**
*
* @return
*/
public List<Item> getAllItems() {
return itemList;
}
/**
*
* @param item
*/
public void addItem(Item item) {
// 为新商品生成ID
item.setId("item_" + System.currentTimeMillis());
// 设置发布时间
item.setPublishTime(System.currentTimeMillis());
// 将新商品添加到列表最前面(最新发布的显示在最前面)
itemList.add(0, item);
}
/**
* ID
* @param id ID
* @return null
*/
public Item getItemById(String id) {
for (Item item : itemList) {
if (item.getId().equals(id)) {
return item;
}
}
return null;
}
/**
*
* @param category
* @return
*/
public List<Item> getItemsByCategory(String category) {
List<Item> result = new ArrayList<>();
for (Item item : itemList) {
if (item.getCategory().equals(category)) {
result.add(item);
}
}
return result;
}
/**
*
* @param keyword
* @return
*/
public List<Item> searchItems(String keyword) {
List<Item> result = new ArrayList<>();
for (Item item : itemList) {
if (item.getTitle().toLowerCase().contains(keyword.toLowerCase()) ||
item.getDescription().toLowerCase().contains(keyword.toLowerCase())) {
result.add(item);
}
}
return result;
}
/**
*
* @return
*/
public int getItemCount() {
return itemList.size();
}
/**
*
*/
public void clearAll() {
itemList.clear();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

@ -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,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,176 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/white">
<!-- 搜索栏 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFDD59"
android:orientation="horizontal"
android:padding="12dp">
<!-- 返回按钮 -->
<ImageButton
android:id="@+id/back_button"
android:layout_width="24dp"
android:layout_height="50dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_back"
android:scaleType="centerInside"
android:padding="6dp"
android:contentDescription="返回" />
<!-- 搜索框 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:alpha="0.8"
android:background="@drawable/rounded_background1"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp">
<!-- 摄像头按钮 -->
<ImageButton
android:id="@+id/camera_button"
android:layout_width="23dp"
android:layout_height="24dp"
android:layout_marginStart="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:padding="0.5dp"
android:scaleType="centerInside"
android:src="@android:drawable/ic_menu_camera"
android:contentDescription="拍照搜索" />
<EditText
android:id="@+id/search_edit_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:background="@null"
android:hint="搜索教材、数码、生活用品..."
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:singleLine="true"
android:textColor="#333333"
android:textColorHint="#999999"
android:textSize="14sp"
android:cursorVisible="true"
android:focusable="true"
android:focusableInTouchMode="true"/>
<!-- 搜索按钮 - 放在输入框外面右侧 -->
<TextView
android:id="@+id/search_button"
android:layout_width="50dp"
android:layout_height="27dp"
android:layout_marginStart="2dp"
android:layout_marginTop="0dp"
android:gravity="center"
android:text="搜索"
android:textColor="#333333"
android:textSize="14sp"
android:textStyle="bold"
android:clickable="true"
android:focusable="true" />
</LinearLayout>
</LinearLayout>
<!-- 内容区域 -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 历史搜索 -->
<TextView
android:id="@+id/history_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="历史搜索"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="12dp" />
<!-- 历史记录容器 - 使用 FlexboxLayout -->
<com.google.android.flexbox.FlexboxLayout
android:id="@+id/history_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexWrap="wrap"
app:alignItems="flex_start"
app:justifyContent="flex_start" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<!-- 展开/收起按钮 -->
<TextView
android:id="@+id/expand_history_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="展开更多"
android:textColor="#666666"
android:textSize="12sp"
android:padding="8dp"
android:visibility="gone" />
<!-- 清空历史 -->
<TextView
android:id="@+id/clear_history_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清空历史记录"
android:textColor="#666666"
android:textSize="12sp"
android:padding="8dp" />
</LinearLayout>
<!-- 猜你可能在找 -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="猜你可能在找"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginTop="24dp"
android:layout_marginBottom="12dp" />
<!-- 推荐容器 - 使用 FlexboxLayout -->
<com.google.android.flexbox.FlexboxLayout
android:id="@+id/recommend_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexWrap="wrap"
app:alignItems="flex_start"
app:justifyContent="flex_start" />
</LinearLayout>
</ScrollView>
</LinearLayout>

@ -0,0 +1,59 @@
<?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="@android:color/white">
<!-- 搜索栏 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFDD59"
android:orientation="horizontal"
android:padding="16dp">
<ImageButton
android:id="@+id/back_button"
android:layout_width="20dp"
android:layout_height="28dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_back"
android:scaleType="centerInside"
android:padding="6dp"
android:contentDescription="返回" />
<TextView
android:id="@+id/search_query_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="16dp"
android:gravity="center_vertical"
android:text="搜索结果"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 搜索结果 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/results_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp" />
<!-- 无结果提示 -->
<TextView
android:id="@+id/no_results_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="120dp"
android:text="没有找到相关商品"
android:textColor="#666666"
android:textSize="16sp"
android:visibility="gone" />
</LinearLayout>

@ -65,7 +65,7 @@
android:src="@android:drawable/ic_menu_camera"
android:contentDescription="拍照搜索" />
<!-- 搜索按钮 -->
<!-- 搜索按钮 - 放在输入框外面右侧 -->
<TextView
android:id="@+id/home_search_button"
android:layout_width="50dp"
@ -182,33 +182,51 @@
</LinearLayout>
</HorizontalScrollView>
<!-- 商品展示区域 -->
<!-- 在导航标签区域后面添加商品展示区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical">
<!-- 商品列表 -->
<!-- 商品展示区域 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_products_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<!-- 暂无商品提示 -->
<TextView
android:id="@+id/home_no_products_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="暂无商品"
android:textColor="#666666"
android:textSize="16sp"
android:visibility="gone" />
</LinearLayout>
<!-- 搜索结果RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_products_recycler_view"
android:id="@+id/search_results_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<!-- 暂无商品提示 -->
<!-- 无结果提示 -->
<TextView
android:id="@+id/home_no_products_text"
android:id="@+id/no_results_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="暂无商品"
android:textColor="#666666"
android:text="没有找到相关商品"
android:textSize="16sp"
android:textColor="#666666"
android:visibility="gone" />
</LinearLayout>
<!-- 首页默认内容区域 -->
<LinearLayout
android:id="@+id/default_content"
@ -218,8 +236,9 @@
android:gravity="center"
android:padding="16dp">
<!-- 这里可以放默认的首页内容 -->
</LinearLayout>
</LinearLayout>
</FrameLayout>

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:background="#f5f5f5">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 商品图片 -->
<ImageView
android:id="@+id/ivItemImage"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:background="@drawable/bg_image_border"
android:src="@mipmap/ic_launcher" />
<!-- 商品基本信息 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@android:color/white"
android:padding="16dp"
android:layout_marginTop="8dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="商品标题"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvPrice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="¥0.00"
android:textColor="#ff4444"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginTop="8dp" />
</LinearLayout>
<!-- 商品详情 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@android:color/white"
android:padding="16dp"
android:layout_marginTop="8dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="商品详情"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="商品描述"
android:textSize="14sp"
android:layout_marginTop="8dp"
android:lineSpacingExtra="4dp" />
</LinearLayout>
<!-- 商品信息 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@android:color/white"
android:padding="16dp"
android:layout_marginTop="8dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="商品信息"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvCategory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="分类:"
android:textSize="14sp"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvLocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="位置:"
android:textSize="14sp"
android:layout_marginTop="4dp" />
<TextView
android:id="@+id/tvContact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="联系方式:"
android:textSize="14sp"
android:layout_marginTop="4dp" />
<TextView
android:id="@+id/tvPublishTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发布时间:"
android:textSize="14sp"
android:layout_marginTop="4dp" />
</LinearLayout>
<!-- 联系卖家按钮 -->
<Button
android:id="@+id/btnContact"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="联系卖家"
android:textSize="16sp"
android:textStyle="bold"
android:background="@drawable/bg_button_primary"
android:textColor="@android:color/white"
android:layout_marginTop="16dp" />
</LinearLayout>
</ScrollView>

@ -37,6 +37,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击登录"
android:clickable="true"
android:focusable="true"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />

@ -0,0 +1,55 @@
<?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="16dp"
android:background="@android:color/white"
android:layout_marginBottom="8dp"
android:elevation="2dp">
<TextView
android:id="@+id/product_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="商品名称"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/product_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="商品描述"
android:textColor="#666666"
android:textSize="14sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/product_category"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="类别"
android:textColor="#999999"
android:textSize="12sp" />
<TextView
android:id="@+id/product_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="¥0.00"
android:textColor="#ff6b35"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>

@ -1,3 +1,4 @@
<resources>
<string name="app_name">LLRiseTabBarDemo</string>
<string name="search_hint">Searchforproducts</string>
</resources>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="." />
<cache-path name="cache_files" path="." />
</paths>
Loading…
Cancel
Save