2018-09-09 關(guān)于用戶登錄的過程(用Fragment去實(shí)現(xiàn))

之前已經(jīng)說過如何進(jìn)行登錄界面的編寫颁湖,一個好的app是需要從用戶的角度去出發(fā)的,我們登錄界面不僅能提供用戶密碼登錄雄驹,還應(yīng)該能支持用戶短信登錄甚至是短信修改密碼,這樣就需要我們用更多的精力去優(yōu)化我們的代碼.首先說一下本篇文章的重點(diǎn)
1.關(guān)于如何進(jìn)行Fragment的跳轉(zhuǎn)
2.如何進(jìn)行Fragment之前的傳參
3.如何使從當(dāng)前Fragment回退到我們需要的界面
4.如何使用mobSdk進(jìn)行短信驗(yàn)證.
5.對于用戶輸入信息的判斷.
這樣荣堰,我們一點(diǎn)一點(diǎn)來分析床未,首先,我們需要進(jìn)行Fragment的跳轉(zhuǎn)振坚。這個問題很重要薇搁,因?yàn)槲覀兊慕缑婵隙ㄊ怯邪存I需求的,當(dāng)用戶按下一個鍵后渡八,會要跳轉(zhuǎn)到我們需要的界面上啃洋,上一篇文章在最后提到可以用接口回調(diào)的方式去實(shí)現(xiàn),其實(shí)這樣太麻煩了屎鳍,我們可以用事務(wù)處理的方式去實(shí)現(xiàn)對Fragment管理.

