ios 注册手机号码验证样式

2018-05-11 17:06:28 fzhlee 阅读数 237

原文:http://coolketang.com/staticCoding/5a995104ac502e5d51cce462.html

1. 本节课将为您演示,表单在提交时的数据验证。首先在左侧的项目导航区,打开视图控制器的代码文件。 



2. 现在开始编写代码,给表单添加验证的功能。 


3. 在当前的类文件中,引入已经安装的第三方类库。 


4. 然后修改当前视图控制器类的父类的名称。 


5. 设置当验证失败时,标签行的视觉刷新事件。 


6. 设置背景颜色为红色。 


7. 然后设置字体的颜色为白色。 


8. 接着依次设置字体的样式,以及文字的对齐方式。 


9. 设置文本行的视觉变化。 


10. 当验证失败时,设置字体的颜色为红色。 


11. 接着在表单中添加一个段落,并设置段落的头部和尾部信息。 


12. 在该段落中添加一个文本行,并设置该行的标题文字。 


13. 接着添加验证规则为非空,如果该行的内容为空,则会提示验证错误。 


14. 添加一个段落,并设置段落的头部和尾部信息。 


15. 在该段落中添加一个文本行,并设置该行的标题文字。 


16. 接着添加验证规则为非空,如果该行的内容为空,则会提示验证错误。 


17. 创建一个字符串类型的规则集合。 


18. 然后添加非空验证和邮箱验证。 


19. 将规则集合赋予当前的表单行。 


20. 然后设置当失去焦点,并且内容发生变化时,进行表单的验证。 


21. 添加一个段落,并设置段落的头部和尾部信息。 


22. 在该段落中添加一个网址行,并设置该行的标题文字。 


23. 接着添加验证规则为网址格式的验证,并且在值发生变化时进行验证。 


24. 设置单元格的刷新动作。 


25. 当验证失败时,设置单元格的字体颜色为红色。 


26. 添加一个段落,并设置段落的头部和尾部的信息。 


27. 在该段落中添加一个密码行,并设置该行的标题文字。 


28. 接着添加验证规则,设置最小的长度为8,最大的长度为13。用户需要输入最小长度和最大长度之间的内容。 


29. 设置单元格的刷新动作。 


30. 当验证失败时,设置单元格的字体颜色为红色。 


31. 添加一个段落,并设置段落的头部和尾部的信息。 


32. 在该段落中添加一个整数行,并设置该行的标题文字。 


33. 接着添加验证规则为,允许用户输入2到999之间的整数。 


34. 设置单元格的刷新动作。 


35. 当验证失败时,设置单元格的字体颜色为红色。 


36. 添加一个段落,并设置段落的头部和尾部的信息。 


37. 在该段落中添加一个密码行,并设置该行的标题文字。 


38. 添加另一个密码行,并设置该行的标题文字。 


39. 接着添加验证规则,设置最小的长度为8,最大的长度为13。 


40. 设置单元格的刷新动作。 


41. 当验证失败时,设置单元格的字体颜色为红色。 


42. 继续添加一个段落,并设置段落的头部和尾部的信息。 


43. 在该段落中添加一个文本行,并设置该行的标题文字。 


44. 接着添加验证规则为非空的规则,并且在值发生变化时进行验证。 


45. 设置单元格的刷新动作。 


46. 当验证失败时,设置单元格的字体颜色为红色。 


47. 设置单元格的在验证发生变化时的情况。 


48. 获得当前表单行在表单中的序号。 


49. 然后删除当前段落的错误信息标签。 


50. 接着处理当验证失败时的情况。 


51. 对所有的错误信息进行遍历。 


52. 创建一个标签表单行,并设置标签的标题文字为错误信息,同时设置单元格的高度。 


53. 接着将标签行,插入到当前行的下方。 


54. 继续在该段落中添加一个邮箱表单行,并设置该行的标题文字。 


55. 接着添加验证规则,为非空规则和邮箱格式的验证。 


56. 设置当失去焦点,并且内容发生变化时,进行表单的验证。 


57. 设置单元格的刷新动作。 


58. 当验证失败时,设置单元格的字体颜色为红色。 


59. 处理单元格在验证发生变化时的情况。 


60. 获得当前表单行在表单中的序号。 


61. 然后删除当前段落的错误信息标签。 


62. 接着处理验证失败时的情况。 


63. 对所有的错误信息进行遍历。 


