一、设计背景
1.需求分析
对于很多人来说拥有一副好身材能让自己增添不少魅力;对于爱吃而又担心自己发胖的人来说适当的运动健身是最好的选择。移动互联网时代,市场上“约跑”“约健身”健身APP软件成为新时代闺蜜朋友的互动模式,健身热潮的来临,这样让越来越多的人加入健身的行列中,大众的健身热情也刺激着更多与健身有关的产业飞速发展,尤其是与“互联网+”结合产生的智能健身运动App开发更是发展得如火如荼... 人们通过一款健身运动型App应用就可以随时随地的进行健身锻炼,可以不用去健身房锻炼也可以达到完美的身材,这样健身运动App开发给人们带来了极大的方便。所以这次做的是一款健身类的软件,为了方便用户随时随地可以健身。在配色方面使用白色和绿色非常简单的颜色能让人眼前一亮。在软件功能方面,用户首先需要注册用户名填写密码,注册成功之后,用户可以用之前注册的用户名和密码进行登录。登录成功之后进入到导航页面,其中包括会员信息和健身项目两个部分,会员信息记录了会员的姓名身高体重等一些基本信息,还可以查看用户报名的课程名称,可以增加以及删除报名项目,健身项目页面则是列举出一些项目名称来供用户选择。
2.目的和意义
所以这次做的是一款健身类的软件,为了方便用户随时随地可以健身。在配色方面使用白色和绿色非常简单的颜色能让人眼前一亮。在软件功能方面,用户首先需要注册用户名填写密码,注册成功之后,用户可以用之前注册的用户名和密码进行登录。登录成功之后进入到导航页面,其中包括会员信息和健身项目两个部分,会员信息记录了会员的姓名身高体重等一些基本信息,还可以查看用户报名的课程名称,可以增加以及删除报名项目,健身项目页面则是列举出一些项目名称来供用户选择。
- 系统需求分析与开发环境
- 系统功能需求
 需要包含登入注册功能,用户名和密码储存在Sharedpreferences轻型数据类中,按钮实现页面跳转。包括数据库的增删查改功能,采用的是SQLite数据库。
- 系统界面需求
 简介美观,采用代表健康的绿色作为主色调,和健身的主题相符合。注册和登入的页面参考了许多app,要让页面做到简介美观,所以登入注册页面都用到了自定义按钮样式和自定义输入框样式,按钮设计出颜色渐变的样式并加入圆角看起来不生硬,输入框同样加入了圆角的设计。
- 开发环境
Android studio3.5.0
- 系统设计


登入注册页面制作完后,做了一个导航页面,页面上方可以横向滑动健身馆内部的图片。然后是会员页面,用户可以通过这个页面查询自己会员信息,这个页面也加入了增删查改的功能,采用的是SQlite数据库,方便用户对课程时间的记录。页面的设计同样采用了按钮的自定义样式和输入框的自定义样式。页面上方是用户的基本信息介绍,头像部分也是设计了一个图片样式的自定义,给图片添加了一个边框,使页面看起来和谐统一美观。


最后是一个课程的展示界面,包括了健身馆开展的全部课程,方便用户查看和挑选。
- 系统测试
- 电脑模拟器测试


- 总结与展望
 1.总结
 在这次移动终端开发课程设计过程中,我发现平时学习的知识与实践环节所用到的有一定的差距,往往我觉得自己掌握的很好或者自认为熟练的技术却在此次实践环节中往往出问题,书本上的知识只提供方法的借鉴,实践中自己必须摸索出适合具体工作的方法,这一切都离不开钻研精神与勤学好问的精神.在人与人相处过程中我收获更大,首先要谦虚谨慎,不能自以为是,认为自己懂得很多,而仅仅埋头苦干,而不向他人请教,工作不但是实践与应用的过程,同时也是学习的过程,我们必须加强与他人的沟通学习,以便获得与他人的交流。在这短短的时间里,让我深深的感觉到自己在实际应用中所学专业知识的匮乏。让我真真领悟到“学无止境”这句话的涵义。而老师在专业认识周中所讲的,都是课本上没有而对我们又非常实用的东西,这又给我们的实训增加了浓墨淡采的光辉。我懂得了实际生活中,专业知识是怎样应用与实践的。在这些过程中,我不仅知道了职业生涯所需具备的专业知识,而且让我深深体会到一个团队中各成员合作的重要性,要善于团队合作,善于利用别人的智慧,这才是大智慧。靠单一的力量是很难完成一个大项目的,在进行团队合作的时候,还要耐心听取每个成员的意见,使我们的组合达到更加完美。
