手机安全卫士第二天实现的功能:
1.自定义View和自定义属性让其实现了点击事件。
2.两个弹窗一个用来设置密码一个用来进行密码效验,密码进行了MD5加密处理。
3.手机防盗功能界面的实现(其中包括了状态选择器,9-Patch图片处理,跳转的动画)。
4.shape形状的使用。
首先进行了自定义View和自定义属性功能的实现
1.开始用settingItemView继承了一个View Relativelayout,然后实现了其构造方法的方法,在每个构造方法里进行初始化操作,然后在XML文件里自定义了属性,然后在自定义中settingItemView进行属性的初始化,代码如下。
/**
* 自定义的组合控件
* Created by Administrator on 2016/4/26.
*/
public class SettingItemView extends RelativeLayout {
private static final String NAMESPACE = "http://schemas.android.com/apk/com.daizhihao.mobilesafe";
private TextView tvTitle;
private TextView tvDesc;
private CheckBox cbStatus;
private String mTitle;
private String mDescOn;
private String mDescOff;
// 用代码new对象时,走此方法
public SettingItemView(Context context) {
super(context);
initView();
}
// 有属性时走此方法
public SettingItemView(Context context, AttributeSet attrs) {
super(context, attrs);
// 根据属性名称,获取属性的值
mTitle = attrs.getAttributeValue(NAMESPACE,"tv_title");
mDescOn = attrs.getAttributeValue(NAMESPACE,"desc_on");
mDescOff = attrs.getAttributeValue(NAMESPACE,"desc_off");
initView();
}
// 有style样式的话会走此方法
public SettingItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
/**
* 初始化布局
*/
private void initView() {
// 将自定义好的布局文件设置给当前的SettingItemView
View.inflate(getContext(), R.layout.view_setting, this);
tvTitle = (TextView) findViewById(R.id.tv_title);
tvDesc = (TextView) findViewById(R.id.tv_desc);
cbStatus = (CheckBox) findViewById(R.id.cb_status);
setTitle(mTitle);
}
2.然后在另外一个布局里面使用该自定义的View,使用方法是在布局里面导入该路径,要使用自定义的属性,需要先设置一个xmlns的名字然后加上路径,代码如下。
xmlns:hysy="http://schemas.android.com/apk/com.daizhihao.mobilesafe"
3.最后在该自定义控件和这个界面进行一些简单的交互。
sivUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 判断当前的勾选状态
if (sivUpdate.isChecked()) {
// 设置不勾选
sivUpdate.setChecked(false);
// 更新sp
mPref.edit().putBoolean("auto_update", false).commit();
} else {
sivUpdate.setChecked(true);
// 更新sp
mPref.edit().putBoolean("auto_update", true).commit();
}
}
});
1.首先判断用户是第一次点击还是第几次点击,然后根据用户点击实现相对的功能。
/**
* 显示密码弹窗
*/
private void showPasswordDialog() {
// 判断是否设置密码
String savedPassword = mPref.getString("password", null);
if (!TextUtils.isEmpty(savedPassword)) {
//已经输入过密码
showPasswordinputDialog();
} else {
//若没有是设置密码则跳转到输入密码
showPasswordsetDialog();
}
}
2.判断之后弹出对应的弹窗,然后根据用户的输入的密码,进行是否让用户进入手机防盗界面。第一次先让用户保存一次密码,第二次用户必须输入第一次保存的密码才算正确输入。
/**
* 输入密码弹框
*/
private void showPasswordinputDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final AlertDialog alertDialog = builder.create();
View view = View.inflate(this, R.layout.dailog_input_password, null);
alertDialog.setView(view, 0, 0, 0, 0);//为对话框设置自定义布局并设置4边留白保证在2.x的版本上运行没问题
Button btn_OK = (Button) view.findViewById(R.id.btn_ok);
Button btn_cancel = (Button) view.findViewById(R.id.btn_cancel);
final EditText ev_password = (EditText) view.findViewById(R.id.et_password);
btn_OK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String password = ev_password.getText().toString();
String savedPassword = mPref.getString("password", null);
//判断String是否为空字符串
if (!TextUtils.isEmpty(password)){
if (MD5Utils.encode(password).equals(savedPassword)){
startActivity(new Intent(HomeActivity.this,LostFindActivity.class));
alertDialog.dismiss();
}else {
Toast.makeText(HomeActivity.this, "密码错误", Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(HomeActivity.this, "输入框不能为空", Toast.LENGTH_SHORT).show();
}
}
});
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertDialog.dismiss();//隐藏对话框
}
});
alertDialog.show();
}
/**
* 弹出设置密码对话框
*/
private void showPasswordsetDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final AlertDialog alertDialog = builder.create();
View view = View.inflate(this, R.layout.dailog_set_password, null);
alertDialog.setView(view, 0, 0, 0, 0);//为对话框设置自定义布局并设置4边留白保证在2.x的版本上运行没问题
Button btn_OK = (Button) view.findViewById(R.id.btn_ok);
Button btn_cancel = (Button) view.findViewById(R.id.btn_cancel);
final EditText ev_password = (EditText) view.findViewById(R.id.et_password);
final EditText ev_passwordConfirm = (EditText) view.findViewById(R.id.et_password_confirm);
btn_OK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String password = ev_password.getText().toString();
String passwordConfirm = ev_passwordConfirm.getText().toString();
//判断String是否为空字符串
if (!TextUtils.isEmpty(password) && !TextUtils.isEmpty(passwordConfirm)) {
if (password.equals(passwordConfirm)) {
mPref.edit().putString("password", MD5Utils.encode(password)).commit();
startActivity(new Intent(HomeActivity.this, LostFindActivity.class));
alertDialog.dismiss();
} else {
Toast.makeText(HomeActivity.this, "两次密码输入不一致密码输入", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(HomeActivity.this, "输入框不能为空", Toast.LENGTH_SHORT).show();
}
}
});
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertDialog.dismiss();//隐藏对话框
}
});
alertDialog.show();
}
3.密码保存,效验都采用的MD5加密,如果嫌MD5不够安全,可以对MD5进行加盐处理(对用户的密码加一串字符串再进行MD5加密)。
public class MD5Utils {
/**
* md5加密
*
* @param password
* @return
*/
public static String encode(String password) {
try {
MessageDigest instance = MessageDigest.getInstance("MD5");// 获取MD5算法对象
byte[] digest = instance.digest(password.getBytes());// 对字符串加密,返回字节数组
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
int i = b & 0xff;// 获取字节的低八位有效值
String hexString = Integer.toHexString(i);// 将整数转为16进制
if (hexString.length() < 2) {
hexString = "0" + hexString;// 如果是1位的话,补0
}
sb.append(hexString);
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
// 没有该算法时,抛出异常, 不会走到这里
}
return "";
}
}
用户输入了正确的密码之后就应该是跳转到手机防盗的向导页面,在手机向导页面最主要的是状态选择器,9-Patch,向导页面的开发。
1.状态选择器的定义,在deawable里面新建一个XML文件,然后对 android:state_pressed="true"状态(按下的状态),android:state_focused="true"状态(获得焦点的状态)item android:drawable="@drawable/function_greenbutton_normal"状态(默认的状态)分别进行选择对应的图片
//按下的图片
//获取焦点的图片
//默认图片
//将选择器设置给Button