Android Studio实现志愿者系统

news2024/11/13 15:57:35

项目目录

  • 一、项目概述
  • 二、主要技术
  • 三、开发环境
  • 四、详细设计
    • 1、基础Activity
    • 2、活动信息
    • 3、成员信息
    • 4、百度地图
    • 5、Widget组件
  • 五、运行演示

一、项目概述

本系统采用MVC架构设计,SQLite数据表有用户表、成员表和活动表,有十多个Activity页面。打开应用,进入欢迎界面,3s后跳转登录界面,用户先注册账号,登录成功后进入主界面。主界面可以查看我的活动,修改和删除活动,还能发布活动。可以添加和删除成员、还能查看我的成员信息。可以查看和修改个人信息。底部导航栏和顶部菜单栏,菜单栏可以打开背景音乐、查询位置和查询时间。应用还制作了钟表显示的小组件,功能非常丰富。

二、主要技术

主要应用的技术如下:

Fragment碎片Service后台服务SharedPreferencesMediaPlayer
HandlerSQLiteDatabaseBundleRecyclerView
Thread多线程Menu菜单栏百度地图Widget组件开发

本项目知识点还是很多的,涉及到Service后台服务,百度地图定位功能,Widget桌面组件开发等。

三、开发环境

开发环境依旧是在Android Studio4.2.1,只要你的AS是近两年从官网下载的,都是可以满足的。日期版本是比4.2.1高的。
在这里插入图片描述

四、详细设计

1、基础Activity

首先,讲下欢迎、注册和登录,这三者作为App不可或缺的内容,同时也是逻辑细节和UI设计最需要注意的地方,做完容易,做好不容易。做过这么多应用了,不同样式的登录界面也接触了20来种。本次注册登录还是很喜欢的风格,很丰富的提示信息,保证账号的唯一性。记住密码,方便用户,注册完也连带账号和密码一起传回来。Layout的Code过于简单,看下Design视图。

在这里插入图片描述

再来讲MainActivity,奠定应用基调的Activity,至关重要,你要将应用的所有功能呈现在这里,底部导航栏采用BottomNavigationView,顶部Menu菜单栏、导航栏以及主体部分都是系统功能。按钮都设置了渐变色的background,按下变色。导航栏有图标,后面的各个输入框都有图标。

在这里插入图片描述
MainActivity的代码很多,因为它负责了后台音乐、位置查询、活动的查看修改删除发布等页面跳转,查看删除添加成员的跳转,以及个人信息的修改等。这里就一起看下导航栏的监听器吧,和Onclick方法很相似,只能说接口方法好像都如此。

// 底部导航栏监听器
  bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
      @Override
      public boolean onNavigationItemSelected(MenuItem item) {
          switch (item.getItemId()) {
              case R.id.my_member:
                  Intent intentMember = new Intent(MainActivity.this, ViewMember.class);
                  startActivity(intentMember);
                  return true;
              case R.id.release_activity:
                  Intent intentActivity = new Intent(MainActivity.this, ReleaseActivity.class);
                  startActivity(intentActivity);
                  return true;
              case R.id.personal_information:
                  Intent intentPersonal = new Intent(MainActivity.this, PersonalActivity.class);
                  startActivity(intentPersonal);
                  return true;
          }
          return false;
      }
  });

2、活动信息

先看下Activity的Bean类的属性and方法。

// 我的活动实体类
public class MyActivity {
    private String name;
    private String number;
    private String beginDate;
    private String endDate;
    public MyActivity() {

    }

    public MyActivity(String name, String number, String beginDate, String endDate) {
        this.name = name;
        this.number = number;
        this.beginDate = beginDate;
        this.endDate = endDate;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

   public String getBeginDate() {
        return beginDate;
   }

   public void setBeginDate() {
        this.beginDate = beginDate;
   }

   public String getEndDate() {
        return endDate;
   }

   public void setEndDate() {
        this.endDate = endDate;
   }
}

再来看下数据库中Activity表,你会发现数据表的字段名就是Bean的属性名。

   // 活动表建表语句
   public static final String CREATE_MYACTIVITY = "create table MyActivity (" +
           "name varchar(20) primary key," +
           "number varchar(20)," +
           "beginDate varchar(20)," +
           "endDate varchar(20))";

建立好表后,在ActivityDao中写好对活动表的增删改查方法吧,后面只需要创建ActivityDao对象就可以操作活动表了,不需要每次都写一遍。

	// 添加我的活动
    public void insertMyActivity(MyActivity myActivity) {
        // 创建ContentValues对象
        ContentValues values = new ContentValues();
        // 向该对象中插入键值对
        values.put("name", myActivity.getName());
        values.put("number", myActivity.getNumber());
        values.put("beginDate", myActivity.getBeginDate());
        values.put("endDate", myActivity.getEndDate());
        // 通过insert()方法插入数据
        sqLiteDatabase.insert(MyDBOpenHelper.TABLE_MYACTIVITY, null, values);
    }
    // 删除我的活动
    public void deleteMyActivity(MyActivity myActivity) {
        sqLiteDatabase.delete(MyDBOpenHelper.TABLE_MYACTIVITY, "name = ?", new String[]{myActivity.getName()});
    }
    // 修改我的活动
    public void updateMyActivity(MyActivity myActivity) {
        ContentValues values = new ContentValues();
        values.put("name", myActivity.getName());
        values.put("number", myActivity.getNumber());
        values.put("beginDate", myActivity.getBeginDate());
        values.put("endDate", myActivity.getEndDate());
        sqLiteDatabase.update(MyDBOpenHelper.TABLE_MYACTIVITY, values, "name = ?", new String[]{myActivity.getName()});
    }
    // 查询我的活动
    public ArrayList<MyActivity> queryMyActivity() {
        ArrayList<MyActivity> arrayList = new ArrayList<>();
        Cursor cursor = sqLiteDatabase.query(MyDBOpenHelper.TABLE_MYACTIVITY, null, null, null, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                String name = cursor.getString(cursor.getColumnIndex("name"));
                String number = cursor.getString(cursor.getColumnIndex("number"));
                String beginDate = cursor.getString(cursor.getColumnIndex("beginDate"));
                String endDate = cursor.getString(cursor.getColumnIndex("endDate"));
                MyActivity myActivity = new MyActivity(name, number, beginDate, endDate);
                arrayList.add(myActivity);
            } while (cursor.moveToNext());
        }
        cursor.close();
        return arrayList;
    }
    // 根据名称查询我的活动
    public MyActivity queryByName(String activityName) {
        Cursor cursor = sqLiteDatabase.query(MyDBOpenHelper.TABLE_MYACTIVITY, null, null, null, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                // 遍历Cursor对象,取出数据比对
                String name = cursor.getString(cursor.getColumnIndex("name"));
                if (activityName.equals(name)) {
                    String number = cursor.getString(cursor.getColumnIndex("number"));
                    String beginDate = cursor.getString(cursor.getColumnIndex("beginDate"));
                    String endDate = cursor.getString(cursor.getColumnIndex("endDate"));
                    MyActivity myActivity = new MyActivity(name, number, beginDate, endDate);
                    cursor.close();
                    return myActivity;
                }
            } while (cursor.moveToNext());
        }
        cursor.close();
        return null;
    }

在这里插入图片描述

3、成员信息

先来看下成员类的属性和方法:

// 成员实体类
public class Member {
    private String id;
    private String name;
    private String age;
    private String phone;

    public Member() {

    }

    public Member(String id, String name, String age, String phone) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.phone = phone;
    }

    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 getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

再写建表语句,SQL语法熟练的话,这些都是基操了,没什么内容。

    // 成员表建表语句
    public static final String CREATE_MEMBER = "create table Member (" +
            "id varchar(20) primary key," +
            "name varchar(20)," +
            "age varchar(20)," +
            "phone varchar(20))";

最后,还是写MemberDao,对用户表的增删改查封装好。

	// 添加我的成员
    public void insertMember(Member member) {
        // 创建ContentValues对象
        ContentValues values = new ContentValues();
        // 向该对象中插入键值对
        values.put("id", member.getId());
        values.put("name", member.getName());
        values.put("age", member.getAge());
        values.put("phone", member.getPhone());
        // 通过insert()方法插入数据
        sqLiteDatabase.insert(MyDBOpenHelper.TABLE_MEMBER, null, values);
    }
    // 删除我的成员
    public void deleteMember(Member member) {
        sqLiteDatabase.delete(MyDBOpenHelper.TABLE_MEMBER, "id = ?", new String[]{member.getId()});
    }
    // 修改我的成员
    public void updateMember(Member member) {
        ContentValues values = new ContentValues();
        values.put("id", member.getId());
        values.put("name", member.getName());
        values.put("age", member.getAge());
        values.put("phone", member.getPhone());
        sqLiteDatabase.update(MyDBOpenHelper.TABLE_MEMBER, values, "id = ?", new String[]{member.getId()});
    }
    // 查询我的成员
    public ArrayList<Member> queryMember() {
        ArrayList<Member> arrayList = new ArrayList<>();
        Cursor cursor = sqLiteDatabase.query(MyDBOpenHelper.TABLE_MEMBER, null, null, null, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                String id = cursor.getString(cursor.getColumnIndex("id"));
                String name = cursor.getString(cursor.getColumnIndex("name"));
                String age = cursor.getString(cursor.getColumnIndex("age"));
                String phone = cursor.getString(cursor.getColumnIndex("phone"));
                Member member = new Member(id, name, age, phone);
                arrayList.add(member);
            } while (cursor.moveToNext());
        }
        cursor.close();
        return arrayList;
    }
    // 根据编号查询成员
    public Member queryById(String memberId) {
        Cursor cursor = sqLiteDatabase.query(MyDBOpenHelper.TABLE_MEMBER, null, null, null, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                // 遍历Cursor对象,取出数据比对
                String id = cursor.getString(cursor.getColumnIndex("id"));
                if (memberId.equals(id)) {
                    String name = cursor.getString(cursor.getColumnIndex("name"));
                    String age = cursor.getString(cursor.getColumnIndex("age"));
                    String phone = cursor.getString(cursor.getColumnIndex("phone"));
                    Member member = new Member(id, name, age, phone);
                    cursor.close();
                    return member;
                }
            } while (cursor.moveToNext());
        }
        cursor.close();
        return null;
    }