- 重要程序
- LoginActivity
 public class LoginActivity extends AppCompatActivity {
 private TextView tv_main_title;//标题
 private TextView tv_back,tv_register,tv_find_psw;//返回键,显示的注册,找回密码
 private Button btn_login;//登录按钮
 private String userName,psw,spPsw;//获取的用户名,密码,加密密码
 private EditText et_user_name,et_psw;//编辑框
 @Override
 protected void onCreate(Bundle savedInstanceState){
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_login);
 //设置此界面为竖屏
 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 init();
 }
 //获取界面控件
 private void init() {
 //从main_title_bar中获取的id
 tv_main_title=findViewById(R.id.tv_main_title);
 tv_main_title.setText("登录");
 tv_back=findViewById(R.id.tv_back);
 //从activity_login.xml中获取的
 tv_register=findViewById(R.id.tv_register);
 tv_find_psw=findViewById(R.id.tv_find_psw);
 btn_login=findViewById(R.id.btn_login);
 et_user_name=findViewById(R.id.et_user_name);
 et_psw=findViewById(R.id.et_psw);
 //返回键的点击事件
 tv_back.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 //登录界面销毁
 LoginActivity.this.finish();
 }
 });
 //立即注册控件的点击事件
 tv_register.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 //为了跳转到注册界面,并实现注册功能
 Intent intent=new Intent(LoginActivity.this,RegisterActivity.class);
 startActivityForResult(intent, 1);
 }
 });
 //找回密码控件的点击事件
 tv_find_psw.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 //跳转到找回密码界面(此页面暂未创建)
 }
 });
 //登录按钮的点击事件
 btn_login.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 //开始登录,获取用户名和密码 getText().toString().trim();
 userName=et_user_name.getText().toString().trim();
 psw=et_psw.getText().toString().trim();
 //对当前用户输入的密码进行MD5加密再进行比对判断, MD5Utils.md5( ); psw 进行加密判断是否一致
 String md5Psw= MD5Utils.md5(psw);
 // md5Psw ; spPsw 为 根据从SharedPreferences中用户名读取密码
 // 定义方法 readPsw为了读取用户名,得到密码
 spPsw=readPsw(userName);
 // TextUtils.isEmpty
 if(TextUtils.isEmpty(userName)){
 Toast.makeText(LoginActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();
 return;
 }else if(TextUtils.isEmpty(psw)){
 Toast.makeText(LoginActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();
 return;
 // md5Psw.equals(); 判断,输入的密码加密后,是否与保存在SharedPreferences中一致
 }else if(md5Psw.equals(spPsw)){
 //一致登录成功
 Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
 //保存登录状态,在界面保存登录的用户名 定义个方法 saveLoginStatus boolean 状态 , userName 用户名;
 saveLoginStatus(true, userName);
 //登录成功后关闭此页面进入主页
 Intent data=new Intent();
 //datad.putExtra( ); name , value ;
 data.putExtra("isLogin",true);
 //RESULT_OK为Activity系统常量,状态码为-1
 // 表示此页面下的内容操作成功将data返回到上一页面,如果是用back返回过去的则不存在用setResult传递data值
 setResult(RESULT_OK,data);
 //销毁登录界面
 LoginActivity.this.finish();
 //跳转到主界面,登录成功的状态传递到 MainActivity 中
 startActivity(new Intent(LoginActivity.this,Classification.class));
 return;
 }else if((spPsw!=null&&!TextUtils.isEmpty(spPsw)&&!md5Psw.equals(spPsw))){
 Toast.makeText(LoginActivity.this, "输入的用户名和密码不一致", Toast.LENGTH_SHORT).show();
 return;
 }else{
 Toast.makeText(LoginActivity.this, "此用户名不存在", Toast.LENGTH_SHORT).show();
 }
 }
 });
 }
 private String readPsw(String userName){
 //getSharedPreferences("loginInfo",MODE_PRIVATE);
 //"loginInfo",mode_private; MODE_PRIVATE表示可以继续写入
 SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
 //sp.getString() userName, "";
 return sp.getString(userName , "");
 }
 private void saveLoginStatus(boolean status,String userName){
 //saveLoginStatus(true, userName);
 //loginInfo表示文件名 SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
 SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
 //获取编辑器
 SharedPreferences.Editor editor=sp.edit();
 //存入boolean类型的登录状态
 editor.putBoolean("isLogin", status);
 //存入登录状态时的用户名
 editor.putString("loginUserName", userName);
 //提交修改
 editor.commit();
 }
 /**
 * 注册成功的数据返回至此
 * @param requestCode 请求码
 * @param resultCode 结果码
 * @param data 数据
 */
 @Override
 //显示数据, onActivityResult
 //startActivityForResult(intent, 1); 从注册界面中获取数据
 //int requestCode , int resultCode , Intent data
 // LoginActivity -> startActivityForResult -> onActivityResult();
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 //super.onActivityResult(requestCode, resultCode, data);
 super.onActivityResult(requestCode, resultCode, data);
 if(data!=null){
 //是获取注册界面回传过来的用户名
 // getExtra().getString("***");
 String userName=data.getStringExtra("userName");
 if(!TextUtils.isEmpty(userName)){
 //设置用户名到 et_user_name 控件
 et_user_name.setText(userName);
 //et_user_name控件的setSelection()方法来设置光标位置
 et_user_name.setSelection(userName.length());
 }
 }
 }
 }