64. 创建一个标签表单行,并设置标签的标题文字为错误信息,同时设置单元格的高度。 


65. 接着将标签插入到当前行的下方。 


66. 继续在该段落中添加一个网址行,并设置该行的标题文字。 


67. 接着添加验证规则,为非空规则的验证,以及设置在值发生变化时进行表单的验证。 


68. 设置单元格的刷新动作。 


69. 当验证失败时,设置单元格的字体颜色为红色。 


70. 处理单元格在验证发生变化时的情况。 


71. 获得当前表单行在表单中的序号。 


72. 然后删除当前段落的错误信息标签。 


73. 接着处理验证失败时的情况。 


74. 对所有的错误信息进行遍历。 


75. 创建一个标签表单行,并设置标签的标题文字为错误信息,同时设置单元格的高度。 


76. 接着将标签插入到当前行的下方。 


77. 继续在该段落中添加一个密码行,并设置该行的标题文字。 


78. 接着添加一个最小长度和最大长度的验证规则。 


79. 设置单元格的刷新动作。 


80. 当验证失败时,设置单元格的字体颜色为红色。 


81. 处理单元格在验证发生变化时的情况。 


82. 获得当前表单行在表单中的序号。 


83. 然后删除当前段落的错误信息标签。 


84. 接着处理验证失败时的情况。 


85. 对所有的错误信息进行遍历。 


86. 创建一个标签行,并设置标签的标题文字为错误信息,同时设置单元格的高度。 


87. 接着将标签插入到当前行的下方。 


88. 继续在该段落中添加一个密码行,并设置该行的标题文字。 


89. 接着添加一个最小长度和最大长度的验证规则。 


90. 设置单元格的刷新动作。 


91. 当验证失败时,设置单元格的字体颜色为红色。 


92. 处理单元格在验证发生变化时的情况。 


93. 获得当前表单行在表单中的序号。 


94. 然后删除当前段落的错误信息标签。 


95. 接着处理当验证失败时的情况。 


96. 对所有的错误信息进行遍历。 


97. 创建一个标签行,并设置标签的标题文字为错误信息,同时设置单元格的高度。 


98. 接着将标签插入到当前行的下方。 


99. 继续在该段落中添加一个整数行,并设置该行的标题文字。 


100. 接着添加验证规则为,允许用户输入2到999之间的整数。 


101. 设置单元格的刷新动作。 


102. 当验证失败时,设置单元格的字体颜色为红色。 


103. 处理单元格在验证发生变化时的情况。 


104. 获得当前表单行在表单中的序号。 


105. 然后删除当前段落的错误信息标签。 


106. 接着处理当验证失败时的情况。 


107. 对所有的错误信息进行遍历。 


108. 创建一个标签行,并设置标签的标题文字为错误信息,同时设置单元格的高度。 


109. 接着将标签插入到当前行的下方。 


110. 添加一个新的段落。 


111. 然后在段落中添加一个按钮行,并设置该行的标题文字。 


112. 设置当表单行处于选择状态时,强制校验表单中的所有元素。接着点击左上角的[编译并运行]按钮,启动模拟器预览项目。 


113. 在弹出的项目中,点击密码行,并打开系统键盘。 


114. 在键盘上点击字符,在密码行中输入内容。 


115. 然后点击完成按钮,完成内容的输入。 


116. 此时表单校验失败,字体变为红色,再次点击密码文本框。 


117. 然后通过键盘再次输入内容,这次输入更多的字符。 


118. 接着继续点击多次按键,输入更多的字符。 


119. 


120. 


121. 当输入一定长度的内容之后,点击完成按钮。 


122. 此时表单检验成功,红色文字消失。接着在下方的圆点处按下手指,并向上方拖动,查看下方的表单。 


123. 接着点击具有非空验证规则的表单行,测试非空的验证规则。 


124. 直接点击键盘上的完成按钮,观察表单的验证效果。 


125. 表单验证失败,并在表单行的下方,插入了一个标签行,用来显示错误信息。 


126. 接着点击键盘上的按键,输入一个字符。 


127. 此时,表单实时验证成功,错误标签被删除。再次点击键盘上的完成按钮,关闭键盘。 


128. 点击底部的按钮,可以检验表单中的所有元素。 


本文整理自:《app开发中的神兵利器》,真正的[手把手]教学模式,用最快的速度上手iOS开发,苹果商店App Store免费下载:https://itunes.apple.com/cn/app/id1209739676,或扫描本页底部的二维码。课程配套素材下载地址:资料下载



