效果视频
ViewPager+TabLayout+PagerAdapter
简述
通过此架构将注册界面与忘记密码进行滑动绑定 导入如下闭包即可使用
implementation 'com.google.android.material:material:1.1.0-alpha09'
implementation 'com.google.android.material:material:1.0.0'
创建滑动适配器
通过继承PagerAdapter 类,将需要插入的视图与标题通过List 传入
public class RegisterAddForgetAdapter extends PagerAdapter {
private List<View> views;
private List<String> FragmentString;
public RegisterAddForgetAdapter(List<View> views, List<String> FragmentString){
this.views = views;
this.FragmentString = FragmentString;
}
@Override
public int getCount() {
return views.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
container.addView( views.get( position ) );
return views.get( position );
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView( views.get( position ) );
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return FragmentString.get( position );
}
}
添加视图与标题
创建视图操作对象
View viewRegister = LayoutInflater.from(RegisterADDForget.this).inflate(R.layout.register_prepare, null);
View viewForget = LayoutInflater.from(RegisterADDForget.this).inflate(R.layout.forget_item, null);
添加视图与标题
views.add(viewRegister);
views.add(viewForget);
Title.add("注册账号");
Title.add("忘记密码");
视图与标题双向绑定
RegisterAddForgetAdapter adapter = new RegisterAddForgetAdapter(views, Title);
for (String title : Title) {
TotalTitle.addTab(TotalTitle.newTab().setText(title));
}
TotalTitle.setupWithViewPager(viewPager);
viewPager.setAdapter(adapter);
TabLayout样式设置
通过创建一个选择器在不同条件触发不同效果,当未被选中时,为灰色,当被选中时为蓝色
选择器
两个drawable 样式文件就不贴出了,就改变背景颜色和圆角弧度两个操作
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/indicator" android:state_selected="true" />
<item android:drawable="@drawable/un_indicator"/>
</selector>
布局设置
在将外层布局设置成灰色,其灰色程度高于默认选择器灰色,形成一个颜色对比 有几个关键点 一、需要将TabLayout 默认滑块的高度设为0
app:tabIndicatorHeight="0dp"
二、滑块居中
app:tabMode="fixed"
app:tabGravity="center"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:background="@drawable/tablayout_style"
android:layout_marginLeft="60dp"
android:layout_marginRight="60dp"
android:layout_marginTop="20dp"
android:padding="10dp">
<com.google.android.material.tabs.TabLayout
android:id="@+id/TotalTitle"
android:layout_width="match_parent"
android:layout_height="30dp"
app:tabSelectedTextColor="#ffffff"
app:tabTextColor="#A59C9C"
app:tabMode="fixed"
app:tabBackground="@drawable/selector"
app:tabIndicatorHeight="0dp"
app:tabGravity="center"
app:tabIndicatorFullWidth="false"
/>
</LinearLayout>
注册
效果图
功能简述
对用户输入的注册信息进行简单判空和格式判定
private boolean Information() {
informationList = dao.QueryAll();
//Toast.makeText(RegisterADDForget.this,informationList.size()+"",Toast.LENGTH_LONG).show();
//String Name = RegisterUser.getText().toString();
PassWord = RNewPassWord.getText().toString();
PhoneNumber = RPhoneNumber.getText().toString().trim();
String Code = RVerificationCode.getText().toString().trim();
//String Sex = RegisterSex.getText().toString();
if (TextUtils.isEmpty(PhoneNumber)) {
toastUtils.ShowWarn("手机号码不能为空");
//processError("手机号码不能为空");
RPhoneNumber.setText("");
return false;
}
if (TextUtils.isEmpty(Code)) {
toastUtils.ShowWarn("验证码不能为空");
//processError("手机号码不能为空");
RVerificationCode.setText("");
return false;
}
if (TextUtils.isEmpty(PassWord)) {
toastUtils.ShowWarn("密码不能为空");
//processError("密码不能为空");
RNewPassWord.setText("");
return false;
}
if (PassWord.length() < 6 || PassWord.length() > 18) {
toastUtils.ShowWarn("密码只能在6-18位");
//processError("密码只能在6-18位");
RNewPassWord.setText("");
return false;
}
if (!JudgePhoneNumberLength(PhoneNumber)) {
toastUtils.ShowWarn("手机号码只能为11位");
//processError("手机号码只能为11位");
//RPhoneNumber.setText("");
return false;
}
if (JudgePhoneNumberFormat(PhoneNumber)) {
toastUtils.ShowWarn("手机号码格式错误");
// processError("手机号码格式错误");
//RPhoneNumber.setText("");
return false;
}
if (!CheckBoxFlag) {
toastUtils.ShowWarn("请先勾选隐私服务");
//processError("请先勾选隐私服务");
RCheckBox.setChecked(false);
CheckBoxFlag = false;
return false;
}
if (informationList != null) {
for (int i = 0; i < informationList.size(); i++) {
if (PhoneNumber.equals(informationList.get(i).getPhone())) {
//如果账号已存在
toastUtils.ShowFail("手机号码已经被注册");
return false;
}
}
}
return true;
}
手机号码格式判定
正则表达式判定手机格式
使用正则表达式对手机号码进行格式判定,其格式为第一位必须为1 ,第2位必须为345789其中一位 ,后面9位可以为0-9任意一位 ;
/*一、中国电信号段:
133、153、173、177、180、181、189、191、199
二、中国联通号段:
130、131、132、155、156、166、175、176、185、186
三、中国移动号段:
134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188、198*/
private boolean JudgePhoneNumberFormat(String Number) {
//第一位必须为1,第二位为345789其中一位,后面九位从0-9都可以
String NumberFormat = "[1][345789]\\d[9]";
if (TextUtils.isEmpty(Number)) {
return false;
} else {
return Number.matches(NumberFormat);
}
}
手机号码长度判定
public boolean JudgePhoneNumberLength(String Number) {
if (TextUtils.isEmpty(Number)) {
return false;
} else {
return Number.length() == 11 ? true : false;
}
}
是否已被注册
通过对SQLite 数据库进行全部记录查询,并返回一个实体类数组
informationList = dao.QueryAll();
然后对其进行一个顺序查找遍历,并根据判定结果,做出相对于的可视化提示提醒用户
if (informationList != null) {
for (int i = 0; i < informationList.size(); i++) {
if (PhoneNumber.equals(informationList.get(i).getPhone())) {
//如果账号已存在
toastUtils.ShowFail("手机号码已经被注册");
return false;
}
}
}
验证码
获取验证码
如果注册信息符合设定的标准,就通过异步通信Handler 的MessageQueue 进行验证码获取
String PhoneNumber = ForgetPhone.getText().toString();
if ((!JudgePhoneNumberFormat(PhoneNumber)) && (!JudgePhoneNumberLength(PhoneNumber))) {
toastUtils.ShowFail("手机号码格式错误");
handlerFlag = false;
} else {
handlerFlag = true;
SMSSDK.getVerificationCode("86", PhoneNumber);
handler.sendEmptyMessageDelayed(0, 1000);
Log.d("RegisterAddForget", "successClickCodeButton");
}
验证码读秒
当点击获取验证码按钮之后,对其进行一个读秒设置,并通过Handler 不断在用户视图中修改其秒值,归0之后,解锁按钮,并恢复成初始化
Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (handlerFlag) {
if (Current > 0) {
Current--;
RGetCode.setEnabled(false);
RGetCode.setText("(" + Current + "s)");
sendEmptyMessageDelayed(0, 1000);
Log.d("RegisterAddForget", Current + "S");
} else {
RGetCode.setEnabled(true);
RGetCode.setText("验证码");
handlerFlag = false;
Current = 60;
}
}else {
RGetCode.setEnabled(true);
RGetCode.setText("验证码");
handlerFlag = false;
Current = 60;
}
}
};
提交验证码
如果成功获取验证码,则提交验证码,判定是否一致
boolean result = Information();
if (result) {
/**register success*/
FuncFlag = true;
String PhoneNumber = RPhoneNumber.getText().toString().trim();
String Code = RVerificationCode.getText().toString().trim();
submitVerificationCode("86", PhoneNumber, Code);
}
public static void submitVerificationCode(String Country, String Phone, String Code) {
SMSSDK.submitVerificationCode(Country, Phone, Code);
}
验证码验证
通过判定回调的标识符,判定验证码是否一致
eh = new EventHandler() {
@Override
public void afterEvent(int event, int result, Object data) {
// TODO 此处为子线程!不可直接处理UI线程!处理后续操作需传到主线程中操作!
if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {
if (result == SMSSDK.RESULT_COMPLETE) {
runOnUiThread(() -> {
if (FuncFlag){
RegisterSuccess();
}else {
ResetSuccess();
}
//toastUtils.ShowSuccess("验证成功");
});
} else {
runOnUiThread(() -> {
//processError("验证码不匹配");
toastUtils.ShowFail("验证码不匹配");
});
}
} else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE) {
runOnUiThread(() -> {
//processError("获取短信验证码成功");
toastUtils.ShowSuccess("获取短信验证码成功");
});
} else {
runOnUiThread(() -> {
//processError("异常");
toastUtils.ShowFail("异常");
});
((Throwable) data).printStackTrace();
}
}
};
注册成功
若注册成功,即将用户输入的信息插入数据库中
private void RegisterSuccess() {
handlerFlag = false;
toastUtils.ShowSuccess("注册成功");
dao.Insert(new Information("", PassWord, "", PhoneNumber, "DefaultCity", "000000", 0, 0, 0));
handler.sendEmptyMessageDelayed(0, 1000);
}
忘记密码
效果图
功能简述
忘记密码和注册差不多,对输入的信息进行格式判定、验证码的获取,提交,判定等流程,此处省略相同部分
按钮背景变化设置
为了优化用户体验,通过对重置密码按钮进行背景变化设置,当没有输入任何字符时,默认呈灰色,当输入字符时,自动变为蓝色
样式效果
样式代码
选择状态
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#2196F3"/>
<corners android:radius="10dp"/>
</shape>
默认灰色
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="10dp"/>
<solid android:color="#F8F7F7"/>
</shape>
样式控制
通过对EditText 进行点击事件监听,然后在不同条件下触发不同效果
RPhoneNumber.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.d("RegisterAddForget", s.toString() + "-before");
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length() > 0) {
ConfirmRegister.setEnabled(true);
ConfirmRegister.setClickable(true);
ConfirmRegister.setBackground(getResources().getDrawable(R.drawable.btn_blue_rd));
ConfirmRegister.setTextColor(Color.parseColor("#ffffff"));
} else {
ConfirmRegister.setEnabled(false);
ConfirmRegister.setClickable(false);
ConfirmRegister.setBackground(getResources().getDrawable(R.drawable.bt_not_sure));
ConfirmRegister.setTextColor(Color.parseColor("#DAD7D7"));
}
Log.d("RegisterAddForget", s.toString() + "-Changed");
}
@Override
public void afterTextChanged(Editable s) {
Log.d("RegisterAddForget", s.toString() + "-after");
}
});
更新密码
对数据库该记录进行更新操作
private void ResetSuccess(){
handlerFlag = false;
toastUtils.ShowSuccess("重置密码成功");
dao.UpdatePassWord(ResetPhoneNumber,NewPassWord);
handler.sendEmptyMessageDelayed(0, 1000);
}
登录
效果图
功能简述
登录功能为根据用户输入的数据对数据库进行查询,然后根据返回的实体类数组进行顺序遍历,然后判定是否匹配,并做出相对应的操作
登录判定
判空处理,手机号码格式判定就省略了,上述中提及过,以下为对实体类数组进行顺序查询判定,如果存在匹配项则更改该记录的登录状态标志符,方便在主界面以及个人信息界面根据此标志符进行判定是否显示、读取数据,如果不存在匹配项,则触发相对应的条件,并显示在用户界面上
if (informationList != null) {
Log.d("Login","get into if");
Log.d("Login",informationList.size() +"size");
for (int i = 0; i < informationList.size(); i++) {
Log.d("Login","get into for");
if ((GetPhoneNumber.equals(informationList.get(i).getPhone())) && (GetPassWordEdit.equals(informationList.get(i).getPassWord()))) {
toastUtils.ShowSuccess("登录成功");
dao.UpdateStatus(GetPhoneNumber, 1);
sp.PutData(Login.this, "PhoneNumber", GetPhoneNumber);
startActivity(new Intent(Login.this, MainActivity.class));
return;
}
}
toastUtils.ShowFail("账号或密码错误");
} else {
toastUtils.ShowFail("异常");
}
尾言
验证码API用的是MobService,收费是0.03一条,官网有详细配置步骤,有意者可以去了解
|