界面
activity_login.xml文件:
1 <?xml version="1.0" encoding="utf-8"?> 2 <!-- 3 这里把整个Activity_login的布局设置成相对布局, 4 因为相对布局比较灵活,想咋放咋放 5 看代码,上来就是三个 xmlns,xml这仨字母认识,ns这俩字母是namespace的缩写 6 正是有了这些namespace的声明,才能在不同的xml中使用相同的id名, 7 而不会造成使用时的冲突 8 --> 9 <RelativeLayout 10 xmlns:android="http://schemas.android.com/apk/res/android" 11 xmlns:app="http://schemas.android.com/apk/res-auto" 12 xmlns:tools="http://schemas.android.com/tools" 13 android:layout_width="match_parent" 14 android:layout_height="match_parent" 15 android:background="#eeeeee" 16 tools:context=".loginActivity"> 17 <!-- 18 整体是相对布局, 19 在整体上方放三个东西,这三个东西也是相对布局 20 合在一起称为一个top 21 一个返回箭头 ← 22 两个文字显示 登录 注册 23 也就是说 login界面的上方长这个样子 24 ← 登录 注册 25 下面是具体代码 26 --> 27 <RelativeLayout 28 android:id="@+id/rl_loginactivity_top" 29 android:layout_width="match_parent" 30 android:layout_height="70dp" 31 android:background="@color/color_minefragment_top" > 32 <ImageView 33 android:id="@+id/iv_loginactivity_back" 34 android:layout_width="30dp" 35 android:layout_height="30dp" 36 android:background="@drawable/ic_left_back" 37 android:layout_centerVertical="true" 38 android:layout_marginLeft="10dp" 39 android:clickable="true" 40 android:onClick="onClick" 41 /> 42 43 <TextView 44 android:id="@+id/tv_loginactivity_login" 45 android:layout_width="wrap_content" 46 android:layout_height="wrap_content" 47 android:text="登录" 48 android:textColor="#fff" 49 android:textSize="20dp" 50 android:layout_toRightOf="@+id/iv_loginactivity_back" 51 android:layout_centerVertical="true" 52 android:layout_marginLeft="20dp" 53 /> 54 <TextView 55 android:id="@+id/tv_loginactivity_register" 56 android:layout_width="wrap_content" 57 android:layout_height="wrap_content" 58 android:text="注册" 59 android:textColor="#fff" 60 android:textSize="20dp" 61 android:layout_centerVertical="true" 62 android:layout_alignParentRight="true" 63 android:layout_marginRight="30dp" 64 android:clickable="true" 65 android:onClick="onClick" 66 /> 67 </RelativeLayout> 68 <!-- 69 顶部三个东西摆放好之后 70 就该来摆放登录时候的两个文本输入框了 71 用户名 72 密码 73 这个明显的是LinerLayout 74 LinerLayout必须指明orientation 方向 要么垂直vertical 要么水平 horizontal 75 这里显然是垂直vertical 76 --> 77 <LinearLayout 78 android:id="@+id/ll_loginactivity_two" 79 android:layout_width="match_parent" 80 android:layout_height="wrap_content" 81 android:orientation="vertical" 82 android:layout_below="@+id/rl_loginactivity_top" 83 android:layout_marginTop="10dp" 84 android:layout_marginLeft="5dp" 85 android:layout_marginRight="5dp" 86 > 87 <LinearLayout 88 android:layout_width="match_parent" 89 android:layout_height="wrap_content" 90 android:orientation="horizontal"> 91 <TextView 92 android:id="@+id/tv_loginactivity_username" 93 android:layout_width="wrap_content" 94 android:layout_height="wrap_content" 95 android:text="用户名:"/> 96 <EditText 97 android:id="@+id/et_loginactivity_username" 98 android:layout_width="match_parent" 99 android:layout_height="wrap_content" 100 android:hint="手机号/邮箱/用户名"/> 101 </LinearLayout> 102 <LinearLayout 103 android:layout_width="match_parent" 104 android:layout_height="wrap_content" 105 android:orientation="horizontal"> 106 <TextView 107 android:id="@+id/tv_loginactivity_password" 108 android:layout_width="wrap_content" 109 android:layout_height="wrap_content" 110 android:text="密 码:"/> 111 <EditText 112 android:id="@+id/et_loginactivity_password" 113 android:layout_width="match_parent" 114 android:layout_height="wrap_content" 115 android:hint="登录密码" 116 android:inputType="textPassword"/> 117 </LinearLayout> 118 </LinearLayout> 119 <!-- 120 填好用户名、密码后,就该点击登录按钮了 121 注意最后有一句: android:onClick="onClick" 122 这是应用了一个开源库,详细信息在loginActivity.java 中有注释 123 --> 124 <Button 125 android:id="@+id/bt_loginactivity_login" 126 android:layout_width="match_parent" 127 android:layout_height="wrap_content" 128 android:layout_below="@+id/ll_loginactivity_two" 129 android:layout_marginTop="10dp" 130 android:layout_marginLeft="5dp" 131 android:layout_marginRight="5dp" 132 android:background="@drawable/selector_loginactivity_button" 133 android:text="登录" 134 android:textColor="#fff" 135 android:gravity="center" 136 android:onClick="onClick" 137 /> 138 <!-- 139 为了App的人性化, 140 想到有以下三种无法密码登录的异常处理情况 141 一、密码错误,重新输入 142 二、忘记密码,重新修改密码 143 三、不想注册,通过短信验证登录 144 密码输错了,重新输入,这个没啥说的 145 忘记密码应该以一个可以点击的文字出现在登录按钮的左下方 146 短信验证登录也以一个可以点击的文字出现在登录按钮的右下方 147 --> 148 <TextView 149 android:id="@+id/tv_loginactivity_forget" 150 android:text="忘记密码" 151 android:textColor="#f00" 152 android:layout_width="wrap_content" 153 android:layout_height="wrap_content" 154 android:layout_marginLeft="50dp" 155 android:layout_marginVertical="50dp" 156 android:layout_below="@+id/bt_loginactivity_login" 157 android:layout_alignLeft="@+id/bt_loginactivity_login" 158 /> 159 <TextView 160 android:id="@+id/tv_loginactivity_check" 161 android:layout_width="wrap_content" 162 android:layout_height="wrap_content" 163 android:text="短信验证码登录" 164 android:textColor="#f00" 165 android:layout_marginRight="50dp" 166 android:layout_marginVertical="50dp" 167 android:layout_below="@+id/bt_loginactivity_login" 168 android:layout_alignRight="@+id/bt_loginactivity_login" 169 /> 170 <!-- 171 当然,QQ、微信、微博、GitHub...在当今如此火热 172 登录的时候完全可以免注册 173 直接使用第三方登录 174 --> 175 <TextView 176 android:id="@+id/tv_loginactivity_else" 177 android:layout_width="wrap_content" 178 android:layout_height="wrap_content" 179 android:layout_below="@+id/tv_loginactivity_forget" 180 android:layout_centerInParent="true" 181 android:layout_marginVertical="30dp" 182 183 android:text="---------------------------第三方登录---------------------------" 184 android:textColor="#B3B3B3" 185 android:gravity="center" 186 /> 187 </RelativeLayout>
界面效果:

登录功能的loginActivity文件
1 package com.example.justloginregistertest;
2 /**
3 * 纯粹实现登录注册功能,其它功能都被注释掉了
4 * 起作用的代码(连带着packag、import算上) 共 73 行
5 * 不多吧?
6 */
7
8 import android.content.Intent;
9 import android.os.Bundle;
10 import android.text.TextUtils;
11 import android.view.View;
12 import android.widget.Button;
13 import android.widget.EditText;
14 import android.widget.LinearLayout;
15 import android.widget.RelativeLayout;
16 import android.widget.TextView;
17 import android.widget.Toast;
18
19 import androidx.appcompat.app.AppCompatActivity;
20
21 import java.util.ArrayList;
22 /**
23 * Created by littlecurl 2018/6/24
24 */
25
26 /**
27 * 此类 implements View.OnClickListener 之后,
28 * 就可以把onClick事件写到onCreate()方法之外
29 * 这样,onCreate()方法中的代码就不会显得很冗余
30 */
31 public class loginActivity extends AppCompatActivity implements View.OnClickListener {
32 /**
33 * 声明自己写的 DBOpenHelper 对象
34 * DBOpenHelper(extends SQLiteOpenHelper) 主要用来
35 * 创建数据表
36 * 然后再进行数据表的增、删、改、查操作
37 */
38 private DBOpenHelper mDBOpenHelper;
39 private TextView mTvLoginactivityRegister;
40 private RelativeLayout mRlLoginactivityTop;
41 private EditText mEtLoginactivityUsername;
42 private EditText mEtLoginactivityPassword;
43 private LinearLayout mLlLoginactivityTwo;
44 private Button mBtLoginactivityLogin;
45
46 /**
47 * 创建 Activity 时先来重写 onCreate() 方法
48 * 保存实例状态
49 * super.onCreate(savedInstanceState);
50 * 设置视图内容的配置文件
51 * setContentView(R.layout.activity_login);
52 * 上面这行代码真正实现了把视图层 View 也就是 layout 的内容放到 Activity 中进行显示
53 * 初始化视图中的控件对象 initView()
54 * 实例化 DBOpenHelper,待会进行登录验证的时候要用来进行数据查询
55 * mDBOpenHelper = new DBOpenHelper(this);
56 */
57 @Override
58 protected void onCreate(Bundle savedInstanceState) {
59 super.onCreate(savedInstanceState);
60 setContentView(R.layout.activity_login);
61
62 initView();
63
64 mDBOpenHelper = new DBOpenHelper(this);
65 }
66
67 /**
68 * onCreae()中大的布局已经摆放好了,接下来就该把layout里的东西
69 * 声明、实例化对象然后有行为的赋予其行为
70 * 这样就可以把视图层View也就是layout 与 控制层 Java 结合起来了
71 */
72 private void initView() {
73 // 初始化控件
74 mBtLoginactivityLogin = findViewById(R.id.bt_loginactivity_login);
75 mTvLoginactivityRegister = findViewById(R.id.tv_loginactivity_register);
76 mRlLoginactivityTop = findViewById(R.id.rl_loginactivity_top);
77 mEtLoginactivityUsername = findViewById(R.id.et_loginactivity_username);
78 mEtLoginactivityPassword = findViewById(R.id.et_loginactivity_password);
79 mLlLoginactivityTwo = findViewById(R.id.ll_loginactivity_two);
80
81 // 设置点击事件监听器
82 mBtLoginactivityLogin.setOnClickListener(this);
83 mTvLoginactivityRegister.setOnClickListener(this);
84 }
85
86 public void onClick(View view) {
87 switch (view.getId()) {
88 // 跳转到注册界面
89 case R.id.tv_loginactivity_register:
90 startActivity(new Intent(this, RegisterActivity.class));
91 finish();
92 break;
93 /**
94 * 登录验证:
95 *
96 * 从EditText的对象上获取文本编辑框输入的数据,并把左右两边的空格去掉
97 * String name = mEtLoginactivityUsername.getText().toString().trim();
98 * String password = mEtLoginactivityPassword.getText().toString().trim();
99 * 进行匹配验证,先判断一下用户名密码是否为空,
100 * if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(password))
101 * 再进而for循环判断是否与数据库中的数据相匹配
102 * if (name.equals(user.getName()) && password.equals(user.getPassword()))
103 * 一旦匹配,立即将match = true;break;
104 * 否则 一直匹配到结束 match = false;
105 *
106 * 登录成功之后,进行页面跳转:
107 *
108 * Intent intent = new Intent(this, MainActivity.class);
109 * startActivity(intent);
110 * finish();//销毁此Activity
111 */
112 case R.id.bt_loginactivity_login:
113 String name = mEtLoginactivityUsername.getText().toString().trim();
114 String password = mEtLoginactivityPassword.getText().toString().trim();
115 if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(password)) {
116 ArrayList<User> data = mDBOpenHelper.getAllData();
117 boolean match = false;
118 for (int i = 0; i < data.size(); i++) {
119 User user = data.get(i);
120 if (name.equals(user.getName()) && password.equals(user.getPassword())) {
121 match = true;
122 break;
123 } else {
124 match = false;
125 }
126 }
127 if (match) {
128 Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
129 Intent intent = new Intent(this, MainActivity.class);
130 startActivity(intent);
131 finish();//销毁此Activity
132 } else {
133 Toast.makeText(this, "用户名或密码不正确,请重新输入", Toast.LENGTH_SHORT).show();
134 }
135 } else {
136 Toast.makeText(this, "请输入你的用户名或密码", Toast.LENGTH_SHORT).show();
137 }
138 break;
139 }
140 }
141 }
登录功能的user文件
1 package com.example.justloginregistertest;
2 /**
3 * Created by littlecurl 2018/6/24
4 */
5 public class User {
6 private String name; //用户名
7 private String password; //密码
8 public User(String name, String password) {
9 this.name = name;
10 this.password = password;
11 }
12 public String getName() {
13 return name;
14 }
15 public void setName(String name) {
16 this.name = name;
17 }
18 public String getPassword() {
19 return password;
20 }
21 public void setPassword(String password) {
22 this.password = password;
23 }
24 }
连接数据库的DBOpenHelper文件
1 package com.example.justloginregistertest;
2
3 import android.content.Context;
4 import android.database.Cursor;
5 import android.database.sqlite.SQLiteDatabase;
6 import android.database.sqlite.SQLiteOpenHelper;
7
8 import java.util.ArrayList;
9 /**
10 * Created by littlecurl 2018/6/24
11 */
12
13 public class DBOpenHelper extends SQLiteOpenHelper {
14 /**
15 * 声明一个AndroidSDK自带的数据库变量db
16 */
17 private SQLiteDatabase db;
18
19 /**
20 * 写一个这个类的构造函数,参数为上下文context,所谓上下文就是这个类所在包的路径
21 * 指明上下文,数据库名,工厂默认空值,版本号默认从1开始
22 * super(context,"db_test",null,1);
23 * 把数据库设置成可写入状态,除非内存已满,那时候会自动设置为只读模式
24 * 不过,以现如今的内存容量,估计一辈子也见不到几次内存占满的状态
25 * db = getReadableDatabase();
26 */
27 public DBOpenHelper(Context context){
28 super(context,"db_test",null,1);
29 db = getReadableDatabase();
30 }
31
32 /**
33 * 重写两个必须要重写的方法,因为class DBOpenHelper extends SQLiteOpenHelper
34 * 而这两个方法是 abstract 类 SQLiteOpenHelper 中声明的 abstract 方法
35 * 所以必须在子类 DBOpenHelper 中重写 abstract 方法
36 * 想想也是,为啥规定这么死必须重写?
37 * 因为,一个数据库表,首先是要被创建的,然后免不了是要进行增删改操作的
38 * 所以就有onCreate()、onUpgrade()两个方法
39 * @param db
40 */
41 @Override
42 public void onCreate(SQLiteDatabase db){
43 db.execSQL("CREATE TABLE IF NOT EXISTS user(" +
44 "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
45 "name TEXT," +
46 "password TEXT)");
47 }
48 @Override
49 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
50 db.execSQL("DROP TABLE IF EXISTS user");
51 onCreate(db);
52 }
53 /**
54 * 接下来写自定义的增删改查方法
55 * 这些方法,写在这里归写在这里,以后不一定都用
56 * add()
57 * delete()
58 * update()
59 * getAllData()
60 */
61 public void add(String name,String password){
62 db.execSQL("INSERT INTO user (name,password) VALUES(?,?)",new Object[]{name,password});
63 }
64 public void delete(String name,String password){
65 db.execSQL("DELETE FROM user WHERE name = AND password ="+name+password);
66 }
67 public void updata(String password){
68 db.execSQL("UPDATE user SET password = ?",new Object[]{password});
69 }
70
71 /**
72 * 前三个没啥说的,都是一套的看懂一个其他的都能懂了
73 * 下面重点说一下查询表user全部内容的方法
74 * 我们查询出来的内容,需要有个容器存放,以供使用,
75 * 所以定义了一个ArrayList类的list
76 * 有了容器,接下来就该从表中查询数据了,
77 * 这里使用游标Cursor,这就是数据库的功底了,
78 * 在Android中我就不细说了,因为我数据库功底也不是很厚,
79 * 但我知道,如果需要用Cursor的话,第一个参数:"表名",中间5个:null,
80 * 最后是查询出来内容的排序方式:"name DESC"
81 * 游标定义好了,接下来写一个while循环,让游标从表头游到表尾
82 * 在游的过程中把游出来的数据存放到list容器中
83 * @return
84 */
85 public ArrayList<User> getAllData(){
86
87 ArrayList<User> list = new ArrayList<User>();
88 Cursor cursor = db.query("user",null,null,null,null,null,"name DESC");
89 while(cursor.moveToNext()){
90 String name = cursor.getString(cursor.getColumnIndex("name"));
91 String password = cursor.getString(cursor.getColumnIndex("password"));
92 list.add(new User(name,password));
93 }
94 return list;
95 }
96 }
浙公网安备 33010602011771号