2015-09-28 10:13:08 ddwhan0123 阅读数 2961

转载请注明出处:王亟亟的大牛之路

iOS的滑动解锁你的心系列(张翰梗)一直是个人觉得蛮好的看的一个东西,然后今天就把这样的一个控件应用到我们今天的Demo中让他滑动解锁。

样式是这样的:出处

这里写图片描述

初始化
这里写图片描述

滑好后
这里写图片描述

包目录:
这里写图片描述


流程–用户打开App–输入账号密码–滑动登录–正确/错误–登陆成功提示/弹出对话框。

很普遍的登陆流程,只是在具体实现上做一些改变,摆脱单一的登录,注册按钮等。

MainActivity:

public class MainActivity extends AppCompatActivity implements SlideBar.OnTriggerListener,OnTouchListener{
    SlideBar slideToUnLock;
    IconEditText users,password;
    String User,Password;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        slideToUnLock = (SlideBar)findViewById(R.id.slideBar);
        users=(IconEditText)findViewById(R.id.user);
        password=(IconEditText)findViewById(R.id.password);

        slideToUnLock.setOnTouchListener(this);
        slideToUnLock.setOnTriggerListener(this);
    }

    @Override
    public void onTrigger() {
        Toast.makeText(this, getResources().
                getString(R.string.unlock_string), Toast.LENGTH_SHORT).show();
    }

    void logic(){
        User=users.getEditText().getText().toString();
        Password=password.getEditText().getText().toString();
        if(!User.equals("wjj")||!Password.equals("123")){
            dialog();
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int action=event.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                logic();
                break;
        }
        return false;
    }

    public void dialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
         builder.setMessage("이 잘못된 비밀번호");
         builder.setTitle("참고 소식");
         builder.setPositiveButton("알았어.", new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 dialog.dismiss();
             }
         });
         builder.create().show();
         }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


}

主布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:widget="http://schemas.android.com/apk/res-auto"
    xmlns:prvandroid="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="@drawable/bg">



        <RelativeLayout
            android:layout_marginLeft="40dp"
            android:layout_marginRight="40dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_centerVertical="true"
            android:layout_centerHorizontal="true">

            <logdemo.wjj.com.logdemo.Custom.IconEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColorHint="#ffffff"
                widget:hint="@string/user_name"
                widget:iconSrc="@mipmap/users"
                android:id="@+id/user"
                widget:isPassword="false"
                android:background="@drawable/layout_bg">
            </logdemo.wjj.com.logdemo.Custom.IconEditText>

            <logdemo.wjj.com.logdemo.Custom.IconEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColorHint="#ffffff"
                widget:hint="@string/password"
                widget:iconSrc="@mipmap/lock"
                android:id="@+id/password"
                widget:isPassword="true"
                android:layout_below="@id/user"
                android:layout_marginTop="30dp"
                android:background="@drawable/layout_bg">
            </logdemo.wjj.com.logdemo.Custom.IconEditText>
        </RelativeLayout>
    <logdemo.wjj.com.logdemo.Custom.SlideBar
        android:id="@+id/slideBar"
        android:layout_width="@dimen/slide_bar_width"
        android:layout_height="@dimen/slide_bar_height"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="20dip"
        android:background="@drawable/layout_bg"
        prvandroid:MinVelocityXToUnlock="1500"
        prvandroid:MinDistanceToUnlock="240"
        prvandroid:LeftAnimationDuratioin="200"
        prvandroid:RightAnimationDuratioin="300">
        <logdemo.wjj.com.logdemo.Custom.GradientView
            android:id="@+id/gradientView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"
            android:layout_marginLeft="@dimen/gradient_view_margin_left"
            prvandroid:StringToShow="@string/slide_to_unlock_string"
            prvandroid:TextSize="@dimen/gradient_text_size"
            prvandroid:TextColor="@color/gradient_text_color"
            prvandroid:SlideColor="@color/gradient_slide_text_color"/>
    </logdemo.wjj.com.logdemo.Custom.SlideBar>
</RelativeLayout>

IconEditText:http://blog.csdn.net/ddwhan0123/article/details/48654681

SlideBar,GradientView就是我们主要实现滑动解锁你的心的类了。

public class GradientView extends View {