在这里插入图片描述

4、百度地图

首先来看下我引入百度地图定位功能的过程。创建libs文件夹,然后拖拽BaiduLBS的jar包进去,然后Add as Library即可。
在这里插入图片描述

在AndroidManifest.xml中添加上meta-data标签和Service标签,一个是api_key,还有一个是location的服务。

        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="@string/api_key" />

        <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" />

在MapActivity中定义并配置地图的参数信息,然后初始化当前位置并显示,因为模拟器的经纬度信息是不通过网络或者GPS获取的,所以绝大多数时候是不能用来使用百度地图的,我们的坐标也都是手动输入显示即可,想使用还是要用真机,况且大家也不是做什么科研项目,不需要到室外定位。

        mapView = findViewById(R.id.map_view);
        baiduMap = mapView.getMap();// 获取到地图
        baiduMap.setMyLocationEnabled(true);
        initMap();     // 设置地图放大的倍数
        configureMap();// 设置定位的参数
        initLocation();// 初始化位置

5、Widget组件

Widget组件是最近才学习的内容,发现平时手机应用对Widget用的很少,不过作为Android开发的知识,有就了解一下不是坏事。为系统制作了一个日期显示的Widget桌面组件,可以在活动列表中拖到模拟器桌面上。后面运行时候会演示打开组件的方法。

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialKeyguardLayout="@layout/my_app_widget"
    android:initialLayout="@layout/my_app_widget"
    android:minWidth="150dp"
    android:minHeight="100dp"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="86400000"
    android:widgetCategory="home_screen"></appwidget-provider>

长按桌面,跳出小组件,然后选择志愿者系统的组件,拖拽到桌面上即可。
在这里插入图片描述

五、运行演示

Android Studio实现志愿者系统

说话有温度,与人交往才能有热度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182419.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

123、【回溯算法】leetcode ——491. 递增子序列:unordered_set去重和int数组去重(C++版本)

题目描述 原题描述&#xff1a;491. 递增子序列 解题思路 此题也是子集问题&#xff0c;但和 90.子集II &#xff08;子集问题startIndex去重&#xff09; 的区别在于&#xff1a;&#xff08;1&#xff09;存储结果集判定条件&#xff1b;&#xff08;2&#xff09;输入数据…

Python学习笔记十二之十大经典排序算法

Python学习笔记十二之十大经典排序算法 排序算法是《数据结构与算法》中最基本的算法之一。排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;…

zos JESMSGLG 不显示 job steps return codes

zos JESMSGLG 不显示 job steps return codes 在普通学习的时候&#xff0c;SDSF 查看 JCL 结果&#xff0c;可能并不会注意到下面结果有什么差别 但跟公司的大型机出的结果是不同的&#xff0c;就是缺少了 job steps return codes&#xff0c;在 STARTED 和 ENDED 中间应该有…

【Linux】冯诺依曼体系结构和操作系统

目录 一、冯诺依曼体系结构 1.组成 2.各结构特性 二、操作系统 1.概念 2.设计OS的目的 3.如何理解 "管理" 4.系统调用 一、冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依…

浅析故障电弧探测器在电气防火中的作用与应用介绍

安科瑞 李雨轩【摘要】&#xff1a; 分析了重大电气火灾数据。结合目前国内前沿的电气火灾探测技术&#xff0c;重点介绍了故障电弧式电气火灾监控探测器在火灾预警系统中的重要作用&#xff0c;给出了基于多种探测技术的电气火灾监控系统的实现方案。【关键词】&#xff1a;故…

C++模板初阶小笔记

目录 一.泛型编程 二.函数模板 1.函数模板语法梳理&#xff1a; 2.函数模板的实例化&#xff1a; 3.函数模板的显式实例化&#xff1a; 4.函数模板使用时的注意事项 三.类模板 1.类模板的语法梳理 2.类模板中声明和定义分离的成员函数 一.泛型编程 泛型编程&#xff…

