实 验 报 告
课程名称
实验名称
指导教师
专业
班级
学号
姓名
一、需求分析
1.需求分析
随着互联网和手机技术的蓬勃发展,网购已经成为许多人,尤其是年轻人的主要消费方式,这就对手机购物APP产生了大量的需求,商品的展示环节更是尤为重要的额一环。本次实验制作了一款鞋子商品展示的APP,包括了鞋子商品的品牌,图片,文字和视频介绍。让消费者直观看到鞋子的各方面信息。同时采用登入注册功能,来保护消费者信息。
- 技术原理
(1)页面布局:使用线性布局并用ScrollView实现页面上下滑动。
(2)数据库:SharedPreferences是Android平台,上一个轻量级的存储类,用来保存应用的一些常用配置,比如Activity状态,Activity 暂停时,将此actity的状态保存到SharedPereferences中;当Activity重载,系统回调方法onSavelnstanceState时,再从SharedPreferences中将值取出。
(3)MD5加密算法:①一致性检验,最.上面那个例子②数字签名,还是最上面那个例子。只是把md5看出了一个指纹,按了个手印说明独一无二了。③安全访问认证,这个就是平时系统设计的问题了。
在用户注册时,会将密码进行md5加密,存到数据库中。这样可以防止那些可以看到数据库数据的人,恶意操作了。
(4)控件的使用:Textview 、Edittext、Button、ImageView 等
- 详细设计
主页面:首页面是一个进入软件的页面,包括一个打开软件的按钮。
登录页面:登陆页面包含了三个按钮,左上方按钮。可以返回上一级。登陆按钮可以进行的登陆功能注册按钮可以跳转到注册页面。页面包含了两个文本框,分别可以输入用户名和密码。输入的用户名和密码会进行核对。如果用户名不存在,点击登陆按钮会提示用户不存在。如果密码输入错误,点击登录按钮会提示密码输入错误。
注册页面:注册页面一共包括两个按钮,左上角还是返回上一级。注册按钮可以进行账户注册的功能。注册页面包含三个文本框。分别是输入用户名,输入密码和第二次输入密码。输输入的密码会进行加密储存在SharedPreferences中。当两次密码输入不一致时,点击注册按钮会提示两次密码输入不一致。如果用户名已经注册过,点击注册按钮会提示用户名已存在。注册成功后,点击注册按钮就会跳转到登录页面,并把注册的用户名传输到登入页面上。
分类页面:分类页面一共包含三个按钮,左上角的返回按钮可以返回到上一级。剩下两个按钮为鞋子的品牌分类按钮起到一个导航的作用,可以清晰直观的看到鞋子的分类。点击分类按钮后,可以跳转到相应的品牌鞋子的图片和文字介绍页面。
子页面:商品子页面包含两个按钮,左上角是返回上一级。查看视频按钮,可以进入到视频播放页面观看这个鞋子的详细视频介绍。整体采用线性布局,包含上方热卖商品鞋子的线性布局和下方全部鞋子的滑动布局。
播放视频页面:视频播放页面包含三个按钮,左上角按钮可以返回商品此页面视频下方两个按钮分别为开始按钮和结束按钮,可以控制视频的播放和结束。 - 系统实现和使用说明
- 系统实现
(1)登入实现
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();
}
}
});
}
/**
*从SharedPreferences中根据用户名读取密码
*/
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 , "");
}
/**
*保存登录状态和登录用户名到SharedPreferences中
*/
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());
}
}
}}
(2)注册实现
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;
}
/**
* 保存账号和密码到SharedPreferences中SharedPreferences
*/
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();
}
} - 使用说明
图1 进入界面
图2 登录界面
图3 注册界面
图4 登陆成功主界面
图5 子界面
图6 商品视频界面
(4)点击返回键,跳转回上一界面。
- 系统测试
进入登录界面,点击“登录”,显示登陆成功
五、总结
随着互联网的发展,互联网广泛的被应用在人们的生活中,UI设计也越来越被需要,本次实验的要求就是关于UI设计以及多用户界面切换功能的实现,想要完成一个好的界面设计,必须要大量的看好的作品提升自己。在实验中我也遇到了一些问题,比如常见的activity忘记注册以及一些细微的错误就可能导致程序运行错误而这些问题只有在自己实际的操作中才能体会并解决,然后牢牢的记住这些问题,而且我们必须明白一个色彩绚丽的界面不仅不能增加美感还会给用户操作带来不便,设计成功的界面是简洁的而且要逻辑合理我们可以站在客户的角度上去进行设计。而在android开发过程中,界面切换是我们必须要掌握的,界面切换是指从一个activity跳转到另一个activity,实现界面之间的跳转和数据传递,这是开发过程中非常重要的一部分。通过本次实验,我在编程方面有很大的收获,了解到了自己存在的不足,但是也对基本的开发过程有了一定的了解,以后一定会在编程上多下功夫。
购买须知
- 1. 【服务提示】广州思坞信息科技有限公司、广州沐思信息科技有限公司(以下称“千聊”)系提供技术支持的网络服务提供者,千聊平台内相关商品的信息内容制作、发布等均由知识店铺独立完成,千聊不事先审核。
- 2. 【交易主体】请您了解,您在千聊平台购买的数字化商品均系由商品页面上标示的知识店铺为您提供,千聊并非数字化商品的提供者和销售者。您一旦支付费用购买千聊平台上知识店铺提供的相关数字化商品,即与提供数字化商品的知识店铺建立合同关系,千聊不构成该合同关系的任一方,相关权利义务均归属于您与知识店铺之间(如课程收益、开票义务、产品安全保障义务归知识店铺),若您需要开票,请您联系知识店铺申请开具发票。
- 3. 知识店铺课程为付费课程的,按课程计划定期更新,每节课程可在开课时学习,也可反复回听。千聊平台上提供的课程、会员等在线商品为数字化商品,根据《消费者权益保护法》等规定,不适用七日无理由退货规定(您与数字化商品提供者达成退款合意的除外),请您于购买时谨慎考虑。
- 4. 购买在线商品后关注我们的服务号,可在菜单里进入听课。
- 5. 该课程听课权益跟随支付购买微信账号ID,不支持更换(赠礼课程除外)。
- 6. 如有其它疑问,可点击右下角“更多”按钮后选择“咨询”,与内容供应商知识店铺沟通后再购买。
- 7. 【退款方式】您的退款申请符合千聊平台规则情形的,该笔退款金额将原路退回您的账户,但若因退款产生第三方支付平台手续费的,将在扣除该手续费后退回剩余款项。
- 8. 该作品版权归原作者所有,禁止任何形式的商业使用(含翻录、传播等侵权行为),违反者将依法承担法律责任。
价格说明
- 1. 划线价格:指商品的正品零售价、知识店铺指导价或该商品的曾经展示过的销售价等,并非原价,仅供参考。
- 2. 未划线价格:指商品的实时标价,不因表述的差异改变性质。具体成交价格根据商品参加活动,或会员使用优惠券等发生变化,最终以订单结算页价格为准。
- 3. 老师/知识店铺课程介绍页(含主图)以图片或文字形式标注的一口价、促销价、优惠价、拼团价、限时特价等价格可能是在使用优惠券或特定优惠活动和时段等情形下的价格,具体请以结算页面的标价、优惠条件或活动规则为准。
- 4. 此说明仅当出现价格比较时有效,具体请参见《千聊价格发布规范》。若老师/知识店铺单独对划线价格进行说明,以老师/知识店铺的表述为准。