Android實用View系列-----仿微信支付寶等風(fēng)格的支付密碼輸入框的實現(xiàn)

開始閱讀本篇文章之前先來說一下使用場景吧旅挤,我們知道如今移動支付已經(jīng)占據(jù)我們?nèi)粘VЦ兜?0%的份額,以微信支付和支付寶支付為主伞鲫,也越來越多的APP開始添加支付模塊粘茄,不管使用哪種支付有一個步驟是少不了的,那就是輸入支付密碼(指紋支付再此就不做討論了哦)榔昔,所以今天來給大家?guī)硪黄远x支付密碼輸入框的設(shè)計和實現(xiàn)方式驹闰,同時記錄自己工作中遇到的問題及解決辦法。


github源碼地址傳送門


按照慣例我們先看看微信和支付寶支付密碼輸入框的樣式吧
微信支付密碼
支付寶支付密碼
看到這樣的效果相信很多開發(fā)者第一反應(yīng)就是先網(wǎng)上搜一下看看有沒有現(xiàn)成的(哈哈撒会,我也不例外哦)嘹朗,因為這都是簡單的一些view不涉及動畫所以網(wǎng)上相關(guān)例子還是很多的,我這邊總結(jié)了一下大致可以分為一下幾類

1诵肛、通過布局的方式:

在布局里邊放置6個EditView,在每個輸入框中間再放置一個view用于設(shè)置中間分割線屹培,每個EditVIew只允許輸入一個字符,然后對每個進(jìn)行監(jiān)聽怔檩,一個密碼輸入完之后讓另一個EditView獲取焦點褪秀,以此類推就可以大致實現(xiàn)圖中的效果了(這樣確實可以實現(xiàn),實現(xiàn)起來也很簡單薛训,但是代碼量不少媒吗,而且這種方式是不是顯得逼格不夠高或者沒有逼格吶)

2、完全自定義view(繼承View):

這個就稍微復(fù)雜一點乙埃,大致流程是闸英,先監(jiān)聽觸摸事件锯岖,按下時彈出鍵盤,然后對軟鍵盤進(jìn)行監(jiān)聽甫何,獲取每次點擊鍵盤對應(yīng)的字符串出吹,然后在onDraw方法里邊畫6個圓,在繪制外邊框辙喂,然后是中間的分割線捶牢。這里邊有個問題就是每次都要對軟鍵盤進(jìn)行監(jiān)聽取值等一系列操作,加上Android機型眾多整不好哪塊軟鍵盤就出問題了吶巍耗。(雖然有逼格秋麸,但是不實用哦)


欲步又止

3、繼承自EditView實現(xiàn)自定義view:

大致流程和上一種差不多芍锦,不過我們不需要對軟鍵盤進(jìn)行處理了,少了很多繁瑣及兼容性的操作竹勉,同時又不失逼格,哈哈娄琉。

看到以上三種實現(xiàn)方式想必你大概已經(jīng)知道我們要使用哪種方式實現(xiàn)了次乓,沒錯就是集成EditView的自定義view,這樣我們還可以使用很多EditView的屬性哦

開發(fā)前先整理一下實現(xiàn)步驟:

1、繪制外邊框(可以是直角也可以是圓角孽水,設(shè)計師要什么我們就給他什么)
2票腰、繪制密碼之間的分割線(豎線)

3、繪制實心圓代替輸入的字符
4女气、對輸入字符進(jìn)行監(jiān)聽杏慰,便于擴展處理
5、實現(xiàn)一些常用的外部接口方法調(diào)用

具體實現(xiàn)

1炼鞠、繪制外邊框:
要想繪制邊框我們首先要知道view的寬高缘滥,通過onSizeChanged方法去初始化寬高等數(shù)據(jù),然后繪制圓角矩形(默認(rèn)讓他矩形顯示直接傳入圓角半徑為0即可)

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        height = h;
        width = w;

        divideLineWStartX = w / maxCount;

        startX = w / maxCount / 2; //第一個圓心的x坐標(biāo)
        startY = h / 2; //第一個圓心的y坐標(biāo)

        bottomLineLength = w / (maxCount + 2);

        rectF.set(0, 0, width, height);

    }
RectF rectF = new RectF()
rectF.set(0, 0, width, height);

canvas.drawRoundRect(rectF, rectAngle, rectAngle, borderPaint);
2谒主、繪制密碼之間的分割線:
既然是分割線肯定是等均分的朝扼,假設(shè)我們的密碼最大輸入maxCount=6,那么我們只需畫5個分割線就可以了霎肯,分割線坐標(biāo)的計算
計算分割線的起點和終點的坐標(biāo)
通過循環(huán)畫出每個分割線
for (int i = 0; i < maxCount - 1; i++) {
            canvas.drawLine((i + 1) * divideLineWStartX,
                    0,
                    (i + 1) * divideLineWStartX,
                    height,
                    divideLinePaint);
        }

