16. “我”模块(一)之登录

上一节对欢迎模块进行了综述(可参见 10. 视频模块 进行了解),接下来将从视频模块开始详细介绍:

  • [“我”模块(一)之创建数据库]
  • [“我”模块(一)之“我”]
  • [“我”模块(一)之注册]
  • [“我”模块(一)之登录]
  • [“我”模块(一)之个人资料]
  • [“我”模块(一)之个人资料修改]

知识点

  • 掌握SQLite数据库的使用,能够使用数据库存储用户信息。
  • 掌握“我”界面开发,能够展示用户基本信息以及该界面的功能。
  • 掌握“登录”“注册”界面的开发,实现用户登录注册功能。
  • 掌握“个人资料”以及“修改”界面的开发,实现用户信息的展示与修改功能。

登录

任务综述:
“登录”界面主要是为用户提供一个输入登录信息的界面,当点击“登录”按钮时,需要在SharedPreferences中查询输入的用户名是否有对应的密码,如果有,则用此密码与当前输入的密码(需MD5加密)进行比对,如果信息一致,则登录成功,并把登陆成功的状态和用户名保存到SharedPreferences中,便于后续判断登录状态和获取用户名。如果登录失败,则有两种情况,一种是输入的用户名和密码不一致,另一种是此用户名不存在。

7. “登录”界面

任务分析:
“登录”界面主要是为了用户提供一个登录的入口,若用户还未注册,则可以点击“快速注册”按钮进入注册界面;若用户忘记密码,则可以点击“忘记密码?”按钮进入“找回密码”界面(“找回密码”界面暂未创建)。界面效果如图所示。

16. “我”模块(一)之登录
“登录”界面

任务实施:
(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);