像微信支付密碼控件,在app中是一個多么司空見慣的功能。最近,項(xiàng)目需要這個功能,于是乎就實(shí)現(xiàn)這個功能。
老樣子,投籃需要找準(zhǔn)角度,變成需要理清思路。對于這個"小而美"的控件,我們思路應(yīng)該這樣子。
Ⅰ、將要輸入密碼數(shù)量動態(tài)通過代碼加載出來。
Ⅱ、利用Gridview模擬產(chǎn)生一個輸入數(shù)字鍵盤,并且按照習(xí)慣從屏幕底部彈出來。
Ⅲ、對輸入數(shù)字鍵盤進(jìn)行事件監(jiān)聽,將這個輸入數(shù)字填入到這個密碼框中,并且當(dāng)您輸入密碼長度一致的時(shí)候,進(jìn)行事件回調(diào)。
這個思維導(dǎo)圖應(yīng)該是這樣的:

首先,我們要根據(jù)需求動態(tài)加載密碼框,相應(yīng)的代碼如下:
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; }我們這里密碼長度設(shè)置為6,將這6個密碼框控件添加到盛放這些控件的父控件中去,并且每個密碼控件中都有一個分隔控件。并且把每個密碼輸入控件放入控件數(shù)組,以便我們進(jìn)行接下來的操作。
然后了,我們利用Gridview產(chǎn)生一個12宮格的模擬數(shù)字鍵盤,這樣模擬鍵盤樣子是這樣的:

源代碼應(yīng)該是這樣的:
/** * 加載數(shù)據(jù)的代碼 */ private void initData() { /* 初始化按鈕上應(yīng)該顯示的數(shù)字 */ 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) { // 點(diǎn)擊0~9按鈕 if (currentIndex >= -1 && currentIndex < 5) { // 判斷輸入位置――――要小心數(shù)組越界 tvList[++currentIndex].setText(valueList.get(position) .get("name")); } } else { if (position == 11) { // 點(diǎn)擊退格鍵 if (currentIndex - 1 >= -1) { // 判斷是否刪除完畢――――要小心數(shù)組越界 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; } 加載模擬鍵盤上的數(shù)據(jù)為0-9與x,然后將這個數(shù)據(jù)通過一個適配器將這些數(shù)據(jù)填充到這個Gridview控件。這些都是老司機(jī)的老套路。按照慣例,這個模擬鍵盤應(yīng)該從屏幕的底部彈出,我這里所做的就是將Gridview依附在popupwindow,然后在從屏幕的底部進(jìn)行彈出。相應(yīng)的代碼如下:
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); // 確定在界面中出現(xiàn)的位置 } @Override public void onWindowFocusChanged(boolean hasWindowFocus) { super.onWindowFocusChanged(hasWindowFocus); show(); }當(dāng)這個控件一加載的時(shí)候,就彈出。
最后,我們要做的就是監(jiān)聽模擬鍵盤,將這個模擬鍵盤的輸入填入到密碼框,說的貌似很高大上的,其實(shí)就是監(jiān)聽Gridview的onitemclick事件,相應(yīng)代碼如下:
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (position < 11 && position != 9) { // 點(diǎn)擊0~9按鈕 if (currentIndex >= -1 && currentIndex < 5) { // 判斷輸入位置――――要小心數(shù)組越界 tvList[++currentIndex].setText(valueList.get(position) .get("name")); } } else { if (position == 11) { // 點(diǎn)擊退格鍵 if (currentIndex - 1 >= -1) { // 判斷是否刪除完畢――――要小心數(shù)組越界 tvList[currentIndex--].setText(""); } } } } });如果用戶點(diǎn)擊數(shù)字0-9,就填入到密碼框中,如果是點(diǎn)擊退格鍵的話,就刪除所對應(yīng)密碼框的內(nèi)容??吹?jīng)],上文所用文本框數(shù)組列表派上了用場。這里值得指出,由于退格鍵點(diǎn)擊效果與眾不同,我這里應(yīng)用代碼設(shè)置他的樣式。
當(dāng)用戶最后一個密碼框輸入完成之后,就進(jìn)行輸入完成的回調(diào),相應(yīng)代碼為:
// 設(shè)置監(jiān)聽方法,在第6位輸入完成后觸發(fā) 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 = ""; // 每次觸發(fā)都要先將strPassword置空,再重新獲取,避免由于輸入刪除再輸入造成混亂 for (int i = 0; i < 6; i++) { strPassword += tvList[i].getText().toString().trim(); } if (pass!=null) { pass.inputFinish(); // 接口中要實(shí)現(xiàn)的方法,完成密碼輸入完成后的響應(yīng)邏輯 } } } });經(jīng)過一番折騰以后,大功告成了,最終效果如下:

源碼下載:http://xiazai.VeVB.COm/201608/yuanma/Android-MyPayUI(VeVB.COm).rar
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。
新聞熱點(diǎn)
疑難解答
圖片精選