- RegisterActivity
 public class RegisterActivity extends AppCompatActivity {
 private TextView tv_main_title;//标题
 private TextView tv_back;//返回按钮
 private Button btn_register;//注册按钮
 //用户名,密码,再次输入的密码的控件
 private EditText et_user_name,et_psw,et_psw_again;
 //用户名,密码,再次输入的密码的控件的获取值
 private String userName,psw,pswAgain;
 //标题布局
 private RelativeLayout rl_title_bar;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 //设置页面布局 ,注册界面
 setContentView(R.layout.activity_register);
 //设置此界面为竖屏
 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 init();
 }
 private void init() {
 //从main_title_bar.xml 页面布局中获取对应的UI控件
 tv_main_title=findViewById(R.id.tv_main_title);
 tv_main_title.setText("注册");
 tv_back=findViewById(R.id.tv_back);
 //布局根元素
 rl_title_bar=findViewById(R.id.title_bar);
 rl_title_bar.setBackgroundColor(Color.TRANSPARENT);
 //从activity_register.xml 页面中获取对应的UI控件
 btn_register=findViewById(R.id.btn_register);
 et_user_name=findViewById(R.id.et_user_name);
 et_psw=findViewById(R.id.et_psw);
 et_psw_again=findViewById(R.id.et_psw_again);
 tv_back.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 //返回键
 RegisterActivity.this.finish();
 }
 });
 //注册按钮
 btn_register.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 //获取输入在相应控件中的字符串
 getEditString();
 //判断输入框内容
 if(TextUtils.isEmpty(userName)){
 Toast.makeText(RegisterActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();
 return;
 }else if(TextUtils.isEmpty(psw)){
 Toast.makeText(RegisterActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();
 return;
 }else if(TextUtils.isEmpty(pswAgain)){
 Toast.makeText(RegisterActivity.this, "请再次输入密码", Toast.LENGTH_SHORT).show();
 return;
 }else if(!psw.equals(pswAgain)){
 Toast.makeText(RegisterActivity.this, "输入两次的密码不一样", Toast.LENGTH_SHORT).show();
 return;
 /**
 *从SharedPreferences中读取输入的用户名,判断SharedPreferences中是否有此用户名
 */
 }else if(isExistUserName(userName)){
 Toast.makeText(RegisterActivity.this, "此账户名已经存在", Toast.LENGTH_SHORT).show();
 return;
 }else{
 Toast.makeText(RegisterActivity.this, "注册成功", Toast.LENGTH_SHORT).show();
 //把账号、密码和账号标识保存到sp里面
 /**
 * 保存账号和密码到SharedPreferences中
 */
 saveRegisterInfo(userName, psw);
 //注册成功后把账号传递到LoginActivity.java中
 // 返回值到loginActivity显示
 Intent data = new Intent();
 data.putExtra("userName", userName);
 setResult(RESULT_OK, data);
 //RESULT_OK为Activity系统常量,状态码为-1,
 // 表示此页面下的内容操作成功将data返回到上一页面,如果是用back返回过去的则不存在用setResult传递data值
 RegisterActivity.this.finish();
 }
 }
 });
 }
 /**
 * 获取控件中的字符串
 */
 private void getEditString(){
 userName=et_user_name.getText().toString().trim();
 psw=et_psw.getText().toString().trim();
 pswAgain=et_psw_again.getText().toString().trim();
 }
 /**
 * 从SharedPreferences中读取输入的用户名,判断SharedPreferences中是否有此用户名
 */
 private boolean isExistUserName(String userName){
 boolean has_userName=false;
 //mode_private SharedPreferences sp = getSharedPreferences( );
 // "loginInfo", MODE_PRIVATE
 SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
 //获取密码
 String spPsw=sp.getString(userName, "");//传入用户名获取密码
 //如果密码不为空则确实保存过这个用户名
 if(!TextUtils.isEmpty(spPsw)) {
 has_userName=true;
 }
 return has_userName;
 }
 private void saveRegisterInfo(String userName,String psw){
 String md5Psw = MD5Utils.md5(psw);//把密码用MD5加密
 //loginInfo表示文件名, mode_private SharedPreferences sp = getSharedPreferences( );
 SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
 //获取编辑器, SharedPreferences.Editor editor -> sp.edit();
 SharedPreferences.Editor editor=sp.edit();
 //以用户名为key,密码为value保存在SharedPreferences中
 //key,value,如键值对,editor.putString(用户名,密码);
 editor.putString(userName, md5Psw);
 //提交修改 editor.commit();
 editor.commit();
 }
 }