    private static final  String  TAG = "GradientView";
    private static final boolean DEBUG = false;
    private float   mIndex = 0;
    private Shader  mShader;
    private int     mTextSize;  
    private static final int mUpdateStep = 15;
    private static final int mMaxWidth = 40 * mUpdateStep; // 26*25 
    private static final int mMinWidth = 6 * mUpdateStep;  // 5*25
    int             mDefaultColor;
    int             mSlideColor;
    private ValueAnimator animator;
    private int mWidth,mHeight;
    private String mStringToShow;
    private Paint mTextPaint;
    private float mTextHeight;
    private Drawable mSlideIcon;
    private int mSlideIconHeight;
    private static final int mSlideIconOffSetTop = 2;

    private AnimatorUpdateListener mAnimatorUpdateListener = new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mIndex =Float.parseFloat(animation.getAnimatedValue().toString());
            // RadialGradient SweepGradient
            mShader = new LinearGradient(mIndex - 20 * mUpdateStep, 100,
                    mIndex, 100, new int[] { mDefaultColor, mDefaultColor, mDefaultColor,mSlideColor,
                    mSlideColor, mDefaultColor, mDefaultColor, mDefaultColor }, null,
                    Shader.TileMode.CLAMP);

            postInvalidate();

        }
    };

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


    public GradientView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GradientView);
        mStringToShow = a.getString(R.styleable.GradientView_StringToShow) ;
        mTextSize = (int)a.getDimension(R.styleable.GradientView_TextSize, 40);
        mDefaultColor = a.getColor(R.styleable.GradientView_TextColor, Color.GRAY);
        mSlideColor = a.getColor(R.styleable.GradientView_SlideColor, Color.WHITE);
        mSlideIcon = context.getResources().getDrawable(R.drawable.slide_icon);
        mSlideIconHeight = mSlideIcon.getMinimumHeight();
        a.recycle();

        animator = ValueAnimator.ofFloat(mMinWidth,mMaxWidth);
        animator.setDuration(1800);
        animator.addUpdateListener(mAnimatorUpdateListener);
        animator.setRepeatCount(Animation.INFINITE);//repeat animation
        animator.start();


        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(mSlideColor);
        mTextPaint.setTextSize(mTextSize); 
        mTextPaint.setTextAlign(Paint.Align.CENTER);

        mTextHeight = mTextPaint.ascent();

        setFocusable(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if(DEBUG)
        Log.w(TAG, "b onDraw()");
        mTextPaint.setShader(mShader);
        canvas.drawBitmap(((BitmapDrawable) mSlideIcon).getBitmap(), 20, mHeight
                / 2 - mSlideIconHeight / 2 + mSlideIconOffSetTop, null);
        canvas.drawText(mStringToShow, mWidth / 2, mHeight / 2 - mTextHeight
                / 2 - mSlideIconOffSetTop, mTextPaint); // slide_unlock
    }


    public void stopAnimatorAndChangeColor() {
        Log.w(TAG, "stopGradient");
        animator.cancel();
        //reset
        mShader = new LinearGradient(0, 100, mIndex, 100,
                new int[] {mSlideColor, mSlideColor},
                null, Shader.TileMode.CLAMP);
        invalidate();
    }

    public void startAnimator() {
        if(DEBUG)
        Log.w(TAG, "startGradient");
        animator.start();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
    }

    public void resetControl(){
        animator.start();
        this.setX(0);
        invalidate();
    }
}

SlideBar

public class SlideBar extends RelativeLayout {

    private static final String TAG = "SlideBar";
    private static final boolean DEBUG = false;

    GradientView mGradientView ;
    private int gradientViewStartX;
    private float mEventDownX;
    private float mGradientViewIndicateLeft;
    private OnTriggerListener mOnTriggerListener;
    private VelocityTracker mVelocityTracker = null;
    private int mMinVelocityXToUnlock;
    private int mMinDistanceToUnlock;
    private int mLeftAnimationDuration;
    private int mRightAnimationDuration;
    private ObjectAnimator animLeftMoveAnimator;
    private ObjectAnimator animRightMoveAnimator;
    private static final int MaxDistance = 400;

    public interface OnTriggerListener {
         void onTrigger();
    }

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

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

