Android開發——本地驗證碼的簡易實現


0.  前言  

驗證碼無處不在。有人問我,你知道達芬奇password以下是什么嗎,對。答案就是達芬奇驗證碼。

驗證碼一個最基本的作用就是防止惡意暴力破解登錄,防止不間斷的登錄嘗試,事實上能夠在server端對該終端進行登錄間隔檢測。假設間隔太短能夠展示拒絕的姿態。可是還是本地驗證碼作用更加實在。能夠減輕server端的壓力。這篇將使用自己定義View來實現一個例如以下效果的簡易本地驗證碼。算是對自己定義View知識的復習吧。



1.  布局結構  

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myattribute="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.calvin.verification_code.MyView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="10dp"
        myattribute:text="0 0 0 0 "
        myattribute:textcolor="#000"
        myattribute:textsize="40sp"
        android:id="@+id/myView" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:hint="刷新后輸入"
        android:layout_below="@+id/myView"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:id="@+id/editText" />

    <Button
        android:text="確認"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/editText"
        android:layout_alignParentEnd="true"
        android:layout_marginEnd="10dp"
        android:id="@+id/button" />
</RelativeLayout>

在自己定義控件MyView中使用了自己定義屬性。面試的時候偶爾也會被問到,事實上並不難。這里使用文字內容、顏色和字號三個自己定義屬性。命名空間別忘了加。

自己定義屬性聲明僅僅須要在values文件夾下聲明一個xml文件就可以。文件名稱字不重要。重要的是這個name屬性,由於我們會在自己定義控件類中通過R.styleable.MyView來找到這個自己定義屬性聲明信息。

<?

xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyView"> <attr name="text" format="string"/> <attr name="textcolor" format="color"/> <attr name="textsize" format="dimension"/> </declare-styleable> </resources>


2.  自己定義View

看一下這個類的構造函數:

public MyView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
        for (int i = 0; i < a.getIndexCount(); i++) {
            int attr = a.getIndex(i);
            switch (attr) {
                case R.styleable.MyView_text:
                    mText = a.getString(attr);
                    break;
                case R.styleable.MyView_textcolor:
                    //二參為默認顏色
                    mTextColor = a.getColor(attr, Color.BLACK);
                    break;
                case R.styleable.MyView_textsize:
                    // 默認字體大小為16sp,TypeValue把sp轉化為px
                    mTextSize = a.getDimensionPixelSize(attr,
                            (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                                    16, getResources().getDisplayMetrics()));
                    break;
            }
        }
        a.recycle();

        mPaint = new Paint();
        mPaint.setTextSize(mTextSize);
        mBound = new Rect();
        //獲得繪制文本的寬和高
        mPaint.getTextBounds(mText, 0, mText.length(), mBound);

        this.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //生成一個隨機的四位數字,並發送一個自己定義廣播
                mText = randomText();
                postInvalidate();
            }

        });
    }

核心代碼就是解析自己定義屬性,並初始化一個畫筆。並把解析出來的字體大小設置給畫筆,設計點擊時間,使其被點擊后又一次隨機產生四位數字驗證碼,並使用postInvalidate()刷新界面。最后使用mBound記錄這個四位數文本的寬高。

 

2.  自己定義View類中的其它細節

@Override    
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = 0;
        int height = 0;
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        switch (specMode) {
            case MeasureSpec.EXACTLY:
                width = getPaddingLeft() + getPaddingRight() + specSize;
                break;
            case MeasureSpec.AT_MOST:
                width = getPaddingLeft() + getPaddingRight() + mBound.width();
                break;
        }
        //相同邏輯處理高
        setMeasuredDimension(width, height);
}

    @Override
    protected void onDraw(Canvas canvas) {
        mPaint.setColor(Color.YELLOW);
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

        mPaint.setColor(mTextColor);
        canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
        Random random = new Random();
        for(int i = 0; i <= 3; i++){
            int temp = random.nextInt(colors.length);
            mPaint.setColor(colors[temp]);
            mPaint.setStrokeWidth(3);
            canvas.drawLine(randomStartWidth(),randomStartHeight(),randomEndWidth(),randomEndHeight(),mPaint);
        }
    }

事實上主要還是measuredraw的過程了。

onMeasure()方法中最重要的邏輯應該就是處理MeasureSpec.AT_MOST的這樣的情況了。這時候前面的mBound.width()就起作用了。還有就是無論何種測量模式,都手動處理了padding的情況。

onDraw()方法中首先繪制了一個黃色矩形作為自己定義View的背景,接着依據自己定義屬性中的文字內容和顏色繪制四位數字,最后繪制四條噪聲直線。顏色隨機,而且起始位置和結束位置也是隨機產生的。

 

3.  實時改變維護的正確驗證碼

為了驗證用戶輸入的驗證碼的正確性,須要在MainActivity中維護一個變量。在用戶點擊自己定義View刷新驗證碼時,能夠實時改變這個變量的值。這里使用自己定義廣播實現。在生成一個隨機的四位數字,發送一個自己定義廣播。

Intent intent = new Intent();
intent.setAction("com.seu_calvin.update");
intent.putExtra("data", sb.toString());
getContext().sendBroadcast(intent);

接着在MainActivity注冊一個廣播接收者就可以取得此時的驗證碼信息,在用戶點擊確定按鈕后在拿到EditText中的值與其進行對照就可以。

這個邏輯還是比較簡單的。

筆者水平有限,假設有問題或者錯誤請多留言交流。

轉載請注明出處:http://blog.csdn.net/seu_calvin/article/details/70156547


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM