由于这个模块内容较多,篇幅较长,请耐心阅读。
注册与登录模块分为三个部分
- 欢迎界面
- 注册界面
-
登录界面
一、欢迎界面
1、创建工程,命名为BoXueGu
,包名为com.boxuegu
。
2、导入界面图片luunch_bg.png
,导入drawable
文件夹中。
3、创建欢迎界面
(1)、欢迎界面的实现
在com.boxuegu
包下创建activity包
,在activity包下新建一个类,命名为SplashActivity
。在res/layout
下创建xml布局文件,命名为activity_splash
。
(2)、activity_splash.xml
文件代码如下:
<?xml version="1.0" encoding="utf-8"?>
<!-- match_parent:占据手机界面全部 wrap_content:占据自己的那一部分-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/launch_bg">
<!-- 设置欢迎界面背景图片 -->
<!-- 文本控件用于显示项目版本号 -->
<TextView
android:id="@+id/tv_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@android:color/white"
android:textSize="18sp"/>
</RelativeLayout>
(3)、修改清单文件(AndroidManifest.xml
)
修改为自己的icon图标,在AndroidManifest.xml的<application>
标签修改icon
属性:
<application
...... ...... ......
android:icon="@mipmap/app_icon"
...... ...... ......>
</application>
项目创建以后所有的界面都要使用自定义颜色的标题栏,所有需要在AndroidManifest.xml
的<application>
标签修改theme
属性:
<application
...... ...... ......
android:theme="@style/Theme.AppCompat.NoActionBar">
...... ...... ......
</application>
修改默认项目启动界面为欢迎界面,将AndroidManifest.xml的 <intent-filter>
及标签里面的内容剪切到SplashActivity
所在的<activity>
标签中
<activity android:name=".activity.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
4、欢迎界面逻辑代码
package com.boxuegu.activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import com.boxuegu.R;
import java.util.Timer;
import java.util.TimerTask;
/*
继承AppCompatActivity类的原因:
比继承activity类界面多了ActionBar
Android studio默认继承AppCompatActivity类
*/
public class SplashActivity extends AppCompatActivity {
private TextView tv_version; //新建tv_version成员变量
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
//设置此界面为竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
init();
}
private void init() {
//将布局文件的tv_version属性赋给成员变量tv_version
tv_version = (TextView) findViewById(R.id.tv_version);
try {
//获取程序包信息
PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
//获得版本号:AndroidManifest.xml里面的versionName
tv_version.setText("V" + info.versionName);
} catch (PackageManager.NameNotFoundException e) {
//如果获取不到版本号,控制台打印错误日志,System.err
e.printStackTrace();
//欢迎界面返回V
tv_version.setText("V");
}
//利用Timer让此界面延迟3秒后跳转,timer中有一个线程,这个线程不断执行task
Timer timer = new Timer();
//timertask实现runnable接口,TimerTask类表示一个在指定时间内执行的task
TimerTask task = new TimerTask() {
@Override
public void run() {
//欢迎界面跳转到主界面
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
SplashActivity.this.finish();
}
};
timer.schedule(task, 3000);//设置这个task在延迟3秒之后自动执行
}
}
5、欢迎界面运行效果
二、注册界面
1、制作标题栏
项目中大部分界面都有一个返回按钮和标题栏。为了便于代码重复利用,可以单独制作一个布局文件
。
(1)、创建标题栏界面
在res/layout
文件夹中,创建main_title_bar.xml
。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/title_bar"
android:layout_height="50dp"
android:background="@android:color/transparent">
<!-- 设置标题栏背景颜色为go_back_selector.xml -->
<TextView
android:id="@+id/tv_back"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@drawable/go_back_selector"/>
<!-- 设置标题栏显示字体样式 -->
<TextView
android:id="@+id/tv_main_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="20sp"
android:layout_centerInParent="true"
/>
</RelativeLayout>
(2)、创建背景选择器
标题栏中的返回按钮按下与弹起有明显的区别,可以通过背景选择器
实现。首先导入图片:iv_bavk_selected.png
(按下)、iv_back.png
(弹起)。选中drawable文件夹,新建一个xml文件。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置标题栏返回按钮背景选择器:图片和默认背景颜色图片 -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/iv_back_selected"></item>
<item android:drawable="@drawable/iv_back"></item>
</selector>
2、制作注册界面
(1)、创建注册界面
在com.boxuegu.activity
包中创建一个类,命名为RegisterActivity
。在在res/layout
文件夹中,创建activity_register.xml
(2)、导入界面图片
注册界面所需要图片:register_bg.png
(背景图片)、default_icon.png
(注册界面头像)、user_name_icon.png
(用户名图标)、psw_icon.png
(密码图标)、register_user_name_bg
(输入用户名)、register_psw_bg
(输入密码)、register_psw_again_bg
(确认密码)———导入drawable
文件夹
(3)、activity_register.xml界面代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/register_bg"
android:orientation="vertical">
<!-- 导入标题栏——main_title_bar.xml文件 -->
<include layout="@layout/main_title_bar"></include>
<!-- 注册界面头像——default_icon.png -->
<ImageView
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="25dp"
android:src="@drawable/default_icon" />
<!-- 用户名输入框 -->
<EditText
android:id="@+id/et_user_name"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"
android:layout_marginTop="35dp"
android:background="@drawable/register_user_name_bg"
android:drawableLeft="@drawable/user_name_icon"
android:drawablePadding="10dp"
android:gravity="center_vertical"
android:hint="请输入用户名"
android:paddingLeft="8dp"
android:singleLine="true"
android:textColor="#000000"
android:textColorHint="#a3a3a3"
android:textSize="14sp"/>
<!-- 密码输入框 -->
<EditText
android:id="@+id/et_psw"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"
android:background="@drawable/register_psw_bg"
android:drawableLeft="@drawable/psw_icon"
android:drawablePadding="10dp"
android:hint="请输入密码"
android:inputType="textPassword"
android:paddingLeft="8dp"
android:singleLine="true"
android:textColor="#000000"
android:textColorHint="#a3a3a3"
android:textSize="14sp"/>
<!-- 确认密码输入框 -->
<EditText
android:id="@+id/et_psw_again"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"
android:background="@drawable/register_psw_again_bg"
android:drawableLeft="@drawable/psw_icon"
android:drawablePadding="10dp"
android:hint="请再次输入密码"
android:inputType="textPassword"
android:paddingLeft="8dp"
android:singleLine="true"
android:textColor="#000000"
android:textColorHint="#a3a3a3"
android:textSize="14sp"/>
<!-- 注册按钮——使用背景选择器register_selector.xml -->
<Button
android:id="@+id/btn_register"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"
android:layout_marginTop="15dp"
android:background="@drawable/register_selector"
android:text="注 册"
android:textColor="@android:color/white"
android:textSize="18sp"/>
</LinearLayout>
(4)、创建背景选择器
注册按钮
按下与弹起有明显的区别,将图片register_icon_normal.png
(弹起)、register_icon_selected.png
(按下)导入drawable文件夹中。并在该文件夹中创建背景选择器register_selected.xml
文件。
<?xml version="1.0" encoding="utf-8"?>
<!-- 注册按钮背景选择器按下为register_icon_selected.png,弹起为register_icon_normal.png -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/register_icon_selected" android:state_pressed="true"/>
<item android:drawable="@drawable/register_icon_normal"/>
</selector>
3、MD5加密算法
MD5的全称是Message-Digest ALgorithm 5
(信息摘要算法第5版)。把任意长度的字符串变换成固定长度的十六进制字符串。注册与登录都会使用MD5加密算法对密码进行简单的加密。
选择com.boxuegu
包,创建一个utils包
(工具包),在utils包中创建一个类MD5Utils
。代码如下:
package com.boxuegu.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
//创建md5方法对密码进行加密
public static String md5(String text){
try {
//获取加密对象digest
MessageDigest digest = MessageDigest.getInstance("md5");
//digest方法对密码进行加密
byte[] result = digest.digest(text.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : result){
int number = b&0xff;
String hex = Integer.toHexString(number);
if (hex.length()==1){
sb.append("0"+hex);
}else{
sb.append(hex);
}
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return "";
}
}
}
4、注册界面逻辑代码——RegisterActivity.java
package com.boxuegu.activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.boxuegu.R;
import com.boxuegu.utils.MD5Utils;
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_rirle_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 = (TextView)findViewById(R.id.tv_main_title);
tv_main_title.setText("注册");
tv_back = (TextView)findViewById(R.id.tv_back);
rl_rirle_bar = (RelativeLayout)findViewById(R.id.title_bar);
rl_rirle_bar.setBackgroundColor(Color.TRANSPARENT);
//activity_register.xml页面布局文件获取对应的UI控件
btn_register = (Button)findViewById(R.id.btn_register);
et_user_name = (EditText) findViewById(R.id.et_user_name);
et_psw =(EditText) findViewById(R.id.et_psw);
et_psw_again = (EditText)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_LONG).show();
return;
}else if (TextUtils.isEmpty(psw)){
Toast.makeText(RegisterActivity.this,"请输入密码",Toast.LENGTH_LONG).show();
return;
}else if (TextUtils.isEmpty(pswAgain)){
Toast.makeText(RegisterActivity.this,"请再次输入密码",Toast.LENGTH_LONG).show();
return;
}else if (!psw.equals(pswAgain)){
Toast.makeText(RegisterActivity.this,"两次的密码不一样",Toast.LENGTH_LONG).show();
return;
}else if (isExistUserName(userName)){
Toast.makeText(RegisterActivity.this,"此账户名已经存在",Toast.LENGTH_LONG).show();
return;
}else {
Toast.makeText(RegisterActivity.this,"注册成功",Toast.LENGTH_LONG).show();
saveRegisterInfo(userName,psw);
Intent data = new Intent();
data.putExtra("userName",userName);
setResult(RESULT_OK,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中获取用户名,并判断此用户名是否存在
*/
private boolean isExistUserName(String userName) {
boolean has_userName = false;
SharedPreferences sp = getSharedPreferences("loginInfo",MODE_PRIVATE);
String spPwd = sp.getString(userName,"");
if (!TextUtils.isEmpty(spPwd)){
has_userName = true;
}
return has_userName;
}
/**
* 保存用户名和密码到SharedPreferences中
*/
private void saveRegisterInfo(String userName, String psw) {
//把密码用MD5加密
String md5Psw = MD5Utils.md5(psw);
//loginInfo表示文件名
SharedPreferences sp = getSharedPreferences("loginInfo",MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit(); //获取编辑器
//以用户名为key,密码为value保存到SharedPreferences
editor.putString(userName,md5Psw);
editor.apply(); //提交修改
}
}
5、修改欢迎界面代码,使欢迎界面跳转到注册界面(测试过程)
6、测试效果
三、登录界面
1、创建登录界面
在com.boxuegu.activity
包中创建一个类,命名为LoginActivity
。在res/layout
下创建一个xml文件,命名为activity_login
。
2、导入界面图片
导入drawable
文件夹:login_bg.png
(背景图片)、login_user_name_bg.png
(输入用户名)、login_psw_bg.png
(输入密码)。
3、界面代码activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/login_bg"
android:orientation="vertical">
<!-- 导入标题栏——main_title_bar.xml文件 -->
<include layout="@layout/main_title_bar" />
<!-- 登录界面头像——default_icon.png -->
<ImageView
android:id="@+id/iv_head"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_marginTop="25dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/default_icon" />
<!-- 用户名输入框 -->
<EditText
android:id="@+id/et_user_name"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_marginTop="35dp"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/login_user_name_bg"
android:drawableLeft="@drawable/user_name_icon"
android:drawablePadding="10dp"
android:paddingLeft="8dp"
android:gravity="center_vertical"
android:hint="请输入用户名"
android:singleLine="true"
android:textColor="#000000"
android:textColorHint="#a3a3a3"
android:textSize="14sp" />
<!-- 密码输入框 -->
<EditText
android:id="@+id/et_psw"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:layout_marginRight="35dp"
android:layout_marginLeft="35dp"
android:background="@drawable/login_psw_bg"
android:drawableLeft="@drawable/psw_icon"
android:drawablePadding="10dp"
android:paddingLeft="8dp"
android:hint="请输入密码"
android:inputType="textPassword"
android:singleLine="true"
android:textColor="#000000"
android:textColorHint="#a3a3a3"
android:textSize="14sp" />
<!-- 登录按钮 -->
<Button
android:id="@+id/btn_login"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:layout_marginTop="15dp"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/register_selector"
android:text="登 录"
android:textColor="@android:color/white"
android:textSize="18sp" />
<!-- 立即注册和找回密码版块 -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="8dp"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
<!-- 跳转到注册界面按钮 -->
<TextView
android:id="@+id/tv_register"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:padding="8dp"
android:text="立即注册"
android:textColor="@android:color/white"
android:textSize="14sp" />
<!-- 跳转到找回密码界面按钮 -->
<TextView
android:id="@+id/tv_find_psw"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:padding="8dp"
android:text="找回密码"
android:textColor="@android:color/white"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
4、登录界面逻辑代码——LoginActivity.java
package com.boxuegu.activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.boxuegu.R;
import com.boxuegu.utils.MD5Utils;
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() {
tv_main_title = (TextView)findViewById(R.id.tv_main_title);
tv_main_title.setText("登录");
tv_back = (TextView)findViewById(R.id.tv_back);
tv_register = (TextView)findViewById(R.id.tv_register);
tv_find_psw = (TextView)findViewById(R.id.tv_find_psw);
btn_login = (Button) findViewById(R.id.btn_login);
et_user_name = (EditText)findViewById(R.id.et_user_name);
et_psw = (EditText)findViewById(R.id.et_psw);
//返回按钮的点击事件
tv_back.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
LoginActivity.this.finish();
}
});
//立即注册控件的点击事件
tv_register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//跳转到注册界面
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 view) {
userName = et_user_name.getText().toString().trim();
psw = et_psw.getText().toString().trim();
String md5Psw = MD5Utils.md5(psw);
spPsw = readPsw(userName);
//如果用户名为空
if (TextUtils.isEmpty(userName)){
Toast.makeText(LoginActivity.this,"请输入用户名",Toast.LENGTH_LONG).show();
return;
}else if (TextUtils.isEmpty(psw)){ //如果密码为空
Toast.makeText(LoginActivity.this,"请输入密码",Toast.LENGTH_LONG).show();
return;
}else if (md5Psw.equals(spPsw)){
Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_LONG).show();
//保存登录状态和登录的用户名
saveLoginStatus(true,userName);
//把登录成功的状态传递到MainActivity中
Intent data = new Intent();
data.putExtra("isLogin",true);
data.putExtra("userName",userName);
setResult(RESULT_OK,data);
LoginActivity.this.finish();
return;
}else if (!TextUtils.isEmpty(spPsw) && !md5Psw.equals(spPsw)){
Toast.makeText(LoginActivity.this,"输入的用户名和密码不一致",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(LoginActivity.this,"此用户名不存在",Toast.LENGTH_LONG).show();
}
}
});
}
/*
* 从SharedPreferences根据用户名获取密码
*/
private String readPsw(String userName){
SharedPreferences sp = getSharedPreferences("loginInfo",MODE_PRIVATE);
return sp.getString(userName,"");
}
/*
* 保存登录状态和登录用户名到SharedPreferences中
*/
private void saveLoginStatus(boolean status, String userName) {
SharedPreferences sp = getSharedPreferences("loginInfo",MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit(); //获取编辑器
editor.putBoolean("isLogin",status);
editor.putString("loginUserName",userName); //保存登录的用户名
editor.commit(); //提交修改
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data!=null){
//从注册界面传递过来的用户名
String userName = data.getStringExtra("userName");
if (!TextUtils.isEmpty(userName)){
et_user_name.setText(userName);
//设置光标的位置
et_user_name.setSelection(userName.length());
}
}
}
}