public class FragmentTranscationUtil {
    //獲取FragmentManager宏娄,開啟事務(wù),添加碎片
    public static void replaceFragment(FragmentActivity activity, Fragment fragment) {
        FragmentManager manager = activity.getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.setCustomAnimations(R.anim.activity_right_in, 0, 0, R.anim.activity_right_out);
        transaction.replace(R.id.userloginFrame_layout, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }

    //獲取FragmentManager逮壁,開啟事務(wù)孵坚,添加碎片
    public static void replaceFragment(FragmentActivity activity, Fragment fragment, Bundle bundle) {
        FragmentManager manager = activity.getSupportFragmentManager();
        fragment.setArguments(bundle);
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.setCustomAnimations(R.anim.activity_right_in, 0, 0, R.anim.activity_right_out);
        transaction.replace(R.id.userloginFrame_layout, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }

這是一個幫助類,參數(shù)很簡單窥淆,首先卖宠,我們要獲取當(dāng)前所在Activity,這個不用多說嗎忧饭,因?yàn)镕ragment多是嵌套在Activity里面的扛伍,第二個參數(shù)就是我們需要跳轉(zhuǎn)的目標(biāo)Fragment
下面第二個構(gòu)造函數(shù)的第三個參數(shù)Bundle則是用來進(jìn)行傳參的.這個我下面會詳細(xì)講解
首先,我們要獲取到FragmentManger的實(shí)例manger,然后manager.beginTransaction();
去開啟事務(wù)词裤,將我們需要執(zhí)行的邏輯放入到事務(wù)中刺洒,在調(diào)用transaction.commit();去執(zhí)行
就行了,這里順便向大家展示一下Fragment生命周期
Fragment的生命周期和activity生命周期很像亚斋,其生命周期方法如下所示作媚。

  1. onAttach:綁定到activity
  2. onCreate:創(chuàng)建fragment
  3. onCreateView: 創(chuàng)建fragment的布局
  4. onActivityCreated: activity創(chuàng)建完成后
  5. onStart: 可見, 不可交互
  6. onResume: 可見, 可交互
  7. onPause: 部分可見, 不可交互
  8. onStop:不可見
  9. onDestroyView: 銷毀fragment的view對象
  10. onDestroy: fragment銷毀了
  11. onDetach: 從activity解綁了
    下面給出FragmentTransaction的全部方法(API 24)轉(zhuǎn)載自http://www.reibang.com/p/5761ee2d3ea1
  • add(Fragment fragment, String tag) // 調(diào)用add(int, Fragment, String),填入為0的containerViewId.
  • add(int containerViewId, Fragment fragment) // 調(diào)用add(int, Fragment, String),填入為null的tag.
  • add(int containerViewId, Fragment fragment, String tag) // 向Activity中添加一個Fragment.
  • addSharedElement(View sharedElement, String name) // 添加共享元素
  • addToBackStack(String name) // 將事務(wù)添加到回退棧
  • attach(Fragment fragment) // 重新關(guān)聯(lián)Fragment(當(dāng)Fragment被detach時)
  • commit() // 提交事務(wù)
  • commitAllowingStateLoss() // 類似commit(),但允許在Activity狀態(tài)保存之后提交(即允許狀態(tài)丟失)帅刊。
  • commitNow() // 同步提交事務(wù)
  • commitNowAllowingStateLoss() // 類似commitNow(),但允許在Activity狀態(tài)保存之后提交(即允許狀態(tài)丟失)漂问。
  • detach(Fragment fragment) // 將fragment保存的界面從UI中移除
  • disallowAddToBackStack() // 不允許調(diào)用addToBackStack(String)操作
  • hide(Fragment fragment) // 隱藏已存在的Fragment
  • isAddToBackStackAllowed() // 是否允許添加到回退棧
  • isEmpty() // 事務(wù)是否未包含的任何操作
  • remove(Fragment fragment) // 移除一個已存在的Fragment
  • replace(int containerViewId, Fragment fragment) // 調(diào)用replace(int, Fragment, String)填入為null的tag.
  • replace(int containerViewId, Fragment fragment, String tag) // 替換已存在的Fragment
  • setBreadCrumbShortTitle(int res) // 為事務(wù)設(shè)置一個BreadCrumb短標(biāo)題
  • setBreadCrumbShortTitle(CharSequence text) // 為事務(wù)設(shè)置一個BreadCrumb短標(biāo)題赖瞒,將會被FragmentBreadCrumbs使用
  • setBreadCrumbTitle(int res) // 為事務(wù)設(shè)置一個BreadCrumb全標(biāo)題,將會被FragmentBreadCrumbs使用
  • setBreadCrumbTitle(CharSequence text) // 為事務(wù)設(shè)置一個BreadCrumb全標(biāo)題
  • setCustomAnimations(int enter, int exit, int popEnter, int popExit) // 自定義事務(wù)進(jìn)入/退出以及入棧/出棧的動畫效果
  • setCustomAnimations(int enter, int exit) // 自定義事務(wù)進(jìn)入/退出的動畫效果
  • setTransition(int transit) // 為事務(wù)設(shè)置一個標(biāo)準(zhǔn)動畫
  • setTransitionStyle(int styleRes) // 為事務(wù)標(biāo)準(zhǔn)動畫設(shè)置自定義樣式
  • show(Fragment fragment) // 顯示一個被隱藏的Fragment

這樣我們就解決了Fragment跳轉(zhuǎn)問題蚤假,同時Fragment回退問題也給出了答案栏饮,那就是利用addToBackStack(String name)
我們知道Activity有任務(wù)棧,用戶通過startActivity將Activity加入棧磷仰,點(diǎn)擊返回按鈕將Activity出棧袍嬉。Fragment也有類似的棧,稱為回退棧(Back Stack),回退棧是由FragmentManager管理的伺通。

image

默認(rèn)情況下箍土,F(xiàn)ragment事務(wù)是不會加入回退棧的,如果想將Fragment加入回退棧并實(shí)現(xiàn)事物回滾罐监,首先需要在commit()方法之前調(diào)用事務(wù)的以下方法將其添加到回退棧中:

  • addToBackStack(String name)
    這個方法在我們跳轉(zhuǎn)Fragment時候?qū)⑹聞?wù)添加至回退棧
    Fragment的回退非常簡單吴藻,然而這里又會出現(xiàn)一個新的問題,就是在修改后的案例每次只能回退到上一步操作弓柱,而并不能一次性回退到我們想要的位置沟堡,這樣才更滿足實(shí)際開發(fā)需要。這就需要我們來多了解事物回滾的相關(guān)原理矢空,其實(shí)在Fragment回退時航罗,默認(rèn)調(diào)用FragmentManager的popBackStack()方法將最上層的操作彈出回退棧。當(dāng)棧中有多層時屁药,我們可以根據(jù)id或TAG標(biāo)識來指定彈出到的操作所在層伤哺。
  • popBackStack(int id, int flags):其中id表示提交變更時commit()的返回值。
  • popBackStack(String name, int flags):其中name是addToBackStack(String tag)中的tag值者祖。
    在上面2個方法里面立莉,都用到了flags,其實(shí)flags有兩個取值:0或FragmentManager.POP_BACK_STACK_INCLUSIVE七问。當(dāng)取值0時蜓耻,表示除了參數(shù)指定這一層之上的所有層都退出棧,指定的這一層為棧頂層械巡;當(dāng)取值POP_BACK_STACK_INCLUSIVE時刹淌,表示連著參數(shù)指定的這一層一起退出棧。
    這樣Fragment的跳轉(zhuǎn)和回退就說到這里讥耗,接下來是傳參問題有勾,這個問題也很簡單,因?yàn)锽undle的底層代碼就是HasMap<key,value>組合古程,首先實(shí)例化一個bundle,然后用<key,value>儲存想要保存的數(shù)據(jù)蔼卡,然后調(diào)用
  • setArguments(bundle);//添加將要傳遞的bundle
    在目標(biāo)Fragment,使用getArguments();去獲取到傳入的值,比較簡單挣磨,就不在贅述了雇逞。這樣,1茁裙,2塘砸,3,問題我們都已經(jīng)解決
    接下來是重點(diǎn)晤锥!如何使用mobSDK去實(shí)現(xiàn)短信驗(yàn)證.
    首先給大家一張圖掉蔬,便于理解短信驗(yàn)證流程
    TIM截圖20180930115033.png