【C++】类和对象---什么是类?

目录1.面向过程和面向对象初步认识2.类的引入2.1使用struct定义类3.类的定义3.1类的两种定义方式&#xff1a;3.2成员变量命名规则的建议3.3成员函数与成员变量定义的位置建议4.类的访问限定符及封装4.1访问限定符4.2封装5.类的作用域6.类的实例化7.类对象模型7.1如何计算类对象…

Kali Linux渗透

Kali Linux是基于Debian的Linux发行版&#xff0c; 设计用于数字取证操作系统。每一季度更新一次。 黑盒测试&#xff0c;它是通过测试来检测每个功能是否都能正常使用。在测试中&#xff0c;把程序看作一个不能打开的黑盒子&#xff0c;在完全不考虑程序内部结构和内部特性的情…

从C语言的使用转换到C++(上篇)——刷题、竞赛篇

文章目录 一、C的基础语法详解 1、1 输入、输出流 1、2 C中头文件的使用 1、3 C中变量的声明 1、4 C中的string类 1、5 C中的引用& 二、C中常见函数使用详解 2、1 排序sort函数详解 2、2 cctype头文件中的函数 三、总结 标题&#xff1a;从C语言的使用转换到C&#xff08;上…

④【Spring】IOC - 基于注解方式 管理bean

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 注解管理Bean一、注解的功能二、四个典型注解三…

day24|491.递增子序列、46.全排列、47.全排列 II

491.递增子序列 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一种特殊情况…

源码深度解析Spring Bean的创建,手把手的一步一步带你看源码

在源码深度解析Spring Bean的加载 中对Bean的加载源码进行了梳理,在本文将对bean的创建进行梳理 在doGetBean()方法中createBean()方法准备创建bean,调用源码如下: createBean() 方法的源码如下: 从代码中可以得出,createBean() 方法涉及4个步骤: 步骤一: 根据设置的class属…

[论文笔记]A ConvNet for the 2020s

目录 Abstract Modernizing a ConvNet: a Roadmap 2.1.Training Techniques 2.2. Macro Design 2.3. ResNeXt-ify 2.4. Inverted Bottleneck 2.5. Large Kernel Sizes 2.6. Micro Design 论文&#xff1a;https://arxiv.org/abs/2201.03545 代码&#xff1a;GitHub - f…

扩散模型(Diffusion model)代码详细解读

扩散模型代码详细解读 代码地址&#xff1a;denoising-diffusion-pytorch/denoising_diffusion_pytorch.py at main lucidrains/denoising-diffusion-pytorch (github.com) 前向过程和后向过程的代码都在GaussianDiffusion​这个类中。​ 常见问题解决 Why self-condition…

盒相关样式-----diaplay:block、inline

盒的基本类型 CSS中的盒分为block类型与inline类型&#xff0c;例如&#xff0c; div元素与p元素属于block类型&#xff0c; span元素与a元素属于inline类型。 block类型的盒对应的是html中的块级元素&#xff0c;inline类型的盒对应了html中的行内元素。 行内元素与块级元素…

JavaScript 练手小技巧:键盘事件

键盘事件应该是鼠标事件之外&#xff0c;使用频率最高的 JS 事件了吧&#xff1f; 一般用于全局或者表单。 键盘事件由用户击打键盘触发&#xff0c;主要有keydown、keypress、keyup三个事件。 keydown&#xff1a;按下键盘时触发。Ctrl、Shift、Alt 等和其它按键组合时&…

BCNF与3NF

今天学了一下午这个BCNFBCNFBCNF与3NF3NF3NF&#xff0c;有感而发&#xff0c;特来总结。好像好久不打键盘了&#xff0c;这手好像刚长出来的一样。本文浅显的分析一下两种范式的关系与不同以及判断方法和分解算法&#xff0c;以做总结。 BCNFBCNFBCNF范式的定义如下: 设属性集…

linux 常用指令大全

目录一、基本指令指令基本格式1、ls1.1 ls相关选项2、pwd3、cd4、mkdir4.1、mkdir相关选项5、touch6、cp6.1 cp相关选项7、mv8、rm8.1、rm相关选项9、输出重定向10、cat11、df11.1、df 相关选项12、free12.1、free 相关选项13、head13.1、head相关选项14、tail14.1 tail相关选项…

day13 二叉树 | 144、二叉树的前序遍历 145、二叉树的后序遍历 54、二叉树的中序遍历

二叉树基础 二叉搜索树 二叉搜索树是一个有序树。 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b;若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b;它的左、右子树也分别为二叉排序树 下面这两棵…

零食商城|基于springboot的零食商城

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…