目录
一、项目演示
网络资源模板--基于Android studio 实现的宿舍管理系统
二、项目测试环境
三、项目详情
所有项目页面展示:
登录页
-
界面组件:
- 包含账户输入框(
etAccount
)和密码输入框(etPassword
)。 - 有一个登录按钮(
btnLogin
)和一个注册文本视图(tvRegister
)。
- 包含账户输入框(
-
注册跳转:
- 点击注册文本视图会跳转到注册界面。
-
登录逻辑:
- 用户输入账户和密码后,首先检查输入是否为空。
- 如果账户和密码都不为空,则通过SQLite数据库查询用户信息。
- 如果用户存在,进一步验证密码是否正确。
- 登录成功后,用户ID和用户类型被保存到SharedPreferences中,并跳转到主界面;如果登录失败,则显示相应的错误提示(如"账号不存在"或"密码错误")。
-
数据库操作:
- 使用
MySqliteOpenHelper
类管理SQLite数据库,查询用户数据。
- 使用
-
用户反馈:
- 通过
Toast
提供即时反馈,提示用户输入错误或登录状态。
- 通过
java
package com.example.studentdormitory.ui.activity;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.studentdormitory.R;
import com.example.studentdormitory.bean.User;
import com.example.studentdormitory.util.MySqliteOpenHelper;
import com.example.studentdormitory.util.SPUtils;
public class LoginActivity extends AppCompatActivity {
private Button btnLogin; // 登录按钮
private EditText etAccount; // 账户输入框
private EditText etPassword; // 密码输入框
private MySqliteOpenHelper helper; // SQLite数据库帮助类
private TextView tvRegister; // 注册文本视图
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login); // 设置布局
helper = new MySqliteOpenHelper(this); // 初始化数据库帮助类
etAccount = findViewById(R.id.et_account); // 获取账户输入框
etPassword = findViewById(R.id.et_password); // 获取密码输入框
tvRegister = findViewById(R.id.tv_register); // 获取注册文本视图
btnLogin = findViewById(R.id.btn_login); // 获取登录按钮
// 注册点击事件,跳转到注册界面
tvRegister.setOnClickListener(v -> startActivity(new Intent(LoginActivity.this, RegisterActivity.class)));
// 登录按钮点击事件
btnLogin.setOnClickListener(v -> {
String account = etAccount.getText().toString(); // 获取账户输入
String password = etPassword.getText().toString(); // 获取密码输入
// 检查账户是否为空
// 检查用户名是否为空
if (account.isEmpty()) {
Toast.makeText(LoginActivity.this, "用户名不能为空", Toast.LENGTH_SHORT).show();
}
// 检查密码是否为空
else if (password.isEmpty()) {
Toast.makeText(LoginActivity.this, "密码不能为空", Toast.LENGTH_SHORT).show();
}
// 如果账户和密码都不为空
else {
User mUser = null; // 声明用户对象
SQLiteDatabase db = helper.getWritableDatabase(); // 获取可写数据库
// 查询账户是否存在
Cursor cursor = db.rawQuery("select * from user where account = ?", new String[]{account});
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
// 从数据库中获取用户信息
mUser = new User(cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getString(4), cursor.getString(5), cursor.getString(6), cursor.getString(7), cursor.getInt(8));
}
}
cursor.close(); // 关闭游标
db.close(); // 关闭数据库
// 检查用户是否存在
if (mUser == null) {
Toast.makeText(LoginActivity.this, "账号不存在", Toast.LENGTH_SHORT).show();
}
// 检查密码是否正确
else if (!password.equals(mUser.getPassword())) {
Toast.makeText(LoginActivity.this, "密码错误", Toast.LENGTH_SHORT).show();
}
// 登录成功
else {
SPUtils.put(LoginActivity.this, SPUtils.USER_ID, mUser.getId()); // 保存用户ID
SPUtils.put(LoginActivity.this, SPUtils.USER_TYPE, mUser.getUserType()); // 保存用户类型
startActivity(new Intent(LoginActivity.this, MainActivity.class)); // 跳转到主界面
finish(); // 结束当前活动
}
}
});
}
}
注册页
-
用户信息输入:
- 提供了多个输入框供用户填写,包括账号、昵称、密码、确认密码、手机号和寝室号。
-
头像选择:
- 允许用户点击头像ImageView选择图片,并使用Glide库加载选择的头像。
-
性别选择:
- 用户可以通过RadioGroup选择性别。
-
数据验证:
- 在用户点击注册按钮时,系统会进行多项验证,包括:
- 头像是否已上传。
- 账号、昵称、手机号、寝室号、密码等输入框不能为空。
- 手机号格式是否正确(长度为11)。
- 确认密码是否与密码一致。
- 在用户点击注册按钮时,系统会进行多项验证,包括:
-
用户注册逻辑:
- 查询数据库以检查账号是否已存在。
- 若账号不存在,则插入新用户信息到数据库。
- 注册成功后显示提示信息,并结束当前活动。
- 若账号已存在,则显示相应提示信息。
-
跳转到登录界面:
- 提供一个文本链接,允许用户跳转回登录界面。
java
package com.example.studentdormitory.ui.activity;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.example.studentdormitory.R;
import com.example.studentdormitory.bean.User;
import com.example.studentdormitory.enums.UserTypeEnum;
import com.example.studentdormitory.util.GlideEngine;
import com.example.studentdormitory.util.MySqliteOpenHelper;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
import com.luck.picture.lib.listener.OnResultCallbackListener;
import java.util.List;
public class RegisterActivity extends AppCompatActivity {
private Button btnRegister; // 注册按钮
private EditText etAccount, etNickName, etPassword, etPasswordSure, etPhone, etRoom; // 输入框
private RequestOptions headerRO = new RequestOptions().circleCrop(); // 头像请求选项
private MySqliteOpenHelper helper; // 数据库助手
private String imagePath = ""; // 头像路径
private ImageView ivPhoto; // 头像ImageView
private RadioGroup rgSex; // 性别选择组
private TextView tvLogin; // 登录文本
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register); // 设置布局
helper = new MySqliteOpenHelper(this); // 初始化数据库助手
// 初始化UI组件
etAccount = findViewById(R.id.et_account);
etNickName = findViewById(R.id.et_nickName);
etPhone = findViewById(R.id.et_phone);
etRoom = findViewById(R.id.et_room);
etPassword = findViewById(R.id.et_password);
etPasswordSure = findViewById(R.id.et_password_sure);
ivPhoto = findViewById(R.id.iv_photo);
rgSex = findViewById(R.id.rg_sex);
tvLogin = findViewById(R.id.tv_login);
btnRegister = findViewById(R.id.btn_register);
// 设置头像点击事件,选择图片
ivPhoto.setOnClickListener(v -> selectClick());
// 设置登录文本点击事件,跳转到登录界面
tvLogin.setOnClickListener(v -> {
startActivity(new Intent(RegisterActivity.this, LoginActivity.class));
finish(); // 关闭当前活动
});
// 设置注册按钮点击事件
btnRegister.setOnClickListener(v -> {
String account = etAccount.getText().toString();
String nickName = etNickName.getText().toString();
String phone = etPhone.getText().toString();
String room = etRoom.getText().toString();
String password = etPassword.getText().toString();
String passwordSure = etPasswordSure.getText().toString();
// 检查输入的有效性
if (TextUtils.isEmpty(imagePath)) {
Toast.makeText(RegisterActivity.this, "请上传头像", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(account)) {
Toast.makeText(RegisterActivity.this, "用户名不能为空", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(nickName)) {
Toast.makeText(RegisterActivity.this, "昵称不能为空", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(phone)) {
Toast.makeText(RegisterActivity.this, "手机号不能为空", Toast.LENGTH_SHORT).show();
} else if (phone.length() != 11) {
Toast.makeText(RegisterActivity.this, "手机号格式错误", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(room)) {
Toast.makeText(RegisterActivity.this, "寝室不能为空", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(password)) {
Toast.makeText(RegisterActivity.this, "密码为空", Toast.LENGTH_SHORT).show();
} else if (!password.equals(passwordSure)) {
Toast.makeText(RegisterActivity.this, "密码不一致", Toast.LENGTH_SHORT).show();
} else {
// 获取性别
String sex = rgSex.getCheckedRadioButtonId() == R.id.rb_man ? "男" : "女";
User mUser = null; // 用户对象
SQLiteDatabase db = helper.getWritableDatabase(); // 获取可写数据库
Cursor cursor = db.rawQuery("select * from user where account = ?", new String[]{account}); // 查询是否已存在用户
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
mUser = new User(cursor.getInt(0), cursor.getString(1), cursor.getString(2),
cursor.getString(3), cursor.getString(4), cursor.getString(5),
cursor.getString(6), cursor.getString(7), cursor.getInt(8));
}
}
// 如果用户不存在,插入新用户
if (mUser == null) {
db.execSQL("insert into user(account, password,name,sex, phone,room,photo,userType) values(?,?,?,?,?,?,?,?)",
new Object[]{account, password, nickName, sex, phone, room, imagePath, UserTypeEnum.User.getCode()});
Toast.makeText(RegisterActivity.this, "注册成功", Toast.LENGTH_SHORT).show();
finish(); // 关闭当前活动
} else {
Toast.makeText(RegisterActivity.this, "该账号已存在", Toast.LENGTH_SHORT).show();
}
db.close(); // 关闭数据库
}
});
}
// 选择头像的方法
private void selectClick() {
PictureSelector.create(this)
.openGallery(PictureMimeType.ofImage()) // 打开图片选择器
.imageEngine(GlideEngine.createGlideEngine()) // 设置图片加载引擎
.maxSelectNum(1) // 限制最多选择一张图片
.forResult(new OnResultCallbackListener<LocalMedia>() {
@Override
public void onResult(List<LocalMedia> result) {
String path = result.get(0).getPath(); // 获取选择的图片路径
imagePath = path; // 更新头像路径
Glide.with(RegisterActivity.this).load(imagePath).into(ivPhoto); // 加载图片
}
@Override
public void onCancel() {
} // 取消选择时的回调
});
}
// 返回按钮点击事件
public void back(View view) {
finish(); // 关闭当前活动
}
}
首页
-
Fragment管理:
- 该活动使用数组
fragments
来存储不同的Fragment,便于在用户界面中进行切换。 - 提供了三个主要Fragment:学生首页(
StudentHomeFragment
)、管理员首页(AdminHomeFragment
)、用户管理(UserManageFragment
)和用户信息(UserFragment
)。
- 该活动使用数组
-
用户类型判断:
- 使用
SPUtils
获取用户类型,以决定显示的Fragment。不同用户类型(学生或管理员)会导致不同的Fragment切换逻辑。
- 使用
-
界面初始化:
- 在
onCreate
方法中,初始化视图组件,包括标题、内容布局和三个RadioButton。 - 根据用户类型控制"管理"按钮的可见性。
- 在
-
按钮点击监听:
- 为每个RadioButton设置点击事件,点击不同按钮会更新标题并切换相应的Fragment。
-
Fragment切换逻辑:
switchFragment(int fragmentIndex)
方法用于切换当前显示的Fragment。根据用户类型和选中的Fragment创建相应的Fragment实例,并管理Fragment的显示和隐藏。
-
返回键处理:
- 通过重写
onKeyDown
方法来处理返回键,提供了双击退出的功能。
- 通过重写
java
package com.example.studentdormitory.ui.activity;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.studentdormitory.R;
import com.example.studentdormitory.enums.UserTypeEnum;
import com.example.studentdormitory.ui.fragment.AdminHomeFragment;
import com.example.studentdormitory.ui.fragment.StudentHomeFragment;
import com.example.studentdormitory.ui.fragment.UserFragment;
import com.example.studentdormitory.ui.fragment.UserManageFragment;
import com.example.studentdormitory.util.SPUtils;
public class MainActivity extends AppCompatActivity {
private Fragment[] fragments = {null, null, null}; // 用于存储不同的Fragment
private LinearLayout llContent; // 主内容布局
private Activity myActivity; // 当前Activity引用
private RadioButton rbHome; // 首页按钮
private RadioButton rbManage; // 管理按钮
private RadioButton rbUser; // 用户按钮
private long time = 0; // 用于记录时间
private TextView tvTitle; // 标题文本
private Integer userType; // 用户类型
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myActivity = this;
setContentView(R.layout.activity_main);
// 初始化视图组件
tvTitle = findViewById(R.id.title);
llContent = findViewById(R.id.ll_main_content);
rbHome = findViewById(R.id.rb_main_home);
rbManage = findViewById(R.id.rb_main_manage);
rbUser = findViewById(R.id.rb_main_user);
initView(); // 初始化视图
setViewListener(); // 设置视图监听器
}
// 设置按钮点击监听器
private void setViewListener() {
rbHome.setOnClickListener(v -> {
tvTitle.setText("首页");
switchFragment(0); // 切换到首页Fragment
});
rbManage.setOnClickListener(v -> {
tvTitle.setText("学生管理");
switchFragment(1); // 切换到学生管理Fragment
});
rbUser.setOnClickListener(v -> {
tvTitle.setText("我的");
// 根据用户类型切换到相应的Fragment
switchFragment(userType.intValue() == UserTypeEnum.User.getCode() ? 1 : 2);
});
}
// 初始化视图组件
private void initView() {
userType = (Integer) SPUtils.get(myActivity, SPUtils.USER_TYPE, 0); // 获取用户类型
// 设置首页按钮图标
setRadioButtonIcon(rbHome, R.drawable.selector_main_rb_home);
// 设置管理按钮图标
setRadioButtonIcon(rbManage, R.drawable.selector_main_rb_manage);
// 设置用户按钮图标
setRadioButtonIcon(rbUser, R.drawable.selector_main_rb_user);
switchFragment(0); // 默认显示首页
// 根据用户类型决定管理按钮的可见性
rbManage.setVisibility(userType.intValue() == UserTypeEnum.User.getCode() ? View.GONE : View.VISIBLE);
rbHome.setChecked(true); // 默认选中首页按钮
}
// 设置RadioButton图标的封装方法
private void setRadioButtonIcon(RadioButton radioButton, int drawableId) {
Drawable icon = getResources().getDrawable(drawableId);
icon.setBounds(0, 0, 68, 68);
radioButton.setCompoundDrawables(null, icon, null, null);
radioButton.setCompoundDrawablePadding(5); // 设置图标与文本的间距
}
// 切换Fragment
private void switchFragment(int fragmentIndex) {
FragmentTransaction transaction = getFragmentManager().beginTransaction(); // 开启事务
if (fragments[fragmentIndex] == null) {
// 根据用户类型和选中的Fragment创建相应的Fragment实例
if (userType.intValue() == UserTypeEnum.User.getCode()) {
if (fragmentIndex == 0) {
fragments[fragmentIndex] = new StudentHomeFragment(); // 学生首页
} else if (fragmentIndex == 1) {
fragments[fragmentIndex] = new UserFragment(); // 用户信息
}
} else {
if (fragmentIndex == 0) {
fragments[fragmentIndex] = new AdminHomeFragment(); // 管理员首页
} else if (fragmentIndex == 1) {
fragments[fragmentIndex] = new UserManageFragment(); // 用户管理
} else if (fragmentIndex == 2) {
fragments[fragmentIndex] = new UserFragment(); // 用户信息
}
}
transaction.add(R.id.ll_main_content, fragments[fragmentIndex]); // 添加Fragment
}
// 隐藏其他Fragment
for (int i = 0; i < fragments.length; i++) {
if (fragmentIndex != i && fragments[i] != null) {
transaction.hide(fragments[i]); // 隐藏不需要的Fragment
}
}
transaction.show(fragments[fragmentIndex]); // 显示选中的Fragment
transaction.commit(); // 提交事务
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exit(); // 处理返回键
return true;
}
return false;
}
// 处理应用退出
public void exit() {
if (System.currentTimeMillis() - time > 2000) {
time = System.currentTimeMillis(); // 更新退出时间
Toast.makeText(myActivity, "再点击一次退出应用程序", Toast.LENGTH_SHORT).show(); // 提示信息
} else {
finish(); // 关闭应用
}
}
}
四、完整的项目源码
👇👇👇👇👇快捷获取方式👇👇👇👇👇