我個人使用的是Mob開發(fā)者平臺(http://sms.mob.com)注冊廊宪,獲取到Appkey和appSecret,這個非常重要

配置Gradle
1女轿、打開項(xiàng)目根目錄的build.gradle箭启,在buildscrip–>dependencies 模塊下面添加 classpath ‘com.mob.sdk:MobSDK:+’,如下所示谈喳;

buildscript {
    repositories {
        jcenter()
    }
 
    dependencies {
        ...
        classpath 'com.mob.sdk:MobSDK:+'
 
    }
}

2册烈、在使用SMSSDK模塊的build.gradle中,添加MobSDK插件和擴(kuò)展婿禽,如:

// 添加插件
apply plugin: 'com.mob.sdk'

// 在MobSDK的擴(kuò)展中注冊SMSSDK的相關(guān)信息
MobSDK {
    appKey "d580ad5*****"http://填寫自己獲取的appKey
    appSecret "7fcae59a******7e2759e9e397c82bdd"http://填寫自己獲取的appSecret

    SMSSDK {}
}

這里面的appkey和appSecret是自己注冊而獲取到的.替換一下就行了,
3赏僧、初始化MobSDK
如果您沒有在AndroidManifest中設(shè)置appliaction的類名,MobSDK會將這個設(shè)置為com.mob.MobApplication扭倾,但如果您設(shè)置了淀零,請?jiān)谀约旱腁pplication類中調(diào)用:

MobSDK.init(this);