完成這一步我們先運行一下看看邊框效果吧

模擬器上運行效果
3擎颖、繪制實心圓代替輸入的字符:

這里需要監(jiān)聽EditView的輸入,重寫onTextChanged方法獲取輸入字符的長度,然后計算每個圓圓心的坐標(biāo)位置

        //第一個圓心的x坐標(biāo)
        startX = w / maxCount / 2;
        //第一個圓心的y坐標(biāo)
        startY = h / 2;

    /**
     * 畫密碼實心圓
     *
     * @param canvas
     */
    private void drawPsdCircle(Canvas canvas) {
        for (int i = 0; i < textLength; i++) {
            canvas.drawCircle(startX + i * 2 * startX,
                    startY,
                    radius,
                    circlePaint);
        }
    }

寫到這里的時候是不是感覺樣式問題已經(jīng)完成的差不多了观游,運行以來輸入幾個字符串一看搂捧,MD出問題了(看圖說話)


Paste_Image.png

從圖中可以看出是繪制了相應(yīng)的實心圓,但是自帶的底部線懂缕、光標(biāo)允跑、字符還在,要是拿這個去交差絕逼會被產(chǎn)品罵死。


產(chǎn)品的內(nèi)心獨白

出現(xiàn)這個問題肯定是代碼的問題嘍聋丝,我們根據(jù)問題去一個一個解決荤崇,首先給view設(shè)置一個透明的背景色,然后隱藏光標(biāo)潮针,再跑一下看看
        this.setBackgroundColor(Color.TRANSPARENT);
        this.setCursorVisible(false);
Paste_Image.png

這次底部的線和光標(biāo)都見了,但是輸入的字符還在倚喂,這又是什么問題每篷??端圈?我們明明重寫了onDraw方法焦读,怎么還會出現(xiàn)原來的字符吶,等等舱权。矗晃。。對啊宴倍,我們只是重寫张症,他肯定還有自己的方法,我們只要把EditView內(nèi)部重繪的方法干掉不就行了鸵贬,想到這里喜出望外俗他,拿跟辣條先壓壓驚,在ondraw方法中這樣做

    @Override
    protected void onDraw(Canvas canvas) {
        //不刪除的話會默認(rèn)繪制輸入的文字
       // super.onDraw(canvas);
    }

你沒看錯阔逼,就是這一行代碼注釋掉就ok兆衅,
至于是為什么你肯定知道,
不注釋的話在我們重寫之前他已經(jīng)調(diào)用了內(nèi)部方法
去繪制輸入的字符了嗜浮,
我們在重寫后雖然我們的方法生效了羡亩,
但它的方法也生效了哦。

此時壓抑不住內(nèi)心的小激動趕緊運行起來看看(哈哈危融,完美解決問題)


Paste_Image.png

至此主要功能已經(jīng)完成畏铆,剩下的需要去封裝一些方法供外部調(diào)用,我這里已經(jīng)封裝幾個方法专挪,我們知道這樣設(shè)置支付密碼的頁面一般有兩個:一個設(shè)置密碼及志,一個重新設(shè)置密碼,按照正常的邏輯我們?nèi)ケO(jiān)聽這個密碼輸入框寨腔,輸入密碼之后進(jìn)行比較看是否相等就完事了速侈,為了方便以后使用不要每次自己再去寫一大堆監(jiān)聽方法,我們直接在內(nèi)部封裝好是不是對以后使用起來更方便一點吶

   /**
     * 密碼比較監(jiān)聽
     */
    public interface onPasswordListener {
        void onDifference();
        void onEqual(String psd);
    }

    //使用者需要調(diào)用的方法
    public void setComparePassword(String comparePassword, onPasswordListener listener) {
        mComparePassword = comparePassword;
        mListener = listener;
    }

這里就直接上代碼了,代碼通俗易懂

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        textLength = text.toString().length();

        if (mComparePassword != null && textLength == maxCount) {
            if (TextUtils.equals(mComparePassword, getPasswordString())) {
                mListener.onEqual(getPasswordString());
            } else {
                mListener.onDifference();
            }
        }
        invalidate();

    }

