主要功能
登陆界面UI由MaterialDesign(原质化设计)为主要框架。
注册与忘记密码界面由TabLayout+ViewPager+PagerAdapter框架编写而成。
其中注册界面的手机验证码采用MobTech的SDK
MobTech
代码详解
第一部分:登陆界面效果图如下:


XML布局代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:paddingTop="20dp">
<ImageView
android:id="@+id/Login_goback"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/goback"
android:scaleType="fitCenter"
android:layout_marginLeft="5dp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="30dp"
android:text="账号密码登陆"
android:textColor="#000000"
android:textSize="30sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/SMedium"
android:orientation="horizontal">
<ImageView
android:layout_width="50dp"
android:layout_height="30dp"
android:src="@drawable/user"
android:text="账 号:"
android:layout_marginTop="@dimen/Small"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:counterEnabled="true"
app:counterMaxLength="12"
app:errorEnabled="true"
app:errorTextAppearance="@style/Error"
>
<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="用户名"
android:paddingLeft="10dp"
android:singleLine="true"
android:textColor="#ff000000"
android:textSize="15sp"
/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp">
<ImageView
android:id="@+id/TipsPassWord"
android:layout_width="50dp"
android:layout_height="30dp"
android:src="@drawable/password"
android:layout_marginTop="10dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:counterEnabled="true"
app:counterMaxLength="12"
app:errorEnabled="true"
app:errorTextAppearance="@style/Error"
app:passwordToggleEnabled="true">
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/TipsPassWord"
android:hint="密 码"
android:paddingLeft="10dp"
android:password="true"
android:textColor="#ff000000"
android:textSize="15sp" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:paddingLeft="20dp">
<CheckBox
android:id="@+id/AgreementStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="已阅读并同意“布道者”智慧停车《服务协议》和《隐私政策》"
android:textSize="10sp"
android:layout_marginTop="10dp"/>
</LinearLayout>
<Button
android:id="@+id/login"
android:layout_width="200dp"
android:layout_height="30dp"
android:layout_marginLeft="80dp"
android:layout_marginTop="10dp"
android:background="#1A73E8"
android:text="进入智慧停车"
android:textColor="#ffffff"
android:textSize="15sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:orientation="vertical"
android:layout_gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="————————其他登陆方式————————" />
</LinearLayout>
<LinearLayout
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:orientation="horizontal"
android:layout_marginLeft="30dp"
>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="fitCenter"
android:src="@drawable/qq" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="fitCenter"
android:src="@drawable/wechat" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="fitCenter"
android:src="@drawable/phone" />
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="20dp">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="忘记密码"
android:textSize="20sp"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:background="#00000000"
/>
<Button
android:id="@+id/ButtonRegister"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册"
android:textSize="20sp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="#00000000"/>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
登陆界面代码如下:
public class Login extends AppCompatActivity {
private EditText UserName,PassWord;
private CheckBox AgreementStatus;
private Button Login,Register;
private ImageView PassWordStatus,GoBack;
private boolean Status = false;
private boolean SmallEyeFlag = true;
private boolean AgreementStatusFlag = true;
public static boolean JudgeLoginStatic = false;
Dao dao = new Dao( com.example.LoginPackage.Login.this );
public static String Login_Account = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_login );
InitView();
SetTitle();
//InitTextInputLayout();
//SeePassWord();
// CannotSeePassWord();
Listener();
}
// private void InitTextInputLayout() {
// final EditText UserID = UserName.getEditText();
// EditText UserPassWord = PassWord.getEditText();
// Account account = LitePal.findLast( Account.class );
// String DataBaseID = account.getUserID();
// String DataBasePassWord = account.getPassWord();
// UserID.addTextChangedListener( new TextWatcher() {
// @Override
// public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//
// }
//
// @Override
// public void onTextChanged(CharSequence s, int start, int before, int count) {
// if (s.length() > 12){
// UserName.setError( "账户长度不能超过12位");
// UserName.setErrorEnabled( true );
// }else {
// UserName.setErrorEnabled( false );
// }
// }
//
// @Override
// public void afterTextChanged(Editable s) {
//
// }
// } );
// UserPassWord.addTextChangedListener( new TextWatcher() {
// @Override
// public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//
// }
//
// @Override
// public void onTextChanged(CharSequence s, int start, int before, int count) {
//
// }
//
// @Override
// public void afterTextChanged(Editable s) {
//
// }
// } );
// }
//设置密码不可见
/* private void CannotSeePassWord() {
PassWordStatus.setImageResource( R.drawable.closeeye );
PassWord.setTransformationMethod( PasswordTransformationMethod.getInstance() );
}*/
//设置密码可见
/* private void SeePassWord() {
PassWordStatus.setImageResource( R.drawable.openeye );
PassWord.setTransformationMethod( HideReturnsTransformationMethod.getInstance() );
}*/
/*********初始化界面*************/
private void InitView() {
UserName = findViewById( R.id.username );
PassWord = findViewById( R.id.password );
AgreementStatus = findViewById( R.id.AgreementStatus );
Login = findViewById( R.id.login );
// PassWordStatus = findViewById( R.id.PassWordStatus );
GoBack = findViewById( R.id.Login_goback );
Register = findViewById( R.id.ButtonRegister );
}
//设置标题栏
private void SetTitle() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
}
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
Intent MyIntent = new Intent(Intent.ACTION_MAIN);
MyIntent.addCategory(Intent.CATEGORY_HOME);
startActivity(MyIntent);
finish();
break;
}
return super.onOptionsItemSelected(item);
}
private void Listener(){
OnClick onClick = new OnClick();
Login.setOnClickListener( onClick );
// PassWordStatus.setOnClickListener( onClick );
GoBack.setOnClickListener( onClick);
Register.setOnClickListener( onClick );
}
/****判断CheckBox是否被选中****/
private boolean AgreementStatusMethod(){
AgreementStatus.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked ){
Status = true;
}else {
Status = false;
}
}
} );
return Status;
}
//判断密码是否正确
/**
* 前期使用固定密码进行调试
* 后期使用数据库保存已注册账号,并进行匹配
* */
private void SignIn(){
String GetUserEdit = UserName.getText().toString();
String GetPassWordEdit = PassWord.getText().toString().trim();
//查询最后一条记录
/*即为刚创建的账号密码*/
String JudgePassWord = dao.Query( GetUserEdit );
if (TextUtils.isEmpty( GetUserEdit )){
UserName.setError( "账号不能为空" );
return;
}
if (GetUserEdit.length() > 12){
UserName.setError( "账号长度不能超过12位" );
return;
}
if (AgreementStatusMethod() == false){
Toast.makeText( com.example.LoginPackage.Login.this,"请先勾选隐私协议",Toast.LENGTH_SHORT ).show();
return;
}
if (GetPassWordEdit .equals(JudgePassWord ))
{
JudgeLoginStatic = true;
Login_Account = GetUserEdit;
Intent intent = new Intent( com.example.LoginPackage.Login.this,Function.class );
startActivity( intent );
}else {
UserName.setError( "账号或者密码错误" );
return;
}
}
/*********内部类点击事件*************/
class OnClick implements View.OnClickListener{
Intent intent = null;
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.login:
//RadioButton如果选定则跳转,否则发出提示
SignIn();
break;
case R.id.Login_goback:
intent = new Intent( Login.this, Function.class );
startActivity( intent );
break;
case R.id.ButtonRegister:
intent = new Intent( com.example.LoginPackage.Login.this,RegisterADDForget.class );
startActivity( intent );
}
}
}
}
注册与忘记密码界面效果图如下:


