目录
一、测试环境说明
电脑环境
Windows 11
编写语言
JAVA
开发软件
Android Studio (2020)
开发软件只要大于等于测试版本即可(近几年官网直接下载也可以),若是版本低于测试版本请自行测试。项目需要根据你的软件自行适配
二、项目简介
该项目简介来自网络,具体内容需要自行测试
本项目是一个基于Android平台的图书商城应用,采用Java语言开发,使用SQLite作为本地数据库存储方案。
系统实现了完整的电子商务功能流程,包括用户注册登录、图书分类浏览、商品详情查看、购物车管理、订单生成与查询等功能模块。
应用采用MVC架构设计,通过RecyclerView实现高性能列表展示,并利用Navigation组件管理页面导航。在界面设计上,遵循Material Design规范,使用CardView、FloatingActionButton等现代化UI组件提升用户体验。
系统特别设计了分类导航功能,用户可以按计算机、小说、科学、历史等分类浏览图书,并通过购物车批量管理选购商品。
订单模块完整记录了购买历史,支持订单详情查看和删除操作。整个应用充分考虑了移动端特性,实现了流畅的用户交互和稳定的数据存储,为读者提供了便捷的图书购买体验。
该项目由编程乐学团队介入,优化布局完善功能
三、项目演示
网络资源模板--基于Android studio 图书商城App
四、部设计详情(部分)
登录注册页
1. 页面结构
该页面采用单Activity结构,核心布局由ConstraintLayout构成,内部嵌套MaterialCardView作为登录卡片容器。
卡片内采用垂直LinearLayout组织UI元素,包含标题、用户名输入框、密码输入框、登录按钮和注册切换链接。整体采用居中卡片设计,背景可自定义,输入框使用Material Design的TextInputLayout实现浮动标签效果,按钮采用MaterialButton保持风格统一。
布局层次清晰,间距合理,符合Material Design设计规范。
2. 使用技术
页面采用AndroidX组件库,使用Material Design组件实现现代化UI,包括MaterialCardView、TextInputLayout和MaterialButton。
数据持久化通过SharedPreferences实现用户名记忆功能。采用MVC模式组织代码,将认证逻辑封装在MyAuth类中。
使用Intent实现页面跳转,并配合清理返回栈。输入验证包括非空检查和错误焦点管理,通过Toast提供用户反馈。
3. 页面功能详解
该页面提供双模式切换功能,可在登录和注册状态间无缝转换。登录模式下验证用户凭证,注册模式检查用户名唯一性。
自动记忆上次成功登录的用户名提升用户体验。输入验证确保必填字段完整性,错误时自动聚焦对应字段。
认证成功后会清除导航栈直接进入主界面,防止用户回退到登录页。
整体交互流畅,错误处理完善,遵循Material Motion动效原则,视觉层次分明,色彩使用符合Material Design调色板规范。
package com.example.shop.controllers;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.shop.MyAuth;
import com.example.shop.R;
/**
* 登录/注册Activity,处理用户认证流程
* 功能:
* 1. 登录/注册模式切换
* 2. 账号密码非空验证
* 3. 自动填充已保存的用户名
* 4. 成功登录后跳转主界面
*/
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
// UI组件
private TextView loginTitle;
private Button authButton;
private TextView toggleAuthMode;
private EditText usernameInput;
private EditText passwordInput;
// 当前模式标志,true为登录模式,false为注册模式
private boolean isLoginMode = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 隐藏ActionBar
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
setContentView(R.layout.activity_login);
// 初始化UI组件
initViews();
// 检查是否有保存的用户名,有则自动填充
checkSavedUsername();
}
/**
* 初始化所有视图组件
*/
private void initViews() {
loginTitle = findViewById(R.id.loginTitle);
authButton = findViewById(R.id.loginButton);
toggleAuthMode = findViewById(R.id.toggleLoginReg);
usernameInput = findViewById(R.id.editTextTextEmailAddress);
passwordInput = findViewById(R.id.editTextTextPassword);
// 设置点击监听器
toggleAuthMode.setOnClickListener(this);
authButton.setOnClickListener(this);
}
/**
* 检查SharedPreferences中是否有保存的用户名
*/
private void checkSavedUsername() {
SharedPreferences sp = getSharedPreferences("preferences", MODE_PRIVATE);
String savedUsername = sp.getString("username", "");
if (!savedUsername.isEmpty()) {
usernameInput.setText(savedUsername);
// 自动聚焦到密码输入框
passwordInput.requestFocus();
}
}
/**
* 跳转到主Activity并清除返回栈
*/
private void navigateToMain() {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish(); // 结束当前Activity
}
/**
* 切换登录/注册模式
*/
private void toggleAuthMode() {
isLoginMode = !isLoginMode;
loginTitle.setText(isLoginMode ? "登录" : "注册");
authButton.setText(isLoginMode ? "登录" : "注册");
toggleAuthMode.setText(isLoginMode ? "立即注册" : "立即登录");
// 清空密码输入框
passwordInput.setText("");
}
/**
* 验证输入是否有效
* @return true表示有效,false表示无效
*/
private boolean validateInput() {
String username = usernameInput.getText().toString().trim();
String password = passwordInput.getText().toString().trim();
if (username.isEmpty()) {
showToast("账号不能为空");
usernameInput.requestFocus();
return false;
}
if (password.isEmpty()) {
showToast("密码不能为空");
passwordInput.requestFocus();
return false;
}
return true;
}
/**
* 处理登录逻辑
*/
private void handleLogin() {
if (!validateInput()) {
return;
}
String username = usernameInput.getText().toString().trim();
String password = passwordInput.getText().toString().trim();
MyAuth auth = new MyAuth(this);
MyAuth.AuthResult result = auth.authUser(username, password);
switch (result) {
case SUCCESS:
saveUsername(username);
navigateToMain();
break;
case INVALID_USERNAME_OR_PWD:
showToast("用户名或密码错误");
passwordInput.setText("");
passwordInput.requestFocus();
break;
case TOKEN_TOO_LONG:
showToast("用户名太长");
usernameInput.requestFocus();
break;
case UNKNOWN_ERROR:
showToast("出现未知错误");
break;
}
}
/**
* 处理注册逻辑
*/
private void handleRegistration() {
if (!validateInput()) {
return;
}
String username = usernameInput.getText().toString().trim();
String password = passwordInput.getText().toString().trim();
MyAuth auth = new MyAuth(this);
MyAuth.AuthResult result = auth.addUser(username, password);
switch (result) {
case SUCCESS:
saveUsername(username);
navigateToMain();
break;
case USER_EXISTED:
showToast("用户已存在");
usernameInput.requestFocus();
break;
case TOKEN_TOO_LONG:
showToast("用户名太长");
usernameInput.requestFocus();
break;
case UNKNOWN_ERROR:
showToast("出现未知错误");
break;
}
}
/**
* 保存用户名到SharedPreferences
* @param username 要保存的用户名
*/
private void saveUsername(String username) {
SharedPreferences sp = getSharedPreferences("preferences", MODE_PRIVATE);
sp.edit().putString("username", username).apply();
}
/**
* 显示Toast消息
* @param message 要显示的消息
*/
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.toggleLoginReg:
toggleAuthMode();
break;
case R.id.loginButton:
if (isLoginMode) {
handleLogin();
} else {
handleRegistration();
}
break;
}
}
}
首页
1. 页面结构
该页面采用垂直LinearLayout布局,顶部为横向滚动的分类导航栏(HorizontalScrollView),底部为RecyclerView展示图书列表。
分类导航栏使用CardView包裹,内部动态生成分类标签卡片。RecyclerView采用GridLayoutManager实现网格布局,支持分类标题跨列显示。
页面结构分为上下两部分,上方分类导航可点击切换,下方图书列表支持点击跳转详情。整体布局简洁高效,分类导航与内容区域联动,提供流畅的浏览体验。
2. 使用技术
页面基于AndroidX组件库,使用RecyclerView实现高性能列表展示,配合GridLayoutManager实现网格布局。
采用自定义SpanSizeLookup处理分类标题的跨列显示。数据层通过BookService获取图书信息,使用HashMap按分类组织数据。
导航采用Navigation组件实现Fragment间跳转。交互方面实现了RecyclerView滚动监听与分类导航联动,通过动态修改CardView背景色指示当前分类。整体采用观察者模式处理滚动事件,实现双向导航交互。
3. 页面功能详解
该页面是图书分类浏览界面,顶部导航栏展示所有图书分类,点击可快速定位到对应分类。图书列表按分类分组显示,每个分类标题占据整行,图书以网格形式展示。
滚动列表时导航栏会自动高亮当前分类,反之点击导航栏也会滚动到对应分类。每本图书可点击进入详情页。
页面采用内存优化设计,动态加载分类导航标签,通过位置映射表高效管理分类定位。视觉上通过卡片阴影和颜色对比强化交互反馈,提供直观的分类浏览体验。
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
app:cardCornerRadius="0dp"
app:cardElevation="4dp">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0">
<LinearLayout
android:id="@+id/linear_pager"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:orientation="horizontal"
android:paddingStart="6dp"
android:paddingEnd="6dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
</HorizontalScrollView>
</androidx.cardview.widget.CardView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/book_list"
android:name="com.example.shop.BookFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:layoutManager="LinearLayoutManager"
tools:context=".controllers.BookFragment"
tools:listitem="@layout/book_fragment_item">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
五、项目源码
👇👇👇👇👇快捷方式👇👇👇👇👇