上一节对欢迎模块进行了综述(可参见 10. 视频模块 进行了解),接下来将从视频模块开始详细介绍:
- [“我”模块(一)之创建数据库]
- [“我”模块(一)之“我”]
- [“我”模块(一)之注册]
- [“我”模块(一)之登录]
- [“我”模块(一)之个人资料]
- [“我”模块(一)之个人资料修改]
知识点
- 掌握SQLite数据库的使用,能够使用数据库存储用户信息。
- 掌握“我”界面开发,能够展示用户基本信息以及该界面的功能。
- 掌握“登录”“注册”界面的开发,实现用户登录注册功能。
- 掌握“个人资料”以及“修改”界面的开发,实现用户信息的展示与修改功能。
登录
任务综述:
“登录”界面主要是为用户提供一个输入登录信息的界面,当点击“登录”按钮时,需要在SharedPreferences中查询输入的用户名是否有对应的密码,如果有,则用此密码与当前输入的密码(需MD5加密)进行比对,如果信息一致,则登录成功,并把登陆成功的状态和用户名保存到SharedPreferences中,便于后续判断登录状态和获取用户名。如果登录失败,则有两种情况,一种是输入的用户名和密码不一致,另一种是此用户名不存在。
7. “登录”界面
任务分析:
“登录”界面主要是为了用户提供一个登录的入口,若用户还未注册,则可以点击“快速注册”按钮进入注册界面;若用户忘记密码,则可以点击“忘记密码?”按钮进入“找回密码”界面(“找回密码”界面暂未创建)。界面效果如图所示。
任务实施:
(1)创建“登录”界面:LoginActivity&activity_login。在该布局文件中,通过<include>标签将main_title_bar.xml(标题栏)引入。
(2)放置界面控件。
一个ImageViewRoundOval控件,用于显示用户默认头像;
两个EditText控件,分别用户输入用户名和密码;
一个Button控件,作为登录按钮(和注册按钮使用同一个背景选择器);
两个TextView控件,分别用于显示文字“快速注册”和“忘记密码?”。
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/register_bg_color"
android:orientation="vertical">
<include layout="@layout/main_title_bar" />
<com.itheima.topline.view.ImageViewRoundOval
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="25dp"
android:layout_marginTop="35dp"
android:scaleType="fitXY"
android:src="@drawable/default_head" />
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
app:cardCornerRadius="5dp"
app:cardElevation="3dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/et_user_name"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/register_edittext_top_radius"
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="@color/register_hint_text_color"
android:textCursorDrawable="@null"
android:textSize="14sp" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="@color/divider_line_color" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="@+id/et_psw"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal"
android:background="@drawable/register_edittext_bottom_radius"
android:drawableLeft="@drawable/psw_icon"
android:drawablePadding="10dp"
android:hint="请输入密码"
android:inputType="textPassword"
android:paddingLeft="8dp"
android:singleLine="true"
android:textColor="#000000"
android:textColorHint="@color/register_hint_text_color"
android:textCursorDrawable="@null"
android:textSize="14sp" />
<ImageView
android:id="@+id/iv_show_psw"
android:layout_width="15dp"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="8dp"
android:src="@drawable/hide_psw_icon" />
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_quick_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="快速注册"
android:textColor="@color/register_hint_text_color"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_forget_psw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="忘记密码?"
android:textColor="@color/register_hint_text_color"
android:textSize="12sp" />
</LinearLayout>
<Button
android:id="@+id/btn_login"
android:layout_width="fill_parent"
android:layout_height="35dp"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginTop="15dp"
android:background="@drawable/register_btn_selector"
android:text="登 录"
android:textColor="@android:color/white"
android:textSize="18sp" />
</LinearLayout>
"登录"界面逻辑代码
任务分析:
当点击“登录”按钮时,需要先判断用户名和密码是否为空,若为空,则提示“请输入用户名和密码”;若不为空,则获取用户输入的用户名。由于头条项目、注册数据使用的是本地数据,因此需要根据用户输入的用户名在SharedPreferences中查询是否有对应 的密码,如果有对应的密码且密码与用户输入的密码(需MD5加密)比对一致,则登录成功。
任务实施:
(1)获取界面控件。在LoginActivity()中创建界面控件的初始化方法init(),用于获取“登录”界面所要用到的控件并设置登录按钮、返回键、快速注册、忘记密码的点击事件。
(2)获取回传数据。在LoginActivity中重写onActivityResult()方法,通过data.getStringExtra()方法获取注册成功的用户名,并将其显示在用户名控件上。
(3)保存登录状态到SharedPreferences中。由于在后续创建“我”界面时,需要根据登录状态设置界面的图标和用户名,因此需要创建saveLoginStatus()方法,在登录成功时把登录状态和用户名保存到SharedPreferences中。
LoginActivity.java
public class LoginActivity extends AppCompatActivity implements View.OnClickListener{
private EditText et_psw,et_user_name;
private TextView tv_quick_register,tv_forget_psw;
private ImageView iv_show_psw;
private Button btn_login;
private boolean isShowPsw=false;
private String userName,psw,spPsw;
private TextView tv_main_title,tv_back;
private RelativeLayout rl_title_bar;
private SwipeBackLayout layout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = (SwipeBackLayout) LayoutInflater.from(this).inflate(
R.layout.base, null);
layout.attachToActivity(this);
setContentView(R.layout.activity_login);
init();
}
private void init(){
tv_main_title= (TextView)findViewById(R.id.tv_main_title);
tv_main_title.setText("登录");
rl_title_bar= (RelativeLayout)findViewById(R.id.title_bar);
rl_title_bar.setBackgroundColor(getResources().getColor(R.color.
rdTextColorPress));
tv_back= (TextView) findViewById(R.id.tv_back);
tv_back.setVisibility(View.VISIBLE);
et_user_name= (EditText) findViewById(R.id.et_user_name);
et_psw= (EditText) findViewById(R.id.et_psw);
iv_show_psw= (ImageView) findViewById(R.id.iv_show_psw);
tv_quick_register= (TextView) findViewById(R.id.tv_quick_register);
tv_forget_psw= (TextView) findViewById(R.id.tv_forget_psw);
btn_login= (Button) findViewById(R.id.btn_login);
tv_back.setOnClickListener(this);
iv_show_psw.setOnClickListener(this);
tv_quick_register.setOnClickListener(this);
tv_forget_psw.setOnClickListener(this);
btn_login.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.tv_back:
LoginActivity.this.finish();
break;
case R.id.iv_show_psw:
psw=et_psw.getText().toString();
if(isShowPsw){
iv_show_psw.setImageResource(R.drawable.hide_psw_icon);
//隐藏密码
et_psw.setTransformationMethod(PasswordTransformationMethod.
getInstance());
isShowPsw=false;
if(psw!=null){
et_psw.setSelection(psw.length());
}
}else{
iv_show_psw.setImageResource(R.drawable.show_psw_icon);
//显示密码
et_psw.setTransformationMethod(HideReturnsTransformationMethod.
getInstance());
isShowPsw=true;
if(psw!=null){
et_psw.setSelection(psw.length());
}
}
break;
case R.id.btn_login:
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_SHORT).show();
return;
}else if(TextUtils.isEmpty(psw)){
Toast.makeText(LoginActivity.this, "请输入密码",
Toast.LENGTH_SHORT).show();
return;
}else if(md5Psw.equals(spPsw)){
Toast.makeText(LoginActivity.this, "登录成功",
Toast.LENGTH_SHORT).show();
//保存登录状态和登录的用户名
saveLoginStatus(true,userName);
//把登录成功的状态传递到MainActivity中
Intent data=new Intent();
data.putExtra("isLogin", true);
setResult(RESULT_OK, data);
LoginActivity.this.finish();
return;
}else if((!TextUtils.isEmpty(spPsw)&&!md5Psw.equals(spPsw))){
Toast.makeText(LoginActivity.this, "输入的用户名和密码不一致",
Toast.LENGTH_SHORT).show();
return;
}else{
Toast.makeText(LoginActivity.this, "此用户名不存在",
Toast.LENGTH_SHORT).show();
}
break;
case R.id.tv_quick_register:
Intent intent=new Intent(LoginActivity.this,RegisterActivity.class);
startActivityForResult(intent,1);
break;
case R.id.tv_forget_psw:
Intent forget=new Intent(LoginActivity.this,FindPswActivity.class);
startActivity(forget);
break;
}
}
/**
*从SharedPreferences中根据用户名读取密码
*/
private String readPsw(String userName){
SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
return sp.getString(userName, "");
}
/**
*保存登录状态和登录用户名到SharedPreferences中
*/
private void saveLoginStatus(boolean status,String userName){
//loginInfo表示文件名
SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
SharedPreferences.Editor editor=sp.edit(); //获取编辑器
editor.putBoolean("isLogin", status); //存入boolean类型的登录状态
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());
}
}
}
}
(4)修改清单文件。“登录”界面向右滑动会关闭该界面,因此需要给该界面添加透明主题的样式。
<activity
android:name=".activity.LoginActivity"
android:theme="@style/AppTheme.TransparentActivity" />
(5)修改MeFragment.java文件。当用户未登录时,点击“我”界面中的头像会跳转到“登录”界面,因此需要找到其中的onClick()方法,在该方法的注释“//跳转到‘登录’界面”下方添加如下代码:
//跳转到登录界面
Intent login = new Intent(getActivity(), LoginActivity.class);
startActivityForResult(login, 1);