demo下载:https://github.com/chaoyu168/LoginDemo
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import com.xiaobai.cloneapp.R;
import com.xiaobai.cloneapp.utils.Base64Utils;
import com.xiaobai.cloneapp.utils.SharedPreferencesUtils;
public class LoginActivity extends Activity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener{
//布局内的控件
private EditText et_name;
private EditText et_password;
private Button mLoginBtn;
private CheckBox checkBox_password;
private CheckBox checkBox_login;
private ImageView iv_see_password;
private LoadingDialog mLoadingDialog; //显示正在加载的对话框
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_main);
initViews();
setupEvents();
initData();
}
private void initData() {
//判断用户第一次登陆
if (firstLogin()) {
checkBox_password.setChecked(false);//取消记住密码的复选框
checkBox_login.setChecked(false);//取消自动登录的复选框
}
//判断是否记住密码
if (remenberPassword()) {
checkBox_password.setChecked(true);//勾选记住密码
setTextNameAndPassword();//把密码和账号输入到输入框中
} else {
setTextName();//把用户账号放到输入账号的输入框中
}
//判断是否自动登录
if (autoLogin()) {
checkBox_login.setChecked(true);
login();//去登录就可以
}
}
/**
* 把本地保存的数据设置数据到输入框中
*/
public void setTextNameAndPassword() {
et_name.setText("" + getLocalName());
et_password.setText("" + getLocalPassword());
}
/**
* 设置数据到输入框中
*/
public void setTextName() {
et_name.setText("" + getLocalName());
}
/**
* 获得保存在本地的用户名
*/
public String getLocalName() {
//获取SharedPreferences对象,使用自定义类的方法来获取对象
SharedPreferencesUtils helper = new SharedPreferencesUtils(this, "setting");
String name = helper.getString("name");
return name;
}
/**
* 获得保存在本地的密码
*/
public String getLocalPassword() {
//获取SharedPreferences对象,使用自定义类的方法来获取对象
SharedPreferencesUtils helper = new SharedPreferencesUtils(this, "setting");
String password = helper.getString("password");
return Base64Utils.decryptBASE64(password); //解码一下
// return password; //解码一下
}
/**
* 判断是否自动登录
*/
private boolean autoLogin() {
//获取SharedPreferences对象,使用自定义类的方法来获取对象
SharedPreferencesUtils helper = new SharedPreferencesUtils(this, "setting");
boolean autoLogin = helper.getBoolean("autoLogin", false);
return autoLogin;
}
/**
* 判断是否记住密码
*/
private boolean remenberPassword() {
//获取SharedPreferences对象,使用自定义类的方法来获取对象
SharedPreferencesUtils helper = new SharedPreferencesUtils(this, "setting");
boolean remenberPassword = helper.getBoolean("remenberPassword", false);
return remenberPassword;
}
private void initViews() {
mLoginBtn = (Button) findViewById(R.id.btn_login);
et_name = (EditText) findViewById(R.id.et_account);
et_password = (EditText) findViewById(R.id.et_password);
checkBox_password = (CheckBox) findViewById(R.id.checkBox_password);
checkBox_login = (CheckBox) findViewById(R.id.checkBox_login);
iv_see_password = (ImageView) findViewById(R.id.iv_see_password);
}
private void setupEvents() {
mLoginBtn.setOnClickListener(this);
checkBox_password.setOnCheckedChangeListener(this);
checkBox_login.setOnCheckedChangeListener(this);
iv_see_password.setOnClickListener(this);
}
/**
* 判断是否是第一次登陆
*/
private boolean firstLogin() {
//获取SharedPreferences对象,使用自定义类的方法来获取对象
SharedPreferencesUtils helper = new SharedPreferencesUtils(this, "setting");
boolean first = helper.getBoolean("first", true);
if (first) {
//创建一个ContentVa对象(自定义的)设置不是第一次登录,,并创建记住密码和自动登录是默认不选,创建账号和密码为空
helper.putValues(new SharedPreferencesUtils.ContentValue("first", false),
new SharedPreferencesUtils.ContentValue("remenberPassword", false),
new SharedPreferencesUtils.ContentValue("autoLogin", false),
new SharedPreferencesUtils.ContentValue("name", ""),
new SharedPreferencesUtils.ContentValue("password", ""));
return true;
}
return false;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_login:
loadUserName(); //无论如何保存一下用户名
login(); //登陆
break;
case R.id.iv_see_password:
setPasswordVisibility(); //改变图片并设置输入框的文本可见或不可见
break;
}
}
/**
* 模拟登录情况
* 用户名twd,密码123456,就能登录成功,否则登录失败
*/
private void login() {
//先做一些基本的判断,比如输入的用户命为空,密码为空,网络不可用多大情况,都不需要去链接服务器了,而是直接返回提示错误
if (getAccount().isEmpty()){
showToast("你输入的账号为空!");
return;
}
if (getPassword().isEmpty()){
showToast("你输入的密码为空!");
return;
}
//登录一般都是请求服务器来判断密码是否正确,要请求网络,要子线程
showLoading();//显示加载框
Thread loginRunnable = new Thread() {
@Override
public void run() {
super.run();
setLoginBtnClickable(false);//点击登录后,设置登录按钮不可点击状态
//睡眠3秒
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//判断账号和密码
if (getAccount().equals("twd") && getPassword().equals("123456")) {
showToast("登录成功");
loadCheckBoxState();//记录下当前用户记住密码和自动登录的状态;
startActivity(new Intent(LoginActivity.this, HomeActivity.class));
finish();//关闭页面
} else {
showToast("输入的登录账号或密码不正确");
}
setLoginBtnClickable(true); //这里解放登录按钮,设置为可以点击
hideLoading();//隐藏加载框
}
};
loginRunnable.start();
}
/**
* 保存用户账号
*/
public void loadUserName() {
if (!getAccount().equals("") || !getAccount().equals("请输入登录账号")) {
SharedPreferencesUtils helper = new SharedPreferencesUtils(this, "setting");
helper.putValues(new SharedPreferencesUtils.ContentValue("name", getAccount()));
}
}
/**
* 设置密码可见和不可见的相互转换
*/
private void setPasswordVisibility() {
if (iv_see_password.isSelected()) {
iv_see_password.setSelected(false);
//密码不可见
et_password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
} else {
iv_see_password.setSelected(true);
//密码可见
et_password.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
}
}
/**
* 获取账号
*/
public String getAccount() {
return et_name.getText().toString().trim();//去掉空格
}
/**
* 获取密码
*/
public String getPassword() {
return et_password.getText().toString().trim();//去掉空格
}
/**
* 保存用户选择“记住密码”和“自动登陆”的状态
*/
private void loadCheckBoxState() {
loadCheckBoxState(checkBox_password, checkBox_login);
}
/**
* 保存按钮的状态值
*/
public void loadCheckBoxState(CheckBox checkBox_password, CheckBox checkBox_login) {
//获取SharedPreferences对象,使用自定义类的方法来获取对象
SharedPreferencesUtils helper = new SharedPreferencesUtils(this, "setting");
//如果设置自动登录
if (checkBox_login.isChecked()) {
//创建记住密码和自动登录是都选择,保存密码数据
helper.putValues(
new SharedPreferencesUtils.ContentValue("remenberPassword", true),
new SharedPreferencesUtils.ContentValue("autoLogin", true),
new SharedPreferencesUtils.ContentValue("password", Base64Utils.encryptBASE64(getPassword())));
} else if (!checkBox_password.isChecked()) { //如果没有保存密码,那么自动登录也是不选的
//创建记住密码和自动登录是默认不选,密码为空
helper.putValues(
new SharedPreferencesUtils.ContentValue("remenberPassword", false),
new SharedPreferencesUtils.ContentValue("autoLogin", false),
new SharedPreferencesUtils.ContentValue("password", ""));
} else if (checkBox_password.isChecked()) { //如果保存密码,没有自动登录
//创建记住密码为选中和自动登录是默认不选,保存密码数据
helper.putValues(
new SharedPreferencesUtils.ContentValue("remenberPassword", true),
new SharedPreferencesUtils.ContentValue("autoLogin", false),
new SharedPreferencesUtils.ContentValue("password", Base64Utils.encryptBASE64(getPassword())));
}
}
/**
* 是否可以点击登录按钮
*
* @param clickable
*/
public void setLoginBtnClickable(boolean clickable) {
mLoginBtn.setClickable(clickable);
}
/**
* 显示加载的进度款
*/
public void showLoading() {
if (mLoadingDialog == null) {
mLoadingDialog = new LoadingDialog(this, getString(R.string.loading), false);
}
mLoadingDialog.show();
}
/**
* 隐藏加载的进度框
*/
public void hideLoading() {
if (mLoadingDialog != null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLoadingDialog.hide();
}
});
}
}
/**
* CheckBox点击时的回调方法 ,不管是勾选还是取消勾选都会得到回调
*
* @param buttonView 按钮对象
* @param isChecked 按钮的状态
*/
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView == checkBox_password) { //记住密码选框发生改变时
if (!isChecked) { //如果取消“记住密码”,那么同样取消自动登陆
checkBox_login.setChecked(false);
}
} else if (buttonView == checkBox_login) { //自动登陆选框发生改变时
if (isChecked) { //如果选择“自动登录”,那么同样选中“记住密码”
checkBox_password.setChecked(true);
}
}
}
/**
* 监听回退键
*/
@Override
public void onBackPressed() {
if (mLoadingDialog != null) {
if (mLoadingDialog.isShowing()) {
mLoadingDialog.cancel();
} else {
finish();
}
} else {
finish();
}
}
/**
* 页面销毁前回调的方法
*/
protected void onDestroy() {
if (mLoadingDialog != null) {
mLoadingDialog.cancel();
mLoadingDialog = null;
}
super.onDestroy();
}
public void showToast(final String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
}
}
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import com.xiaobai.cloneapp.R;
/**
* 主界面
*/
public class HomeActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_activity);
}
}
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.widget.TextView;
import com.xiaobai.cloneapp.R;
/**
* 加载对话框
*/
public class LoadingDialog extends ProgressDialog {
private String mMessage;
private TextView mTitleTv;
public LoadingDialog(Context context, String message, boolean canceledOnTouchOutside) {
super(context, R.style.Theme_Light_LoadingDialog);
this.mMessage = message;
// 如果触摸屏幕其它区域,可以选择让这个progressDialog消失或者无变化
setCanceledOnTouchOutside(canceledOnTouchOutside);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_loading);
mTitleTv = (TextView) findViewById(R.id.tv_loading_dialog);
mTitleTv.setText(mMessage);
setCancelable(false);//不可取消
}
public void setTitle(String message) {
this.mMessage = message;
mTitleTv.setText(mMessage);
}
/**
* 显示在底部
*/
public void showButtom() {
// WindowManager windowManager = ((Activity)
// mContext).getWindowManager();
// Display display = windowManager.getDefaultDisplay();
//
// WindowManager.LayoutParams lp = getWindow().getAttributes();
// lp.width = (int) (display.getWidth() * 0.8);
// getWindow().setAttributes(lp);
// super.show();
}
}
import java.io.IOException;
import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;
/**
* 使用Base64来保存和获取密码数据
*/
public class Base64Utils {
/**
* BASE64解密
*
* @param key
* @return
* @throws Exception
*/
public static String decryptBASE64(String key) {
int decodetime = 5;//压缩和解压的次数,防止被简单破解
byte[] bt;
key = key.trim().replace(" ", "");//去掉空格
try {
while (decodetime > 0) {
bt = (new BASE64Decoder()).decodeBuffer(key);
key = new String(bt);
decodetime--;
}
return key;//如果出现乱码可以改成: String(bt, "utf-8")或 gbk
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
/**
* BASE64加密
*
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(String key) {
int decodetime = 5;//压缩和解压的次数,防止被简单破解
byte[] bt = null;
key = key.trim().replace(" ", "");//去掉空格
while (decodetime > 0) {
bt = key.getBytes();
key = (new BASE64Encoder()).encodeBuffer(bt);
decodetime--;
}
return key;
}
}
import android.content.Context;
import android.content.SharedPreferences;
/**
* 这是一个SharePreference的根据类,使用它可以更方便的数据进行简单存储
* 这里只要知道基本调用方法就可以了
* 1.通过构造方法来传入上下文和文件名
* 2.通过putValue方法传入一个或多个自定义的ContentValue对象,进行数据存储
* 3.通过get方法来获取数据
* 4.通过clear方法来清除这个文件的数据
* 这里没有提供清除单个key的数据,是因为存入相同的数据会自动覆盖,没有必要去理会
*/
public class SharedPreferencesUtils {
//定义一个SharePreference对象
SharedPreferences sharedPreferences;
//定义一个上下文对象
//创建SharePreference对象时要上下文和存储的模式
//通过构造方法传入一个上下文
public SharedPreferencesUtils(Context context, String fileName) {
//实例化SharePreference对象,使用的是get方法,而不是new创建
//第一个参数是文件的名字
//第二个参数是存储的模式,一般都是使用私有方式:Context.MODE_PRIVATE
sharedPreferences = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
}
/**
* 存储数据
* 这里要对存储的数据进行判断在存储
* 只能存储简单的几种数据
* 这里使用的是自定义的ContentValue类,来进行对多个数据的处理
*/
//创建一个内部类使用,里面有key和value这两个值
public static class ContentValue {
String key;
Object value;
//通过构造方法来传入key和value
public ContentValue(String key, Object value) {
this.key = key;
this.value = value;
}
}
//一次可以传入多个ContentValue对象的值
public void putValues(ContentValue... contentValues) {
//获取SharePreference对象的编辑对象,才能进行数据的存储
SharedPreferences.Editor editor = sharedPreferences.edit();
//数据分类和存储
for (ContentValue contentValue : contentValues) {
//如果是字符型类型
if (contentValue.value instanceof String) {
editor.putString(contentValue.key, contentValue.value.toString()).commit();
}
//如果是int类型
if (contentValue.value instanceof Integer) {
editor.putInt(contentValue.key, Integer.parseInt(contentValue.value.toString())).commit();
}
//如果是Long类型
if (contentValue.value instanceof Long) {
editor.putLong(contentValue.key, Long.parseLong(contentValue.value.toString())).commit();
}
//如果是布尔类型
if (contentValue.value instanceof Boolean) {
editor.putBoolean(contentValue.key, Boolean.parseBoolean(contentValue.value.toString())).commit();
}
}
}
//获取数据的方法
public String getString(String key) {
return sharedPreferences.getString(key, null);
}
public boolean getBoolean(String key, Boolean b) {
return sharedPreferences.getBoolean(key, b);
}
public int getInt(String key) {
return sharedPreferences.getInt(key, -1);
}
public long getLong(String key) {
return sharedPreferences.getLong(key, -1);
}
//清除当前文件的所有的数据
public void clear() {
sharedPreferences.edit().clear().commit();
}
}
2dp
4dp
8dp
12dp
20dp
32dp
64dp
1dp
0.5dp
10sp
12sp
14dp
16dp
18dp
25dp
30dp
40dp
50dp
65dp
100dp
120dp
15dp
20dp
30dp
50dp
100dp
48dp
60dp
0.1dp
0.5dp
1dp
2dp
2.5dp
3dp
4dp
4.5dp
5dp
6dp
7dp
7.5dp
8dp
9dp
10dp
11dp
12dp
13dp
14dp
15dp
16dp
17dp
18dp
19dp
20dp
21dp
22dp
23dp
24dp
25dp
26dp
27dp
28dp
29dp
30dp
32dp
33dp
34dp
35dp
36dp
38dp
39dp
40dp
41dp
42dp
43dp
44dp
45dp
46dp
47dp
48dp
49dp
50dp
51dp
52dp
53dp
54dp
55dp
56dp
57dp
58dp
59dp
60dp
61dp
62dp
63dp
64dp
65dp
66dp
67dp
68dp
69dp
70dp
71dp
72dp
73dp
74dp
75dp
76dp
77dp
78dp
79dp
80dp
81dp
82dp
83dp
84dp
85dp
86dp
87dp
88dp
89dp
90dp
91dp
92dp
93dp
94dp
95dp
96dp
97dp
98dp
99dp
100dp
101dp
104dp
105dp
106dp
110dp
111dp
112dp
113dp
120dp
123dp
125dp
128dp
132dp
134dp
135dp
136dp
139dp
140dp
142dp
143dp
150dp
155dp
159dp
160dp
162dp
165dp
170dp
175dp
177dp
179dp
180dp
184dp
190dp
194dp
196dp
200dp
202dp
210dp
216dp
219dp
220dp
225dp
230dp
235dp
238dp
240dp
245dp
250dp
267dp
270dp
275dp
277dp
280dp
285dp
289dp
293dp
300dp
301dp
302dp
306dp
320dp
325dp
338dp
355dp
360dp
365dp
370dp
402dp
410dp
422dp
472dp
500dp
600dp
640dp
800dp
240dp
20dp
demo下载:https://github.com/chaoyu168/LoginDemo