Android开发(10)——手机号验证登录

本节内容

1.EditText简介

2.Button简介

3.Bomb三方库提供短信验证服务

4.首页布局

5.实现手机号自动分割

6.解决bug并删除号码

7.添加按钮界面跳转

8.使用selector设置按钮点击状态颜色

9.按钮文字颜色切换

10.解决格式化号码转换为正常号码bug

11.布局验证页面提示信息

12.将输入的内容显示到小方格中

13.Bmob环境搭建

14.请求验证码

15.验证输入的验证码

一、EditText简介
1.它可以监听文本改变的事件
mPhoneEditText.addTextChangedListener(object:LoginTextWatcher(){
override fun afterTextChanged(s: Editable?) {
  }
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
      }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {           
     }
}
  • 这三个事件分别是: afterTextChanged(文本改变之后)、onTextChanged(文本正在改变)和beforeTextChanged(文本改变之前)
2.如果不想显示EditText中的光标,可以设置一下,将它去除
android:cursorVisible="false"
3.输入数字时,如果觉得数字间的间距很小,可以设置一下把间距加大
 android:letterSpacing="0.1"
4.如果想要输入内容,但是又不想显示输入框,那么就可以将它的透明度设置得小一点,这样就可以将其隐藏起来。
android:alpha="0.01"
二、Button简介
1.通过text属性设置按钮的文本,颜色,文字大小等前面都讲过,这里就不再详述。
2.给按钮添加一个id之后,就可以给它设置点击事件了。
3.比较特别的按钮有switch,也可以给switch设置点击事件。switch有一个比较特别的属性就是isChecked。在手机的设置里面可能会使用到switch。
 switch1.setOnClickListener {
            val s = it as Switch
              if(s.isChecked){
                  mLogin.text = "打开了"
              }else{
                  mLogin.text = "关闭了"
              }
        }
4.还有checkBox按钮,这些属性都比较简单,可以自行琢磨。
三、Bmob三方库提供短信验证服务
1.先在Bmob注册一个账号,进入主页之后,点击左上角创建应用
image.png
  • 我这里是已经创建好了一个
2.回到网站首页,点击文档进入文档中心。然后点击数据服务的Android。
QQ图片20210322181427.png
3.之后按照那一页的提示操作即可。
  • 首先导入SDK
image.png
  • 反正跟着它一路向下操作即可。
  • 先在这里面添加底下那一行代码,也就是仓库地址