以初始化MobSDK。
具體代碼
這里有兩種方式去實(shí)現(xiàn)膛壹,一個是可視化界面驾中,一個是非UI實(shí)現(xiàn),
因?yàn)槲覀€人是是使用無UI的方式模聋,所以會講述無Ui實(shí)現(xiàn)的方法肩民,這里給出可視化界面的文檔(http://wiki.mob.com/sdk-sms-android-3-0-0/
首先介紹一下EventHandler這是一個異步操作,和Handler類似所有的業(yè)務(wù)邏輯將會在這里處理链方,它是和registerEventHandler一起使用的持痰,registerEventHandler是一個事件接收器,他是專門負(fù)責(zé)接收所有被觸發(fā)的事件祟蚀,而registerEventHandler本身可以注冊多個工窍,所有接收器也會在事件被觸發(fā)時候接收消息.一般是配套使用,否則容易產(chǎn)生內(nèi)存泄露
下面給出具體代碼

 //請求短信驗(yàn)證碼
    private void SendCode(String country, String number) {
        EventHandler eh = new EventHandler() {
            @Override
            public void afterEvent(int i, int i1, Object o) {
                if (i == SMSSDK.EVENT_GET_VERIFICATION_CODE) {//獲取短信驗(yàn)證碼事件
                    //獲取驗(yàn)證碼成功
                    if (i1 == SMSSDK.RESULT_COMPLETE) {
                        listener.getCodeSuccess();
                    } else if (i1 == SMSSDK.RESULT_ERROR) {
                        listener.getCodeFailure();
                    }
                }
            }
        };
        SMSSDK.registerEventHandler(eh);
        SMSSDK.getVerificationCode(country, number);
    }

可以看到這是我自定義的一個方法前酿,首先獲取國家患雏,中國是86開頭,沒啥好說的罢维,然后是你將要發(fā)送短信驗(yàn)證的用戶手機(jī)號碼淹仑,這也沒啥好說的,至于listener是我自定義的接口言津,會統(tǒng)一處理事務(wù)邏輯.

 //提交驗(yàn)證碼
    private void SubmitCode(String country, final String number, String code) {
        EventHandler eh = new EventHandler() {
            @Override
            public void afterEvent(int i, int i1, Object o) {
                if (i == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {//驗(yàn)證碼提交事件
                    if (i1 == SMSSDK.RESULT_COMPLETE) {
                        //回調(diào)成功
                        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                        listener.submitCodeSuccesss(number, dateFormat.format(new Date()));
                    } else if (i1 == SMSSDK.RESULT_ERROR) {//提交驗(yàn)證碼失敗
                        listener.submitCodeFailure();
                    }
                }
            }
        };
        SMSSDK.registerEventHandler(eh);
        SMSSDK.submitVerificationCode(country, number, code);
    }

提交驗(yàn)證碼多出一個你接收短信驗(yàn)證的信息code,其他都差不多的攻人。
這里給出mob業(yè)務(wù)邏輯,可以最大限度自定義出符合你自己要求的業(yè)務(wù)邏輯悬槽。

Handler mhandle = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int event = msg.arg1;
            int result = msg.arg2;
            Object data = msg.obj;

            if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {//驗(yàn)證碼提交事件
                if (result == SMSSDK.RESULT_COMPLETE) {
                    //回調(diào)成功
                    Toast.makeText(context, "提交驗(yàn)證碼成功"+result, Toast.LENGTH_LONG).show();
                } else if (result == SMSSDK.RESULT_ERROR) {
                    Toast.makeText(context, "提交驗(yàn)證碼失敗"+data, Toast.LENGTH_LONG).show();
                }

            } else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE) {//獲取短信驗(yàn)證碼事件

                //獲取驗(yàn)證碼成功
                if (result == SMSSDK.RESULT_COMPLETE) {
                    Toast.makeText(context, "獲取短信驗(yàn)證碼成功", Toast.LENGTH_LONG).show();
                    boolean mobcheck = (Boolean) data;
                    if (mobcheck) {
                        //通過智能驗(yàn)證
                        Toast.makeText(context, "mob云驗(yàn)證", Toast.LENGTH_LONG).show();
                    } else {
                        //依然走短信驗(yàn)證
                        Toast.makeText(context, "短信驗(yàn)證", Toast.LENGTH_LONG).show();
                    }
                } else if (result == SMSSDK.RESULT_ERROR) {
                    Toast.makeText(context, "獲取短信驗(yàn)證碼失敗"+data, Toast.LENGTH_LONG).show();
                }
            } else if (event == SMSSDK.EVENT_GET_SUPPORTED_COUNTRIES) {
                SMSSDK.getSupportedCountries();
            } else {

                try {
                    ((Throwable) data).printStackTrace();
                    Throwable throwable = (Throwable) data;
                    JSONObject jsonObject = new JSONObject(throwable.getMessage());
                    String des = jsonObject.optString("detail");
                    int status = 0;
                    status = jsonObject.optInt("status");
                    if (TextUtils.isEmpty(des)) {

                    }
                } catch (Exception e) {
                    SMSLog.getInstance().w(e);
                }
            }
        }
    };

Ps:SMSSDK已經(jīng)做了混淆處理,再次混淆會導(dǎo)致不可預(yù)期的錯誤瞬浓,請?jiān)谀幕煜_本中添加如下的配置初婆,跳過對SMSSDK的混淆操作:

-keep class com.mob.**{*;}
-keep class cn.smssdk.**{*;}
-dontwarn com.mob.**

這個時候,大家可能就有疑問了,沒有UI界面我如何去輸入收到的短信驗(yàn)證碼去驗(yàn)證磅叛,很簡單屑咳,自己寫個UI就行了啊,一般現(xiàn)在流行的界面可能就是如下圖所示了弊琴,引用一下圖片http://www.reibang.com/p/91b0b8038dd5

1879314-56d1f0d5b902bfee.png

這位大牛的效果還是不錯的兆龙,我說下自己的思路,簡單的就是TextView+Edittext去組合實(shí)現(xiàn)的敲董,下面紫皇,附上xml資源,大家可以詳細(xì)了解一下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorWhite">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv_code1"
            style="@style/codeTextView" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_code2"
            style="@style/codeTextView" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_code3"
            style="@style/codeTextView" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_code4"
            style="@style/codeTextView" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_code5"
            style="@style/codeTextView" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_code6"
            style="@style/codeTextView" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:orientation="horizontal">

        <View
            android:id="@+id/view1"
            android:layout_width="40dp"
            android:layout_height="2dp"
            android:layout_gravity="bottom"
            android:background="@color/colorGray707061" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:id="@+id/view2"
            android:layout_width="40dp"
            android:layout_height="2dp"
            android:layout_gravity="bottom"
            android:background="@color/colorGray707061" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:id="@+id/view3"
            android:layout_width="40dp"
            android:layout_height="2dp"
            android:layout_gravity="bottom"
            android:background="@color/colorGray707061" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:id="@+id/view4"
            android:layout_width="40dp"
            android:layout_height="2dp"
            android:layout_gravity="bottom"
            android:background="@color/colorGray707061" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:id="@+id/view5"
            android:layout_width="40dp"
            android:layout_height="2dp"
            android:layout_gravity="bottom"
            android:background="@color/colorGray707061" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:id="@+id/view6"
            android:layout_width="40dp"
            android:layout_height="2dp"
            android:layout_gravity="bottom"
            android:background="@color/colorGray707061" />

    </LinearLayout>

    <lf.com.android.blackfishdemo.view.CodeEditTextView
        android:id="@+id/et_code_text"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#00000000"
        android:inputType="number"
        android:longClickable="false"
        android:maxLength="6"
        android:textColor="#00000000" />

</RelativeLayout>

乍一看貌似很復(fù)雜腋寨,其實(shí)就是繪制了可以輸入6位數(shù)的Textview和對應(yīng)的下標(biāo)Item,然后上面再被我自定義的EditText所覆蓋


/**
 * 驗(yàn)證碼控件聪铺,去掉傳統(tǒng)EditText雙擊選中EditText的內(nèi)容
 * 和去掉光標(biāo)位置會隨點(diǎn)擊改變
 */
public class CodeEditTextView extends AppCompatEditText {
    private long lastTime = 0;

    public CodeEditTextView(Context context) {
        super(context);
    }

    public CodeEditTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CodeEditTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onSelectionChanged(int selStart, int selEnd) {
        super.onSelectionChanged(selStart, selEnd);
        this.setSelection(this.getText().length());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://判斷點(diǎn)擊事件,防止用戶多次點(diǎn)擊
                long currenTime = System.currentTimeMillis();
                if (currenTime - lastTime < 500) {
                    lastTime = currenTime;
                    return true;
                } else {
                    lastTime = currenTime;
                }
                break;


        }
        return super.onTouchEvent(event);
    }
}

