网络资源模板--Android Studio 实现宿舍管理系统App

目录

一、项目演示

二、项目测试环境

三、项目详情

四、完整的项目源码


一、项目演示

网络资源模板--基于Android studio 实现的宿舍管理系统

二、项目测试环境

三、项目详情

所有项目页面展示:

登录页

  1. 界面组件

    • 包含账户输入框(etAccount)和密码输入框(etPassword)。
    • 有一个登录按钮(btnLogin)和一个注册文本视图(tvRegister)。
  2. 注册跳转

    • 点击注册文本视图会跳转到注册界面。
  3. 登录逻辑

    • 用户输入账户和密码后,首先检查输入是否为空。
    • 如果账户和密码都不为空,则通过SQLite数据库查询用户信息。
    • 如果用户存在,进一步验证密码是否正确。
    • 登录成功后,用户ID和用户类型被保存到SharedPreferences中,并跳转到主界面;如果登录失败,则显示相应的错误提示(如"账号不存在"或"密码错误")。
  4. 数据库操作

    • 使用MySqliteOpenHelper类管理SQLite数据库,查询用户数据。
  5. 用户反馈

    • 通过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(); // 结束当前活动
                }
            }
        });
    }
}

注册页

  1. 用户信息输入:

    • 提供了多个输入框供用户填写,包括账号、昵称、密码、确认密码、手机号和寝室号。
  2. 头像选择:

    • 允许用户点击头像ImageView选择图片,并使用Glide库加载选择的头像。
  3. 性别选择:

    • 用户可以通过RadioGroup选择性别。
  4. 数据验证:

    • 在用户点击注册按钮时,系统会进行多项验证,包括:
      • 头像是否已上传。
      • 账号、昵称、手机号、寝室号、密码等输入框不能为空。
      • 手机号格式是否正确(长度为11)。
      • 确认密码是否与密码一致。
  5. 用户注册逻辑:

    • 查询数据库以检查账号是否已存在。
    • 若账号不存在,则插入新用户信息到数据库。
    • 注册成功后显示提示信息,并结束当前活动。
    • 若账号已存在,则显示相应提示信息。
  6. 跳转到登录界面:

    • 提供一个文本链接,允许用户跳转回登录界面。
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(); // 关闭当前活动
    }
}

首页

  1. Fragment管理:

    • 该活动使用数组 fragments 来存储不同的Fragment,便于在用户界面中进行切换。
    • 提供了三个主要Fragment:学生首页(StudentHomeFragment)、管理员首页(AdminHomeFragment)、用户管理(UserManageFragment)和用户信息(UserFragment)。
  2. 用户类型判断:

    • 使用 SPUtils 获取用户类型,以决定显示的Fragment。不同用户类型(学生或管理员)会导致不同的Fragment切换逻辑。
  3. 界面初始化:

    • onCreate 方法中,初始化视图组件,包括标题、内容布局和三个RadioButton。
    • 根据用户类型控制"管理"按钮的可见性。
  4. 按钮点击监听:

    • 为每个RadioButton设置点击事件,点击不同按钮会更新标题并切换相应的Fragment。
  5. Fragment切换逻辑:

    • switchFragment(int fragmentIndex) 方法用于切换当前显示的Fragment。根据用户类型和选中的Fragment创建相应的Fragment实例,并管理Fragment的显示和隐藏。
  6. 返回键处理:

    • 通过重写 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(); // 关闭应用
        }
    }
}

四、完整的项目源码

👇👇👇👇👇快捷获取方式👇👇👇👇👇

相关推荐
梓仁沐白5 分钟前
【Kotlin】数字&字符串&数组&集合
android·开发语言·kotlin
技术小甜甜10 分钟前
【Godot】如何导出 Release 版本的安卓项目
android·游戏引擎·godot
火柴就是我26 分钟前
Dart 原始字符串(Raw Strings)详解文档
android
玲小珑37 分钟前
Auto.js 入门指南(五)实战项目——自动脚本
android·前端
玲小珑38 分钟前
Auto.js 入门指南(四)Auto.js 基础概念
android·前端
没有了遇见2 小时前
DrawerLayout 滑动冲突
android
玲小珑3 小时前
Auto.js 入门指南(六)多线程与异步操作
android·前端
用户2018792831674 小时前
通俗易懂理解Java注解
android
用户2018792831674 小时前
通俗易懂理解泛型
android
linversion4 小时前
如何手动上传Android混淆映射文件Mapping.txt到Firebase
android