    private void initView(Context context,AttributeSet attrs){
        gradientViewStartX = context.getResources().
                getDimensionPixelSize(R.dimen.gradient_view_margin_left) + 8;
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideBar);
        mMinVelocityXToUnlock = a.getInt(R.styleable.SlideBar_MinVelocityXToUnlock,2000) ;
        mMinDistanceToUnlock = a.getInt(R.styleable.SlideBar_MinDistanceToUnlock,300) ;
        mLeftAnimationDuration = a.getInt(R.styleable.SlideBar_LeftAnimationDuratioin,250) ;
        mRightAnimationDuration = a.getInt(R.styleable.SlideBar_RightAnimationDuratioin,300) ;
        a.recycle();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getActionMasked();
        boolean handled = false;

        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }

        mVelocityTracker.addMovement(event);

        switch (action) {
            case MotionEvent.ACTION_POINTER_DOWN:
            case MotionEvent.ACTION_DOWN:
                if (DEBUG) Log.v(TAG, "*** DOWN ***");
                handleDown(event);
                handled = true;
                break;

            case MotionEvent.ACTION_MOVE:
                if (DEBUG) Log.v(TAG, "*** MOVE ***");
                handleMove(event);
                handled = true;
                break;

            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_UP:
                if (DEBUG) Log.v(TAG, "*** UP ***");
                handleUp(event);
                handled = true;
                break;

            case MotionEvent.ACTION_CANCEL:
                if (DEBUG) Log.v(TAG, "*** CANCEL ***");
                handled = true;
                break;

        }
        invalidate();
        return handled ? true : super.onTouchEvent(event);
    }


    public void handleUp(MotionEvent event) {

        Log.v(TAG, "handleUp,mIndicateLeft:" + mGradientViewIndicateLeft);
        //1. 如果用户滑动一些距离,解锁
        if(mGradientViewIndicateLeft >= mMinDistanceToUnlock){
            unlockSuccess();
            return;
        }
        //2. 如果用户滑动很快,解锁
        if(velocityTrigUnlock()){
            return;
        }
        resetControls();
    }

    /**
     * 另一种方式来解锁,如果用户滑动非常快
     */
    private boolean velocityTrigUnlock() {
        final VelocityTracker velocityTracker = mVelocityTracker;
        velocityTracker.computeCurrentVelocity(1000);

        int velocityX = (int) velocityTracker.getXVelocity();

        Log.v(TAG, "velocityX:" + velocityX);

        if(velocityX > mMinVelocityXToUnlock){
            unlockSuccess();
            return true;
        }

        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
        return false;
    }


    private void unlockSuccess() {
        mOnTriggerListener.onTrigger();
        animRightMoveAnimator = ObjectAnimator.ofFloat(mGradientView, "x",mGradientView.getX(), MaxDistance)
                .setDuration(mRightAnimationDuration);
        animRightMoveAnimator.start();
    }


    private void handleMove(MotionEvent event) {

        mGradientViewIndicateLeft = event.getX() - mEventDownX + gradientViewStartX;
        if(mGradientViewIndicateLeft <= gradientViewStartX){
            mGradientViewIndicateLeft = gradientViewStartX;     
        }
        mGradientView.setX(mGradientViewIndicateLeft);
    }


    private void handleDown(MotionEvent event) {
        mEventDownX = event.getX();
        if(mGradientView == null){
            mGradientView = (GradientView) findViewById(R.id.gradientView);
        }   
        mGradientView.stopAnimatorAndChangeColor();

    }

    public void setOnTriggerListener(OnTriggerListener listener) {
        mOnTriggerListener = listener;
    }

    private void resetControls(){
        mGradientView.startAnimator();
        animLeftMoveAnimator = ObjectAnimator.ofFloat(mGradientView, "x", mGradientView.getX(),gradientViewStartX).setDuration(mLeftAnimationDuration);
        animLeftMoveAnimator.start();
    }

}

attrs:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="IconEditText">
        <attr name="iconSrc" format="reference" />
        <attr name="isPassword" format="boolean" />
        <attr name="hint" format="string"/>
    </declare-styleable>

    <declare-styleable name="GradientView">
        <attr name="StringToShow" format="reference"/>
        <attr name="TextSize" format="dimension"/>
        <attr name="TextColor" format="integer"/>
        <attr name="SlideColor" format="integer"/>
    </declare-styleable>


    <declare-styleable name="SlideBar">
        <attr name="MinVelocityXToUnlock" format="integer"/>
        <attr name="MinDistanceToUnlock" format="integer"/>
        <attr name="LeftAnimationDuratioin" format="integer"/>
        <attr name="RightAnimationDuratioin" format="integer"/>
    </declare-styleable>