實際使用中我們這樣設(shè)置(是不是瞬間感覺用的過程簡單了很多)

        passwordInputView.setComparePassword("123456", new PayPsdInputView.onPasswordListener() {
            @Override
            public void onDifference() {
                // TODO: 2017/5/7   和上次輸入的密碼不一致  做相應(yīng)的業(yè)務(wù)邏輯處理 
                Toast.makeText(MainActivity.this,"兩次密碼輸入不同",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onEqual(String psd) {
                // TODO: 2017/5/7 兩次輸入密碼相同迫卢,那就去進(jìn)行支付樓 
                Toast.makeText(MainActivity.this,"密碼相同"+psd,Toast.LENGTH_SHORT).show();

            }
        });

文章到此本應(yīng)該結(jié)束了倚搬,可是我們UI設(shè)計師給出的效果圖不是這樣子的,不按常理出牌(心中頓時飄過一萬只草泥馬)

草泥馬

來看看我們的效果圖


Paste_Image.png
大哥乾蛤,算了算了每界,還是去給他實現(xiàn)一下吧

他不按常量出牌捅僵,不過這也是他們一貫的作風(fēng),既然他們要這樣的效果那我們就去做嘍眨层,整個流程還是一樣的庙楚,唯一的不同就是外邊框和密碼之間的分割線變成了底部間斷的線,這肯定難不倒我們啦趴樱,不就是畫六條線嗎馒闷,每根線的起點終點坐標(biāo)和上邊圓心左邊計算差不多,就不多描述了看代碼最實在

    /**
     * 畫底部顯示的分割線
     *
     * @param canvas
     */
    private void drawBottomBorder(Canvas canvas) {

        for (int i = 0; i < maxCount; i++) {
            cX = startX + i * 2 * startX;
            canvas.drawLine(cX - bottomLineLength / 2,
                    height,
                    cX + bottomLineLength / 2,
                    height, bottomLinePaint);
        }
    }

項目至此完美收工叁征,看看效果吧


MD你要的效果給你.png

最后總結(jié)

以上微信支付密碼和我們這種現(xiàn)實效果我都封裝在PayPsdInputView中了纳账,可以根據(jù)需求切換不同的樣式,


Paste_Image.png

如果以后還要其他的支付密碼輸入的樣式的話同樣會添加進(jìn)來的捺疼,目的只有一個--------->下次開發(fā)省時省力疏虫。


兩種樣式供你選擇

番外篇

我相信看到這里肯定有一部分小伙伴會說MDZZ,這不就是簡單的畫矩形、畫圓啤呼、畫線嗎卧秘,有什么好寫的,誰都會做官扣。我想說的是你們說的沒錯斯议,涉及的知識點是很簡單,但是不要忘了醇锚,麻雀雖小五腑俱全哼御,真正你去一行一行敲的時候你會發(fā)現(xiàn)有很多不曾注意過的問題都會浮出水面。只是單純的會幾個知識點其實沒什么卵用焊唬,把所學(xué)知識點運用起來重組成一個功能模塊的時候你才算真正的掌握恋昼。


來,老表赶促,抽根煙液肌,平復(fù)一下暴躁的心情

謹(jǐn)以此篇來記錄自己項目中遇到的問題,獻(xiàn)給需要類似功能的小伙伴們鸥滨。如果你有好的建議歡迎評論指出嗦哆,大家一起討論、學(xué)習(xí)婿滓、進(jìn)步老速!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市凸主,隨后出現(xiàn)的幾起案子橘券,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旁舰,死亡現(xiàn)場離奇詭異锋华,居然都是意外死亡,警方通過查閱死者的電腦和手機箭窜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門毯焕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人磺樱,你說我怎么就攤上這事芥丧。” “怎么了坊罢?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長擅耽。 經(jīng)常有香客問我活孩,道長,這世上最難降的妖魔是什么乖仇? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任憾儒,我火速辦了婚禮,結(jié)果婚禮上乃沙,老公的妹妹穿的比我還像新娘起趾。我一直安慰自己,他們只是感情好警儒,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布训裆。 她就那樣靜靜地躺著,像睡著了一般蜀铲。 火紅的嫁衣襯著肌膚如雪边琉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天记劝,我揣著相機與錄音变姨,去河邊找鬼。 笑死厌丑,一個胖子當(dāng)著我的面吹牛定欧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播怒竿,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼砍鸠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了耕驰?” 一聲冷哼從身側(cè)響起睦番,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后托嚣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巩检,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年示启,在試婚紗的時候發(fā)現(xiàn)自己被綠了兢哭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡夫嗓,死狀恐怖迟螺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舍咖,我是刑警寧澤矩父,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站排霉,受9級特大地震影響窍株,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜攻柠,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一球订、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瑰钮,春花似錦冒滩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至苟耻,卻和暖如春士八,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梁呈。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工婚度, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人官卡。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓蝗茁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親寻咒。 傳聞我的和親對象是個殘疾皇子哮翘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

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