获取手机验证码详解:
第一步:点击获取验证码
参数为:国家代码,手机号码
SMSSDK.getVerificationCode( "86",PhoneNumber );
/********************获取验证码***********************/
GetVerificationCode.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
String PhoneNumber = RegisterPhoneNumber.getText().toString();
if ((!JudgePhoneNumberFormat( PhoneNumber )) && (!JudgePhoneNumberLength( PhoneNumber ) )){
Toast.makeText( RegisterADDForget.this,"手机号码格式错误",Toast.LENGTH_SHORT ).show();
return;
}
SMSSDK.getVerificationCode( "86",PhoneNumber );
}
} );
第三步:提交验证码
SMSSDK.submitVerificationCode( "86", PhoneNumber,Code);
第三步:创建EventHandler实例接收验证码回调信息
eventHandler = new EventHandler(){
@Override
public void afterEvent(final int i, int i1, Object o) {
if (i == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {
//提交短信、语音验证码成功
runOnUiThread( ()->{
if (i1 == SMSSDK.RESULT_COMPLETE) {
AlertDialog.Builder builder = new AlertDialog.Builder( RegisterADDForget.this );
builder.setTitle( "提示" )
.setMessage( "注册成功" )
.setIcon( R.drawable.success )
.setCancelable( true )
.create()
.show();
Flag = true;
}else {
AlertDialog.Builder builder = new AlertDialog.Builder( RegisterADDForget.this );
builder.setTitle( "提示" )
.setMessage( "验证码不正确" )
.setIcon( R.drawable.smssdk_sign )
.setCancelable( true )
.create()
.show();
Flag = false;
}
} );
} else if (i == SMSSDK.EVENT_GET_VERIFICATION_CODE) {
//获取短信验证码成功
runOnUiThread( ()->{
Current = 60;
handler.sendEmptyMessage( 0 );
boolean smart = (Boolean) o;
if (smart) {
//通过Mob云验证
Toast.makeText( RegisterADDForget.this, "通过Mob云验证", Toast.LENGTH_SHORT ).show();
} else {
Toast.makeText( RegisterADDForget.this, "验证码获取成功", Toast.LENGTH_SHORT ).show();
//依然走短信验证
}
} );
} else if (i1 == SMSSDK.RESULT_ERROR) {
Toast.makeText( RegisterADDForget.this, "验证码获取失败", Toast.LENGTH_SHORT ).show();
//失败回调
} else {
//其他失败回调
((Throwable) o).printStackTrace();
}
}
};
SMSSDK.registerEventHandler( eventHandler );
并最后与绑定SMSSDK
SMSSDK.registerEventHandler( eventHandler );
使用完EventHandler需注销,否则可能出现内存泄漏
@Override
protected void onDestroy() {
super.onDestroy();
SMSSDK.unregisterEventHandler( eventHandler );
}
其中判断手机号码格式方法如下:
public boolean JudgePhoneNumberLength(String Number){
if (TextUtils.isEmpty( Number )){
return false;
}else {
return Number.length() == 11 ? true : false;
}
}
/*一、中国电信号段:
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 static 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 );
}
}
总结
实践出真知