</resources>

源码地址:http://download.csdn.net/detail/ddwhan0123/9143841

2015-04-27 13:13:24 zhaoguodongios 阅读数 1083

    

   //---验证手机号的UIBtutton--

    self.submitBtn = [UIButton buttonWithType:(UIButtonTypeCustom)];

    self.submitBtn.frame = CGRectMake(0, self.undoView.frame.origin.y+self.undoView.frame.size.height, self.view.frame.size.width, 35);

    self.submitBtn.backgroundColor = [UIColor colorWithHexString:@"47a5d6"];

    //self.submitBtn.alpha = 0.5;

    [self.submitBtn setTitle:@"发送" forState:(UIControlStateNormal)];

    [self.submitBtn addTarget:self action:@selector(didBtnAction) forControlEvents:(ValidationEmailFormat)];

//邮箱地址

    self.emailFT = [[UITextField alloc] initWithFrame:CGRectMake(30, lineView.frame.origin.y+lineView.frame.size.height + 15, self.view.frame.size.width-60, 40)];

    self.emailFT.backgroundColor = [UIColor colorWithHexString:@"f8f8f8"];

    self.emailFT.placeholder = @"您的手机号!";

    self.emailFT.font = [UIFont systemFontOfSize:17.0];

    self.emailFT.clearsOnBeginEditing = YES;

    self.emailFT.textAlignment = NSTextAlignmentCenter;

    [self.view addSubview:self.emailFT];



//[Dubai]验证手机号是否正确

- (void)ValidationEmailFormat

{

    

    NSString *mobileRegex = @"^((13[0-9])|(147)|(170)|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";

    NSPredicate *mobileTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",mobileRegex];

    BOOL n = [mobileTest evaluateWithObject:self.emailFT.text];

    if (n == NO) {

        [AlertVC showWithMessage:@"手机号格式不正确!"];

         self.navigationItem.rightBarButtonItem.enabled = YES;

        [self removeLoadingView];

        [self.timerTT invalidate];

        

    }else{

        [self.timerTT fire];

        //[self removeLoadingView];

        [self closeVC];

        self.navigationItem.rightBarButtonItem.enabled = YES;

    

    }

}


2017-12-14 00:35:33 weixin_33856370 阅读数 83

###开篇 我们登录简书的时候就会看到如下类似的验证方式,个人还是很喜欢这种验证方式的,想着如果把它自如自己设计的软件中还是不错的,但是我们要怎么实现这种验证效果呢,今天就来介绍一下。

####他是怎么做的呢? 作为一个好奇宝宝类型的开发,从开始见到他,就觉得这个方式不错,酷炫,仔细想想可能包含二次验证,安全性可能还可以,见了斗鱼的那个背景是广告的验证方式,简直刷新了三观,验证码也能做广告了!后来仔细找了一下,原来我们可以通过一个第三方工具来实现它,这就是极验验证。 ####介绍 首先我们来看一下他的逻辑,这里我们先放上他的官网地址和iOS版的开发文档。

下面我们看一下极验验证文档中给的实现流程图

从上图中可以看到,在JS与用户交互中,与极验的服务器和我们自己的服务器进行两次验证,在验证方式的安全上有了一定的保证。
我们注册登录后台后可以在个性定制了设置自己想要的图片甚至可以使用高级定制根据自己的网站或者APP的风格去定制验证的样式和图片。 阅读了他的官方文档之后,觉得他使用还挺方便的,不好的就是,不像许多的第三方那样,无法完全摆脱后台,单独我们移动端自己去尽情的尝试,必须和后台服务器相结合。 有人会说,你一个移动端做什么验证登录,苹果的风格不是注重简单和实用性么,但是这种验证风格在不同的环境中还是有其用武之地的,重点是用它帅啊(傲娇)。 ####看代码 就像上文中说的,他无法摆脱服务器进行自己的尝试,所以就只能先看下官方提供的代码了。官方代码地址传送门在这里吐槽一下,如果能像融云那样,利用网页版与移动端就行交互自己试验就比较理想了。

