Android 高仿微信支付密碼輸入控件

  像微信支付密碼控件,在app中是一個多麼司空見慣的功能。最近,項目須要這個功能,因而乎就實現這個功能。android

  老樣子,投籃須要找準角度,變成須要理清思路。對於這個"小而美"的控件,咱們思路應該這樣子。數組

  Ⅰ、將要輸入密碼數量動態經過代碼加載出來。微信

  Ⅱ、利用Gridview模擬產生一個輸入數字鍵盤,而且按照習慣從屏幕底部彈出來。app

  Ⅲ、對輸入數字鍵盤進行事件監聽,將這個輸入數字填入到這個密碼框中,而且當您輸入密碼長度一致的時候,進行事件回調。ide

  這個思惟導圖應該是這樣的:佈局

 

  首先,咱們要根據需求動態加載密碼框,相應的代碼以下:微信支付

for (int i = 0; i < 6; i++) {
            TextView textView = new TextView(context);
            android.widget.LinearLayout.LayoutParams layoutParams = new android.widget.LinearLayout.LayoutParams(
                    0, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT, 1);
            textView.setGravity(Gravity.CENTER);
            textView.setTransformationMethod(PasswordTransformationMethod.getInstance());
            textView.setTextSize(32);
            textView.setLayoutParams(layoutParams);
            ll_pwd.addView(textView);
            if (i != 5) {
                View view2 = new View(context);
                android.widget.LinearLayout.LayoutParams layoutParams1 = new android.widget.LinearLayout.LayoutParams(
                        1,
                        android.widget.LinearLayout.LayoutParams.MATCH_PARENT,
                        0);
                view2.setLayoutParams(layoutParams1);
                view2.setBackgroundColor(Color.parseColor("#999999"));
                ll_pwd.addView(view2);

            }
            tvList[i] = textView;
        }

  咱們這裏密碼長度設置爲6,將這6個密碼框控件添加到盛放這些控件的父控件中去,而且每一個密碼控件中都有一個分隔控件。而且把每一個密碼輸入控件放入控件數組,以便咱們進行接下來的操做。spa

  而後了,咱們利用Gridview產生一個12宮格的模擬數字鍵盤,這樣模擬鍵盤樣子是這樣的:code

  源代碼應該是這樣的:orm

     
       /**
     * 加載數據的代碼
     */
    private void initData() {
        /* 初始化按鈕上應該顯示的數字 */
        for (int i = 1; i < 13; i++) {
            Map<String, String> map = new HashMap<String, String>();
            if (i < 10) {
                map.put("name", String.valueOf(i));
            } else if (i == 10) {
                map.put("name", "");
            } else if (i == 11) {
                map.put("name", String.valueOf(0));
            } else if (i == 12) {
                map.put("name", "×");
            } else {
                map.put("name", "");
            }
            valueList.add(map);
        }
        gridView.setAdapter(adapter);
        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                if (position < 11 && position != 9) { // 點擊0~9按鈕
                    if (currentIndex >= -1 && currentIndex < 5) { // 判斷輸入位置————要當心數組越界
                        tvList[++currentIndex].setText(valueList.get(position)
                                .get("name"));
                    }
                } else {
                    if (position == 11) { // 點擊退格鍵
                        if (currentIndex - 1 >= -1) { // 判斷是否刪除完畢————要當心數組越界
                            tvList[currentIndex--].setText("");
                        }
                    }
                }
            }
        });
    }
        /**
           * GrideView的適配器
           */ 
    BaseAdapter adapter = new BaseAdapter() {
        @Override
        public int getCount() {
            return valueList.size();
        }

        @Override
        public Object getItem(int position) {
            return valueList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @SuppressWarnings("deprecation")
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = View.inflate(context, R.layout.item_gride, null);
                viewHolder = new ViewHolder();
                viewHolder.btnKey = (TextView) convertView
                        .findViewById(R.id.btn_keys);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            viewHolder.btnKey.setText(valueList.get(position).get("name"));
            if (position == 9||position==11) {
                viewHolder.btnKey.setBackgroundDrawable(Utils.getStateListDrawable(context));
                viewHolder.btnKey.setEnabled(false);
            }
            if (position == 11) {
                viewHolder.btnKey.setBackgroundDrawable(Utils.getStateListDrawable(context));
            }

            return convertView;
        }
    };
    
    
    /**
     * 存放控件
     */
    public final class ViewHolder {
        public TextView btnKey;
    }    
            

  加載模擬鍵盤上的數據爲0-9與x,而後將這個數據經過一個適配器將這些數據填充到這個Gridview控件。這些都是老司機的老套路。按照慣例,這個模擬鍵盤應該從屏幕的底部彈出,我這裏所作的就是將Gridview依附在popupwindow,而後在從屏幕的底部進行彈出。相應的代碼以下:

 

    View contentView = LayoutInflater.from(context).inflate(
                R.layout.layout_popupdemo, null);// 定義後退彈出框
        gridView = (GridView) contentView.findViewById(R.id.gv_keybord);// 泡泡窗口的佈局    
    popupWindow = new PopupWindow(contentView,
                ViewGroup.LayoutParams.MATCH_PARENT,// width

                ViewGroup.LayoutParams.WRAP_CONTENT);// higth
        popupWindow.setFocusable(false);
        popupWindow.setAnimationStyle(R.style.animation);
            //從底部彈出
  public void show() {
        popupWindow.showAtLocation(rl_bottom, Gravity.BOTTOM, 0, 0); // 肯定在界面中出現的位置
    }
    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        show();
    }

  當這個控件一加載的時候,就彈出。

  最後,咱們要作的就是監聽模擬鍵盤,將這個模擬鍵盤的輸入填入到密碼框,說的貌似很高大上的,其實就是監聽Gridview的onitemclick事件,相應代碼以下:

gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                if (position < 11 && position != 9) { // 點擊0~9按鈕
                    if (currentIndex >= -1 && currentIndex < 5) { // 判斷輸入位置————要當心數組越界
                        tvList[++currentIndex].setText(valueList.get(position)
                                .get("name"));
                    }
                } else {
                    if (position == 11) { // 點擊退格鍵
                        if (currentIndex - 1 >= -1) { // 判斷是否刪除完畢————要當心數組越界
                            tvList[currentIndex--].setText("");
                        }
                    }
                }
            }
        });

  若是用戶點擊數字0-9,就填入到密碼框中,若是是點擊退格鍵的話,就刪除所對應密碼框的內容。看到沒,上文所用文本框數組列表派上了用場。這裏值得指出,因爲退格鍵點擊效果不同凡響,我這裏應用代碼設置他的樣式。

  當用戶最後一個密碼框輸入完成以後,就進行輸入完成的回調,相應代碼爲:

    // 設置監聽方法,在第6位輸入完成後觸發
    public void setOnFinishInput(final OnPasswordInputFinish pass) {
        tvList[5].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) {
                if (s.toString().length() == 1) {
                    strPassword = ""; // 每次觸發都要先將strPassword置空,再從新獲取,避免因爲輸入刪除再輸入形成混亂
                    for (int i = 0; i < 6; i++) {
                        strPassword += tvList[i].getText().toString().trim();
                    }
                    if (pass!=null) {
                        pass.inputFinish(); // 接口中要實現的方法,完成密碼輸入完成後的響應邏輯                        
                    }
                }
            }
        });

 

  通過一番折騰之後,大功告成了,最終效果以下:

  項目地址爲:http://pan.baidu.com/s/1o88FK2A

相關文章
相關標籤/搜索