allprojects { 
repositories {
 //Bmob的maven仓库地址--必填
        maven {url 'https://dl.bintray.com/chaozhouzhang/maven' }
  • 然后在app的buildGradle的android里面添加依赖库
 useLibrary 'org.apache.http.legacy'
  • 然后在dependencies里面添加以下的依赖文件,然后同步一下。
 implementation 'cn.bmob.android:bmob-sdk:3.7.8'
    implementation "io.reactivex.rxjava2:rxjava:2.2.8"
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    implementation 'com.squareup.okhttp3:okhttp:3.14.1'
    implementation 'com.squareup.okio:okio:2.2.2'
    implementation 'com.google.code.gson:gson:2.8.5'
  • 然后配置一下Mainfest,在里面添加以下权限
 <!-- 允许联网 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 获取GSM(2g)、WCDMA(联通3g)等网络状态的信息 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- 获取wifi网络状态的信息 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!-- 保持CPU 运转,屏幕和键盘灯有可能是关闭的,用于文件上传和下载 -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <!-- 获取sd卡写的权限,用于文件上传和下载 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- 允许读取手机状态 用于创建BmobInstallation -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • 配置ContentProvider
 <provider
            android:name="cn.bmob.v3.util.BmobContentProvider"
            android:authorities="com.example.message.BmobContentProvider"
            android:exported="false">
        </provider>
  • 初始化Bomb,重新创建一个类,重写onCreate()方法
class MyApplication:Application() {
    override fun onCreate() {
        super.onCreate()
        //第一.默认初始化
        Bmob.initialize(this, "c12f5ff15568e1e18c72649071389bea");
    }
}
  • Application ID从之前创建的应用的key里面查看。
image.png
  • 通过 requestSMSCode 方式给绑定手机号的该用户发送指定短信模板的短信验证码:
/**
 * TODO template 如果是自定义短信模板,此处替换为你在控制台设置的自定义短信模板名称;如果没有对应的自定义短信模板,则使用默认短信模板。
 */
BmobSMS.requestSMSCode(phone, "DataSDK", new QueryListener<Integer>() {
    @Override
    public void done(Integer smsId, BmobException e) {
        if (e == null) {
            mTvInfo.append("发送验证码成功,短信ID:" + smsId + "\n");
        } else {
            mTvInfo.append("发送验证码失败:" + e.getErrorCode() + "-" + e.getMessage() + "\n");
        }
    }
});
四、首页布局
我们要将界面布局成如下效果:
QQ图片20210322190621.png

image.png
1.布局首页的时候,添加几个guideline,这样方便我们布局。
image.png
2.图片是一个正方形,我们之前讲过,在右侧属性中,点击那个矩形的左上角,让它的比例为1:1。
3.中间添加一个EditText,调节一下它的大小。
4.给输入框添加一个边框,所以在drawable中新建一个名为shape_roundrect的xml文件,然后把<selector>改为<shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <corners android:radius="10dp"/>
    <stroke android:color="@color/colorGray"
        android:width="1dp"/>
    <solid android:color="@color/colorAlphaGray"/>
</shape>
5.然后找到EditText,把这个边框应用上
 android:background="@drawable/shape_roundrect"
6.为了有更多的颜色可以选择,可以在values下添加一个colors.xml,在里面添加一些颜色
<resources>
    <color name="colorPrimary">#6200EE</color>
    <color name="colorPrimaryDark">#3700B3</color>
    <color name="colorAccent">#03DAC5</color>
    <color name="colorGray">#666</color>
    <color name="colorAlphaGray">#2666</color>
    <color name="colorRed">#FF0000</color>
    <color name="colorBlack">#000</color>
</resources>
7.想要输入框内部的内容和边框有一点间距,那么就可以设置一下padding。(自己和自己的间距)
android:paddingStart="10dp"
8.给输入框设置一下默认提示文字
 android:hint="输入手机号"
五、实现手机号自动分割
1.我们平常输入手机号码时,都会自动分割为3 4 4 的形式。我们的实现思路为:时刻监听文本输入,当输入了三个数字之后添加一个空格,当输入八个字符之后,再添加一个空格。所以我们要给EditText添加一个监听事件,时刻监听它的变化。
 mPhoneEditText.addTextChangedListener(object:LoginTextWatcher(){
            override fun afterTextChanged(s: Editable?) {
                //设置按钮是否可以点击
                mLogin.isEnabled = (s.toString().length == 13)

                //判断是在删除还是输入
                if (!shouldAutoSplit) return
                s.toString().length.also {
                    if (it == 3 || it == 8) {
                        //需要添加空格
                        s?.append(" ")
                    }
                }
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                  shouldAutoSplit =( count ==1)
            }
        })
2.对于TextWatcher监听器,我们只会用到其中的两个方法,但使用的时候还是不得不实现所有的方法。所以我们可以新建一个类,让它继承于TextWatcher,然后空实现这个接口的所有方法。后面新建的对象继承于我们创建的类即可。
3.新建一个类,继承TextWatcher。
open class LoginTextWatcher: TextWatcher{
    override fun afterTextChanged(s: Editable?) {

    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

    }

}
4.当字符串的长度为3和8时,需要添加空格。
 s.toString().length.also {
                    if (it == 3 || it == 8) {
                        //需要添加空格
                        s?.append(" ")
                    }
                }
5.因为输入的数字不超过11位,加上两个空格,就不超过13位。所以在EditText设置它的最大长度位13.
 android:maxLength="13"
六、解决删除bug并获取号码
1.经过上面的操作,我们发现了一个bug。当我们发现输错号码,想要删除时,结果到了空格那里,发现空格删不掉。
  • 因为当我们删到第八个的时候,它又执行afterTextChanged方法,结果发现长度为8,又添加一个空格,反反复复,所以删不掉。
2.实验过程中,我们发现,在 onTextChanged方法中,添加数字的时候 count = 1,删除数据的时候 count=0。所以我们可以根据count的值来判断用户是在增加还是删除。所以我们可以定义一个变量来记录这个。
 private var shouldAutoSplit = true
3.在afterTextChanged方法中,加一个判断是在删除还是输入。如果是在输入的话,那么就执行下面的添加空格。如果是在删除的话,那么就return,就不会执行添加空格的操作。
 if (!shouldAutoSplit) return
4.如果count = 1,那么就是在做增加,那么 shouldAutoSplit = true,否则就是false
 override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                  shouldAutoSplit =( count ==1)
            }
5.因为在输入的时候添加了空格,所以到时候传递过去的数据可能也包含空格。为了避免出现这种情况,我们就要把它转化为正常的数据。
 private fun getPhoneNumber(editable: Editable):String{
        //创建一个新的对象 用于操作editable对象里面的内容
        SpannableStringBuilder(editable.toString()).also {
            it.delete(3,4)
            it.delete(7,8)
            return it.toString()
        }
    }
七、添加按钮界面跳转
1.添加一个按钮,设置一个id,然后给它设置一个点击事件
2.因为要跳转到另外一个界面,所以我们要准备好另外一个界面。在这个监听事件中只需要启动一下页面即可。
 mLogin.setOnClickListener{
            Intent().apply {
                //跳转方向
                setClass(this@MainActivity,VerifyActivity::class.java)
                //配置跳转携带的数据
                putExtra("phone",getPhoneNumber(mPhoneEditText.text))
                //启动
                startActivity(this)
            }
        }
3.跳转过来的页面需要接收一下数据
intent.getStringExtra("phone").also {
                //显示号码
                  mPhone.text = it
              }
八、使用selector设置按钮点击状态颜色
1.输入手机号的时候,只有输入了13位手机号,登录按钮才会被点击,界面才会跳转。为了实现这个功能,我们设置一下按钮的enabled属性,当它为fasle的时候,按钮是不能被点击的。
 android:enabled="false"
2.在afterTextChanged方法中设置按钮是否可以点击,只有当位数为13时,按钮才能被点击。
   mLogin.isEnabled = (s.toString().length == 13)
3.为了让用户能够直观到感受到按钮能否被点击,我们可以让按钮在不同时刻变更不一样的颜色。所以我们在drawable中新建一个xml。enabled状态不同,显示的颜色也不同。这样就可以根据控件的状态,实现选择器的效果。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!--
    根据控件的enable值 设置不同的颜色
    注意顺序:特殊在前 常规在后
    enable状态 运行起来正常状态 enable = true 其他状态 enable = false
    从上至下匹配
    -->
     <item android:drawable="@color/colorAccent"  android:state_enabled="true"/>
    <item android:drawable="@color/colorAlphaGray" android:state_enabled="false"/>
</selector>
4.把selector整好了以后,在按钮那里使用起来,把它的背景选为这个xml文件
android:background="@drawable/btn_status_selector"
九、按钮文字颜色切换
1.为了美观,我们希望登录按钮文字的颜色也随用户的输入而变化,所以我们再创建一个xml。不能点击时,颜色为黑色。可以点击时,颜色为白色。
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_enabled="false" android:color="@color/colorBlack"/>
    <item android:state_enabled="true" android:color="@color/colorRed"/>
</selector>
2.在code再把textColor改为这个drawable中的文件
 android:textColor="@drawable/btn_text_selector"
十、解决格式化号码转化为正常号码bug
1.bug:当我们输入号码时,它会按照3 4 4 的格式正常分割,然后我们进行界面跳转。再返回当前界面时,会发现显示的是去空格后格式化的号码,而不是3 4 4 形式的号码。
2.要避免出现这种情况,我们一开始就不能直接对editable进行操作。必须先把里面的东西取出来,然后再进行操作。所以我们用的是SpannableStringBuilder。
 SpannableStringBuilder(editable.toString()).also {
            it.delete(3,4)
            it.delete(7,8)
            return it.toString()
        }
这就是前面我们这样使用的原因。
十一、布局验证页面提示信息
1.输入手机号之后,进入验证码验证页面,也就是输入验证码
image.png
2.上方图片调整为正方形,然后添加几个TextView即可。
3.输入验证码的地方有六个小边框,每个框框对应一个数字。最外面用一个EditText来包裹一下,小的框框是TextView。
4.添加六个TextView,让文字居中
android:gravity="center"
5.给这六个TextView添加六个边框,边框就是在drawable中新建一个xml,然后设置一下<shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <stroke android:color="@color/colorPrimary" android:width="1dp"/>
    <solid android:color="@color/colorAlphaGray"/>
    <corners android:radius="6dp"/>
</shape>
6.然后在code里面把background设置为这个drawable中的文件。
7.拖动一个EditText,和这六个小框框重合,设置为match_parent,并设置其透明度为0.01
十二、将输入的内容显示到小方格中
1.给每个小框框添加id,为mv1——mv6。
2.让EditText中的内容显示到每一个小方框中的方法:EditText中是一串字符串,字符串又有索引。只需要将索引对应的字符作为每一个小的TextView中的Text即可。
3.保存所有显示验证码的textView
 private val verifyViews:Array<TextView> by lazy {
        arrayOf(mv1,mv2,mv3,mv4,mv5,mv6)
    }
4.监听文本框内容改变的事件
 mOrigin.addTextChangedListener(object:TextWatcher{
            override fun afterTextChanged(s: Editable?) {

            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
}
5.这次我们只需要实现最后一个onTextChanged方法,所以后面的代码都是写在这个方法里面的。
6.将输入的内容拆分到每一个textView中,其中i是索引,item是字符。
for((i,item)in s?.withIndex()!!){
                   //获取i对应的textView
                   verifyViews[i].text = item.toString()
               }
7.如果位数小于6个 后面的文本框不显示任何内容。
 for(i in s.length..5){
                    verifyViews[i].text= ""
                }
8.设置Edit Text文本框最长输入长度为6.
android:maxLength="6"
十三、Bmob环境搭建
1.当我们进入输入验证码的界面的时候,我们希望终端能自动向我们输入的号码发送短信。输入验证码之后,它又会将接收到的验证码和服务器发给用户的验证码进行比较,如果一致就返回一个结果,如果不一致就提示输入错误。这里我们就需要用到一个服务器发送短信。
2.关于配置数据库和依赖库等,我已经在前面写过了。其中配置的应用包名为applicationId后面显示的内容。
3.在Manifest里面配置一下name
android:name=".MyApplication"
十四、请求验证码
1.不让这个EditText被长按。
android:longClickable="false"
2.为了方便管理Bmob操作,我们创建一个类来管理关于Bmob的操作。
object BmobUtil {}
3.实现的功能就是①向服务器 请求发送验证码,完成之后有两个返回值(发送成功、发送失败)②验证用户输入的验证码 (验证成功 、验证失败)
4.先写一个发送验证码的方法,传递两个参数,第一个是手机号,第二个是回调的结果。我们这里用高阶函数作为返回的结果。
fun requestSMSCode(phone:String,callBack:(Int)->Unit){
           BmobSMS.requestSMSCode(phone,"",object:QueryListener<Int>(){
               override fun done(p0: Int?, p1: BmobException?) {
                   if(p1==null){
                        callBack(SUCCESS)
                   }else{
                        callBack(FAILURE)
                   }
               }
           } )
    }
  • 为了方便理解,定义两个静态参数。
    const val SUCCESS = 0
    const val FAILURE = 1
5.对于客户端来说,只要调用我们这里写好的方法就可以发送短信了。
override fun onResume() {
        super.onResume()
        BmobUtil.requestSMSCode(mPhone.text.toString()){
            if(it==BmobUtil.SUCCESS){
                Toast.makeText(this,"发送验证码成功",Toast.LENGTH_SHORT).show()
            }else{
                Toast.makeText(this,"发送验证码失败",Toast.LENGTH_SHORT).show()
            }
        }
    }
十五、验证输入的验证码
1.在BmobUtil 类中重写一下验证的方法。第一个参数为电话号码,第二个参数为用户输入的验证码,第三个参数为匿名内部类。
fun verifySMSCode(phone:String,code:String,callBack: (Int) -> Unit){
        BmobSMS.verifySmsCode(phone,code,object :UpdateListener(){
            override fun done(p0: BmobException?) {
              if(p0==null){
                  //验证码验证成功
                  callBack(SUCCESS)
              }else{
                  //验证失败
                  callBack(FAILURE)
              }
            }
        })
    }
2.发送验证请求之后,再判断验证成功与否。如果成功,则进行界面跳转。如果失败就提示一下,并清空文本框中的内容。
 if(s.length==6){
                    //发起验证的请求
                 BmobUtil.verifySMSCode(mPhone.text.toString(),s.toString()){
                     if(it==BmobUtil.SUCCESS){
                            startActivity(Intent(this@VerifyActivity,HomeActivity::class.java))
                     }else{
                         Toast.makeText(this@VerifyActivity,"验证失败",Toast.LENGTH_SHORT).show()
                        mOrigin.text.clear()
                     }
                 }
                }
3.自己创建一个简单的页面,作为验证成功后跳转的界面。就改一下背景颜色即可。只要能分辨得出和前面的页面不一样都行。之后在manifest中注册一下。
 <activity android:name=".HomeActivity"/>
所有的操作基本完成,我们运行之后,发送短信,如果是正确的号码,就会收到这样的短信。
QQ图片20210323200717.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容