首先我们创建一个工程的时候要把那两个静态库加入到项目中,然后,将GTFramework.framework项目以Static Library的方式进行引用。将所需的GTFramework.framework拷贝到工程所在文件夹下。在 TARGETS->Build Phases-> Link Binary With Libaries中点击“+”按钮,在弹出的窗口中点击“Add Other”按钮,选择GTFramework.framework文件添加到工程中。[add GTframework to 'Link Binary With Libraries']。 具体的使用方法相信官方的在线文档里已经讲得足够详细了,由于不能自己全部试验,后台又有别的事,这里只能先简单介绍这些了,相信大家的聪明才智,只要有了方向,别的都不是问题了,以后如果用到了,再做个详细的使用教程。 ####后记 欢迎使用过这个下伙伴们,留言使用过程中遇到的坑,希望对想做这个但又不知道怎么下手的小伙伴有所帮助。

2019-10-10 20:47:11 RachelCSDN 阅读数 984

考察的点有两个,一个是对手机号格式和验证码格式的验证,一个是对验证码获取功能的验证。
基本原理:验证码1分钟内只能发一次,有效期10分钟。验证码是后台Java代码生成的,然后验证码生成时间和此验证码会保存在数据库的验证码表里面,同时通过短信形式发给手机,用户输入短信验证码并提交后,是Java代码拿到此验证码和库表的验证码进行时间和内容比对的。比对内容一致且时间差少于10分钟,就通过。
在这里插入图片描述
1.冒烟测试(通过性测试),测试注册功能能否正常使用
• 输入未被注册过的正确的手机号码,点击获取验证码,查看手机是否收到短信。
• 收到短信后输入验证码,点击注册按钮,查看是否注册成功,去数据库检查数据的正确性。
若测试成功后进行非通过性测试

2.输入无效等价类手机号
• 输入10位数字,是否有相应提示
• 输入12位数字,是否有相应提示
• 输入11位数字,获取验证码按钮能否点击,是否会发出验证码
• 输入手机号位中含中文、字母、特殊字符、表情符,是否有相应提示
• 输入手机号位中含空格,点击获取验证码,是否有相应提示
• 输入手机号为空,获取验证码能否被点击,是否有相应提示
• 输入已注册过的手机号,获取验证码以后,是否可以直接登录
• 输入欠费或停机的手机号,点击获取验证码,能否获取到验证码

3.获取验证码验证
前提:输入手机号正确
• 获取验证码按钮能否被点击
• 点击获取验证码按钮,发送了验证码以后,获取验证码按钮是否会变为灰色的重新获取并且一分钟内不能再点击
• 获取验证码按钮变为重新获取以后是否有一分钟倒计时显示,且倒计时显示正确,一分钟以后恢复为获取验证码按钮。
• 1分钟后再点击发送验证码,得到新验证码后,输入前一个旧验证码应该提示验证码错误;输入当前最新验证码,成功通过。
• 10分钟后使用,系统应该提示验证码已失效。

4.输入无效等价类验证码
前提:输入的手机号正确
• 输入时间过期的正确的验证码,点击注册按钮,是否提示验证码错误
• 输入6位错误的验证码,点击注册按钮,是否提示验证码错误
• 输入5位的验证码,点击注册按钮,是否提示验证码错误
• 输入7位的验证码,点击注册按钮,是否提示验证码错误
• 输入验证码中带有中文、字母、特殊字符、表情符,点击注册按钮,是否提示验证码错误
• 输入验证码中含有空格,点击注册按钮,是否提示验证码错误
• 输入验证码为空,点击注册按钮,是否提示请输入验证码

5.网络测试
1.在无网状态时点击获取验证码按钮,能否获取验证码
2.在无网状态时注册按钮能否点击并实现跳转
3.在弱网状态、网络间切换时注册功能能否正常使用
4.在弱网状态时,检查数据是否会一直处于提交中的状态,有无超时限制。如遇数据交换失败时要给予提示。

6.UI界面测试
1.界面风格、文字、图片、颜色的风格是否美观统一。
2.界面的按钮、控件、菜单的布局是否合理、是否美观,该对齐的要对齐,该居中的要居中
3.界面是否有错字、别字
4.文字描述准确,无歧义。

7.兼容性测试用例:

对APP的兼容性测试
1.不同操作系统的手机(Android与iOS)的兼容性
2.不同品牌手机的兼容性
3.不同分辨率手机的兼容性
4.网络的兼容性:2G\3G\4G\WIFI,弱网下、断网时
5.app跨版本的兼容性。

对web的兼容性测试
1.不同硬件平台(PC、手机、平板等)
2.不同操作系统(linux、windows、macOS、android、ios等)
3.浏览器兼容性(IE、360、搜狗、chrome、火狐等)