- DatabaseHelper
public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context){super(context,"Test.db",null,1);}
//第一个参数是上下文,第二个参数是数据库名称,
//第三个参数是CursorFactory对象,一般设置为null,第四个参数是数据库的版本
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20),age INTEGER)");
}
//创建表 表名information 表结构 自增id,字符串姓名,int年龄
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d("myDeBug","数据库版本已更新");
}
//数据库版本发生变化时调用
}
4.DictActivity
public class DictActivity extends AppCompatActivity {
private Button insertButton, updateButton, searchButton, deleteButton;
private Button btn_xl1;
private EditText name, age;
private TextView show, showAge;
final DatabaseHelper dbHelper = new DatabaseHelper(DictActivity.this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dict);
btn_xl1 = findViewById(R.id.btn_xl);
btn_xl1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建Intent 对象
Intent intent = new Intent(DictActivity.this, Classification.class);
//启动Activity
startActivity(intent);
}
});
insertButton = findViewById(R.id.btn_insert);
updateButton = findViewById(R.id.btn_update);
searchButton = findViewById(R.id.btn_search);
deleteButton = findViewById(R.id.btn_delete);
name = findViewById(R.id.name);
age = findViewById(R.id.age);
show = findViewById(R.id.tv_show);
showAge = findViewById(R.id.tv_showAge);
SQLiteDatabase db = dbHelper.getReadableDatabase();
myShow();
insertButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", name.getText().toString());
values.put("age", age.getText().toString());
long id = db.insert("information", null, values);
Log.d("myDeBug", "insert");
myShow();
db.close();
name.setText(null);
age.setText(null);
}
});
updateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("age", age.getText().toString());
db.update("information", values, "name=?", new String[]{name.getText().toString()});
myShow();
db.close();
Log.d("myDebug", "update");
name.setText(null);
age.setText(null);
}
});
searchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
String name1 = name.getText().toString();
show.setText(null);
if (name1.equals("")) {
myShow();
db.close();
} else {
show.setText("项目名称");
showAge.setText("日期");
Cursor cursor = db.rawQuery("select * from information where name = ? ", new String[]{name1});
while (cursor.moveToNext()) {
String newName = cursor.getString(cursor.getColumnIndex("name"));
int newAge = cursor.getInt(cursor.getColumnIndex("age"));
// show.setText(show.getText() + "\n" + newName + "\t" + newAge);
show.setText(show.getText() + "\n" + newName);
showAge.setText(showAge.getText() + "\n" + newAge);
}
cursor.close();
db.close();
name.setText(null);
age.setText(null);
}
}
});
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("information", "name=?", new String[]{name.getText().toString()});
myShow();
db.close();
Log.d("myDeBug", "DeleteSuccess");
name.setText(null);
age.setText(null);
}
});
}
public void myShow() {
SQLiteDatabase db = dbHelper.getReadableDatabase();
show.setText("项目名称");
showAge.setText("日期");
Cursor cursor = db.rawQuery("select * from information", null);
while (cursor.moveToNext()) {
String newName = cursor.getString(cursor.getColumnIndex("name"));
int newAge = cursor.getInt(cursor.getColumnIndex("age"));
show.setText(show.getText() + "\n" + newName);
showAge.setText(showAge.getText() + "\n" + newAge);
}
cursor.close();
}










