1.系统环境:Windows、Mac等
2.集成开发环境:Android Studio、虚拟机版本为Android 7.0(Nexus 5 API 24型号)
数据库系统:Android Studio自带轻量级数据库SQLite
辅助工具:Mark Man(图标标注工具)、iconfont(阿里巴巴矢量图库)、MindMaster(流程分析)
Android
1.Android客户端登录界面首先要有选择不同角色(用户、管理员)登录的下拉列表,可以根据用户各自的选项来确定展示部分,即可使用功能部分的多少。
2.登录界面还需设置不同的登录方式,可进行本机一键登录,也可以根据不同的手机号,通过消息提示框发送六位随机验证码的形式,和用户输入的进行对比,匹配成功后方可登录菜单界面。
3.普通用户登陆成功后,首先可以看到菜单界面,包括一个可左右滑动的健身不分类型选择,和一个可以上下滑动的课程分类。
4.会员用户登录后,可以在普通用户的基础上增添一个利用frame页面切换的效果,链接到自定义课程页面,可以根据课程名和课程类型,对自定义课程进行增、删、改、查操作,并将最终用户的课程添加到日常课程选项里。
5.用户可以通过下拉列表选择不同强度的训练,并且可以依照不同的日期,进行当天课程的规划安排。
6.用户可以根据每个课程所学的时间在个人信息界面统计出自己所学课程的总健身时间。
(一)、用例建模
根据上述的用户需求,我们主要归纳该软件的功能模块如下:
1.健身课程模块,对健身课程进行基本的分类展示
2.组图模块,将健身课程以一个列表组合的图片形式进行展现
3.视频模块,将健身视频有机融合在软件的设计中
4.课程详情页,可以根据用户的需求,自定义健身课程,并添加到日常课程中
5.反馈模块,用户可以将自己使用软件的反馈信息提交到控制台,也可接收自己的课程信息
6.用户管理界面,管理员可根据选择的用户信息进行修改、删除
根据系统的需求实现和功能分析,我主要归纳整理出以下四个大主体——普通用户、会员用户、管理员以及课程管理数据库,通过功能重叠、交叉,画出该系统的用例分析图如下:
(一)、概要设计
根据软件系统的设计理念,将上述需求分析阶段得到的用户需求进行分析、总结、归纳,得到该系统的实体以及实体属性,并在这里采用层次图的方式抽象成信息结构即概念模型。
(二)、数据库设计
本系统主要分为用户数据库和课程数据库两类,如下图所示:
表1 用户表
字段名称 |
数据类型 |
长度 |
是否允许null值 |
约束 |
备注 |
用户编号 |
Integer |
否 |
主键 |
||
用户名 |
VarChar |
否 |
|||
用户类型 |
Boolean |
是 |
表2 课程表
字段名称 |
数据类型 |
长度 |
是否允许null值 |
约束 |
备注 |
课程编号 |
Integer |
否 |
主键 |
||
课程名 |
VarChar |
否 |
|||
课程类型 |
Varchar |
是 |
(三)、算法设计
根据上述概要设计,我们对本系统的功能有了大体的了解,紧接着,便是选择合适的编程算法,对所要达到的目的进行操作上的实现,为了避免自然语言在语法和语义上常常展示的多义性,导致运行系统、试用群体及编程者们出现歧义,这里我们选择用流程图的方式对我们需要做到的登录界面的过程进行简单的概括,为后期的具体功能的开发提供良好的算法支持,登录界面的流程图如下所示:
(一)、广告界面的设计
1.UI设计
用默认布局ConstraintLayout(约束布局)作为底层布局,为保证代码在整体设计之初就尽量减少,因此我这里也本着控件减少的理念设计第一个主页布局,即将其的背景直接设置为Keep软件起始展示的背景图片,由于约束布局本身的自适应手机大小的特性,也避免了用ImageView插入图片后再继续调整图片大小与位置的漏洞,避免图片的拉伸导致失帧。
紧接着,我对右上方的跳过按钮进行了简单的优化,设计灵感也是来源于平日生活中,大部分软件对于广告跳过时出现的按钮样式,这里,我在drawable文件夹中自定义新建了一个名为shape的Drawable resource file,用来改变按钮的原始默认样式,具体效果展示如下:
部分代码如下所示 :
2.功能实现
这里我首先选择使用Timer对象,通过新建的timer调用定时器的常用方法schedule接着创建TimerTask()执行其定义的抽象方法run(),将显示意图的跳转效果写在方法体内部,执行意图,并设定其延迟时间。可是,在运行时发现了一个运行bug,即无论我是否点击跳过按钮进行及时跳过,这个延迟三秒的方法都会实现,也就是说,他们跳转的下一个界面会打开两次,这里我便开始思考,如何设置自己的方法,让它进行简单的方法体互斥,因此,我想到了使用全局变量和if语句条件判断进行拦截的方式,即设置一个布尔类型的变量进行条件筛选,运行后依旧出现问题,在对方法体进行分析后,发现此类方法体虽然设定了延迟时间,但其本身方法与延迟时间在同一个方法体内部定义,即它要先执行这个方法才能延迟时间,也就是说,无论布尔值后期被改变为多少,由于方法的同时性,它在进入时始终是变量初值,后期按钮的监听事件并不能进行改变。
new Thread() {
@Override
public void run() {
super.run();
try {
Thread.sleep(3000);//休眠3秒
} catch (InterruptedException e) {
e.printStackTrace();}
if (!skip) {
Intent intent = new Intent(MainActivity.this, LoginFrame.class);
startActivity(intent); }}}.start();
(二)、登录界面的设计
1.UI设计
通过插入videoView视频控件作为接收视频的容器,设置其大小布满手机屏幕。其中为方便所要插入的图片格式自适应,这里大多图片都以TextView设置背景图的形式展现。而为实现后期功能的分支,这里也使用了Spinner下拉列表控件,也设置了单选按钮来模拟现实生活中软件与用户的协议要求。具体实现效果如下图:
2.功能实现
这里Android开发提供了两种不同的导入方式,其中使用MeidiaPlayer播放音频,并不能简单插入在某个布局文件的内部,因此,只能通过在class内设置方法,才能通过此类来播放音频。为方便用户查看,实现打开界面就能保证始终播放,这里我最终选择使用VideoView控件进行视频文件的播放,通过在res文件目录下,引入视频源文件,通过相对路径进行引入,具体代码如下:
public void video(){
videoView=findViewById(R.id.videoView);
String packageName = getPackageName();
videoView.setVideoURI(Uri.parse("android.resource://"+packageName+"/"+R.raw.login));
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
mp.setLooping(true); }});}
通过适配器为它编写初始展示样式,也通过调用setDropDownViewResource()方法设置下拉列表下拉时的菜单样式,最后进行展示,具体代码如下所示:
list.add("普通用户");
list.add("会员用户");
spinneruser=(Spinner)findViewById(R.id.spinner3);
adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinneruser.setAdapter(adapter);
(三)、验证码界面的设计
1.UI设计
根据上述理念的描述过程,我在默认的约束布局内部加入简单的几个文本框与按钮控件,仅修改其文字大小、内边距等控件属性,这里采用约束布局能较快的分配每个控件在手机展示窗口的大体位置,方便做进一步调整,展示效果如下所示:
根据上述要求,这里继续选用控件设定位置相对灵活性较高的约束布局,添加文本框提示用户输入验证码的信息,具体效果体现如下:
2.功能实现
通过Math类的random方法生成一个六位随机数,将这两个重要信息与本机号码一同添加至大篮子(Bundle)对象中,进行下一个界面的值传递,为了更好的实现变量的动态共用方法。具体代码操作如下:
db = openOrCreateDatabase("test.db", Context.MODE_PRIVATE, null);
Cursor cursor=db.query("user",null,"number like ?",
new String[]{number},null,null,null);
while (cursor.moveToNext()){
String position=String.valueOf(cursor.getString(2));
if(position.equals("1")){
int round = (int) Math.round(Math.random() * (999999 - 100000) + 100000);
String code = String.valueOf(round);
Toast.makeText(LoginFrameOther.this, "验证码为"+code, Toast.LENGTH_SHORT).show();
Bundle bundle=new Bundle();
bundle.putString("code",code);
bundle.putString("number",number);
bundle.putString("judgement","true");
Intent intent=new Intent(this,LoginFrameOtherNext.class);
intent.putExtras(bundle);
startActivity(intent);
(四)、菜单页界面的设计
1.UI设计
在默认约束布局内添加ViewPager控件即可。
2.功能实现
首先该类需要继承FragmentActivity父类的抽象方法,还需要实现两个Fragment对象各自的接口,以设置监听事件的抽象方法,接下来在该类中自定义FragAdapter类继承FragmentPagerAdapter,用来与ViewPager进行适配,创建的两个Fragment对象文件,添加至一个数组中,初始化ViewPager控件,并调用setAdapter()方法即可,具体代码体现如下:
public class FragAdapter extends FragmentPagerAdapter {
public FragAdapter(FragmentManager fm, Listfragments) {
super(fm);
fragmentList=fragments;}
@Override
public Fragment getItem(int arg0) {
return fragmentList.get(arg0);}
@Override
public int getCount() {
return fragmentList.size();}}
(五)、推荐页界面的设计
1.UI设计
剩下的两个切换效果,我分别使用了HorizontalScrollView横向滚动条和ListView控件,对课程的类型及具体课程的信息进行了简单的分类,两种生成滚动条的不同形式,避免了相同代码的冗余情况,实现了相同效果的不同体现方式的代码创新。这里对各个文本框的样式也进行了细节上的优化,即设置一个布局文件,将文本框的background属性设置为该文件的相对路径。
2.功能实现
初始化ListView控件,进行绑定设置,定义一个内部类MyBaseAdapter继承最基本的适配器BaseAdapter,并且实现它继承的四个抽象方法,分别得到当前item的条目总数、代表对象、id下标以及转换后的View视图对象,最后在该类建成的onCreate()方法中创建一个Adapter实例,设置listview控件添加当前适配器。具体代码如下:
public View getView(int position, View convertView, ViewGroup parent) {
View view=View.inflate(Fragment1.this.getActivity(),R.layout.list_item,null);
TextView textView=(TextView) view.findViewById(R.id.textView10);
TextView textView1=(TextView) view.findViewById(R.id.textView11);
TextView textView2=(TextView) view.findViewById(R.id.textView14);
textView.setText(names[position]);
textView1.setText(text1[position]);
textView2.setText(text2[position]);
ImageView imageView=(ImageView)view.findViewById(R.id.imageView9);
imageView.setBackgroundResource(icons[position]);
return view;}
(六)、会员精选界面的设计
1.UI设计
对于该页面的UI设计,我首先引用了之前推荐页的标题栏,将“会员精选”的样式进行突出,接着添加一个ListView控件用于显示会员自定义的课程数据,接着是两个编辑框的添加,首行编辑框是主要运行的字段名检索,而课程类型编辑框则用于修改按钮的单独使用,最后是四个按钮控件的添加。展示效果为追求查询效率,则故意简化UI设计,以减少加载时间。
2.功能实现
采用for循环进行图片的循环输出,其中定义一个判别变量flag,根据它值的不同设置不同的图片,而根据简单的数学思想指定的算法,利用取余的方式,实现简单的循环效果,具体代码如下:
if(flag<=2){ if(flag==0){
layout.setBackgroundResource(R.drawable.classone);
flag=flag+1; }else if(flag==1){
layout.setBackgroundResource(R.drawable.classtwo);
flag=flag+1; }else if(flag==2){
layout.setBackgroundResource(R.drawable.classthree);
flag=flag+1;}}else{ flag=flag%3;
if(flag==0){ layout.setBackgroundResource(R.drawable.classone);
flag=flag+1;
}else if(flag==1){ layout.setBackgroundResource(R.drawable.classtwo);
flag=flag+1;
}else if(flag==2){ layout.setBackgroundResource(R.drawable.classthree);
flag=flag+1;}}
(七)、个人信息界面的设计(定时公告滚动条)
1.UI设计
根据上述要求,我开始设计本页面的具体布局形式,为了进一步利用帧布局体现UI叠加的效果,这里我选用FrameLayout作为打底布局,上下两个线性布局采用2:1的形式隔开,同等级别下,在建立一个约束布局,在其中添加文本框控件,并设置其背景与外边距属性,根据用户自定义的位置,让其悬浮于两个线性布局之上,形成所需效果。具体效果图如下:
2.功能实现
实例化一个Handler对象,将所要执行的循环体写在其继承实现的Runnable方法体内部,根据调用postDelayed()方法,设置所要执行的方法体和间隔时间,具体代码如下:
Runnable runnable = new Runnable() {
@Override
public void run() {
if(judge==1){ textView.setText("618狂欢,年卡超值7折起");
judge=0;
}else{ textView.setText("学生618专属,限时5折起"); judge=1;}
handler.postDelayed(this, 3000);}
(八)、全部课程规划界面的设计
1.UI设计
首先我添加了一个水平方向的线性布局,在其中设置了四个按钮作为日期,为了整体布局的美观考虑,给它的属性添加了特殊的按钮样式,这里也可以继续使用横向滚动条的控件,进一步实现贴近生活的效果,此后我选择帧布局作为底层布局,将四个线性布局叠加嵌套在同一个位置,根据下拉列表Spinner控件选择的文本信息,对课程进行添加,这里为了避免多次使用ListView控件匹配适配器的方法,为了实现同样的效果,通过线性布局叠加滚动条的办法,根据用户单击事件,去增添新视图,而四个日期的即时切换效果,则根据不同的日期按钮,设置四个布局文件是否可见的属性,自主控制它们的显示优先级来完成。具体效果体现如下图所示:
2.功能实现
一个是对下拉列表的设置,通过定义下拉列表内容、为下拉列表定义一个适配器、设置下拉列表下拉时的菜单样式、将适配器添加到下拉列表上、添加监听器,为下拉列表设置事件的响应五步走,对下拉列表控件进行绑定和功能实现,第二部分则是对课程添加操作的编写,最后是与个人信息界面达成值回传的绑定效果。
spinnername=(Spinner)findViewById(R.id.spinner);
adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnername.setAdapter(adapter);
spinnername.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView> parent, View view, int position, long id) { name=adapter.getItem(position);
parent.setVisibility(View.VISIBLE); }
public void onNothingSelected(AdapterView> parent) {
name=""; parent.setVisibility(View.VISIBLE); }});
(九)、管理员操作界面的设计
1.UI设计
根据概述的信息,我们首先对管理员的布局界面进行设计,这里采用视图控件与文本框控件交替的方法,其中View视图起到的作用是在两列之间起到分割的作用,纵观这个布局文件,就是完成这样的工作,设置一个表头,将三个TextView放置在一个水平的线性布局中去,分别显示一列的表头,然后需要一个ListView与上述的线性布局一同放入一个垂直的线性布局中去,用来显示每一条记录。而每一条记录的显示需要我们来实现一个adapter适配器去适配数据进而完成每一项的显示,这样我们就基本完成了程序的主体布局,实现效果图如下:
2.功能实现
添加一个长按事件,并实例化一个窗口,接着根据switch语句分别设定四种选项——增添、修改、删除以及取消,设置点击事件,并引入AlertDialog对话框,这里对数据库的操作也不同于往常的Dao设计模式,即将所有的数据库执行方法写入一个Dao类中,而是通过增加一个SQLiteDatabase对象。
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView> parent, View view,
final int position, long id) {
new AlertDialog.Builder(ManagerActivity.this) .setTitle("选择操作")
.setItems(new String[] {"增添", "更新", "删除", "取消" },
new DialogInterface.OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) { switch (which) { case 0: LayoutInflater inflater = getLayoutInflater();
final View layout = inflater.inflate(R.layout.dialog, null);
至此,该Android开发模拟Keep运动健身管理系统的基本功能与界面展示完毕。如对您有所帮助,望留下宝贵一赞!谢谢!
需源码、1w5报告 请私信 扣扣 1092644308