自定義的Edittext首先會通過long currenTime = System.currentTimeMillis();獲取到當(dāng)前時間點(diǎn)萄窜,判斷兩個點(diǎn)擊時間間隔铃剔,從而屏蔽雙擊事件,長按會走 onSelectionChanged這個方法查刻,所以键兜,設(shè)置光標(biāo)始終在文本后面,也就屏蔽了長按事件
然后通過對Edittext事件進(jìn)行TextWatcher監(jiān)聽(后面會詳細(xì)講解)穗泵,依次將輸入內(nèi)容分寫到Textview上普气,就完成了上面的效果.至此,如何使用短信驗(yàn)證就告一段落.
好了火欧,同通過短信驗(yàn)證就意味著棋电,用戶登錄過程已經(jīng)接近尾聲甚至已經(jīng)結(jié)束了,但是苇侵,在這里赶盔,我還是想一起說了吧,因?yàn)槎绦膨?yàn)證不僅僅用于登錄榆浓,也用于修改密碼于未,而且,用戶輸入的內(nèi)容我們要去判斷陡鹃,不可能用戶隨便輸入一個文本我們就要對其進(jìn)行一次短信驗(yàn)證吧烘浦,畢竟,喜歡找Bug的用戶也不少萍鲸,所以闷叉,我們要對用戶輸入的內(nèi)容進(jìn)行判斷。這就是我么要說的5.對于用戶輸入信息的判斷.在說這個之前脊阴,我先向大家介紹一下握侧,什么是正則表達(dá)式蚯瞧。
正則表達(dá)式是一種查找以及字符串替換操作。正則表達(dá)式在文本編輯器中廣泛使用品擎,比如正則表達(dá)式被用于:

  • 檢查文本中是否含有指定的特征詞
  • 找出文中匹配特征詞的位置
  • 從文本中提取信息埋合,比如:字符串的子串修改文本與文本編輯器相似,幾乎所有的高級編程語言都支持正則表達(dá)式萄传。在這樣的語境下甚颂,“文本”也就是一個字符串,可以執(zhí)行的操作都是類似的秀菱。一些編程語言(比如Perl振诬,JavaScript)會檢查正則表達(dá)式的語法。
    正則表達(dá)式的語法是是一種輕量級答朋、簡潔贷揽、適用于特定領(lǐng)域的編程語言。
    關(guān)于詳解梦碗,建議大家去看這篇文章http://www.reibang.com/p/67af3eeb6798
    這里給大家常用正則表達(dá)式的鏈接https://www.cnblogs.com/zxin/archive/2013/01/26/2877765.html
    所以禽绪,當(dāng)我們使用正則表達(dá)式時候,可利用事件監(jiān)聽
 private void setEditTextLitener() {
        mEditText.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) {
 
            }
        });
    }

我們可以通過監(jiān)聽afterTextChanged獲取到輸入內(nèi)容洪规,從而進(jìn)行判斷印屁,然后去編寫我們所需要的邏輯,至此斩例,用戶登錄過程就完美結(jié)束了雄人,歡迎大家留言,提出問題.謝謝大家的閱讀念赶。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末础钠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子叉谜,更是在濱河造成了極大的恐慌旗吁,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件停局,死亡現(xiàn)場離奇詭異很钓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)董栽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門码倦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锭碳,你說我怎么就攤上這事袁稽。” “怎么了擒抛?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵运提,是天一觀的道長蝗柔。 經(jīng)常有香客問我闻葵,道長民泵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任槽畔,我火速辦了婚禮栈妆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厢钧。我一直安慰自己鳞尔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布早直。 她就那樣靜靜地躺著寥假,像睡著了一般。 火紅的嫁衣襯著肌膚如雪霞扬。 梳的紋絲不亂的頭發(fā)上糕韧,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機(jī)與錄音喻圃,去河邊找鬼萤彩。 笑死,一個胖子當(dāng)著我的面吹牛斧拍,可吹牛的內(nèi)容都是我干的雀扶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼肆汹,長吁一口氣:“原來是場噩夢啊……” “哼愚墓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起昂勉,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤浪册,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后硼啤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體议经,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年谴返,在試婚紗的時候發(fā)現(xiàn)自己被綠了煞肾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡嗓袱,死狀恐怖籍救,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情渠抹,我是刑警寧澤蝙昙,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布闪萄,位于F島的核電站,受9級特大地震影響奇颠,放射性物質(zhì)發(fā)生泄漏败去。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一烈拒、第九天 我趴在偏房一處隱蔽的房頂上張望圆裕。 院中可真熱鬧,春花似錦荆几、人聲如沸吓妆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽行拢。三九已至,卻和暖如春诞吱,著一層夾襖步出監(jiān)牢的瞬間舟奠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工狐胎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鸭栖,地道東北人。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓握巢,卻偏偏與公主長得像晕鹊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子暴浦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容