一个简单的智能停车APP——登陆篇

本文详细介绍了如何使用MaterialDesign构建一个智能停车APP的登录界面,包括账号密码输入、TabLayout+ViewPager+PagerAdapter框架的注册与忘记密码界面。在注册过程中,使用了MobTech的SDK进行手机验证码验证。同时,代码中包含了登录验证逻辑和事件监听处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个简单的智能停车APP

主要功能

登陆界面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 );
        }
    }

总结

实践出真知

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FranzLiszt1847

嘟嘟嘟嘟嘟

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值