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

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

源代碼應(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;
}
加載模擬鍵盤(pán)上的數(shù)據(jù)為0-9與x,然后將這個(gè)數(shù)據(jù)通過(guò)一個(gè)適配器將這些數(shù)據(jù)填充到這個(gè)Gridview控件。這些都是老司機(jī)的老套路。按照慣例,這個(gè)模擬鍵盤(pán)應(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)這個(gè)控件一加載的時(shí)候,就彈出。
最后,我們要做的就是監(jiān)聽(tīng)模擬鍵盤(pán),將這個(gè)模擬鍵盤(pán)的輸入填入到密碼框,說(shuō)的貌似很高大上的,其實(shí)就是監(jiān)聽(tīng)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("");
}
}
}
}
});
如果用戶(hù)點(diǎn)擊數(shù)字0-9,就填入到密碼框中,如果是點(diǎn)擊退格鍵的話(huà),就刪除所對(duì)應(yīng)密碼框的內(nèi)容??吹?jīng)],上文所用文本框數(shù)組列表派上了用場(chǎng)。這里值得指出,由于退格鍵點(diǎn)擊效果與眾不同,我這里應(yīng)用代碼設(shè)置他的樣式。
當(dāng)用戶(hù)最后一個(gè)密碼框輸入完成之后,就進(jìn)行輸入完成的回調(diào),相應(yīng)代碼為:
// 設(shè)置監(jiān)聽(tīng)方法,在第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)過(guò)一番折騰以后,大功告成了,最終效果如下:

源碼下載:http://xiazai.jb51.net/201608/yuanma/Android-MyPayUI(jb51.net).rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android開(kāi)發(fā)-之環(huán)境的搭建(圖文詳解)
這篇文章主要介紹了Android開(kāi)發(fā)-之環(huán)境的搭建(圖文詳解),具有一定的參考價(jià)值,有興趣的可以了解一下。2016-11-11
Android MarkTipsView文字標(biāo)識(shí)控件使用方法
這篇文章主要為大家詳細(xì)介紹了Android MarkTipsView文字標(biāo)識(shí)控件的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
Android ViewPager自定義輪播圖并解決播放沖突
這篇文章主要為大家詳細(xì)介紹了Android ViewPager自定義輪播圖并解決播放沖突,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Android中ExpandableListView使用示例詳解
這篇文章主要為大家詳細(xì)介紹了Android中ExpandableListView使用示例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
android實(shí)現(xiàn)一個(gè)圖片驗(yàn)證碼倒計(jì)時(shí)功能
本文通過(guò)實(shí)例代碼給大家介紹了android實(shí)現(xiàn)一個(gè)圖片驗(yàn)證碼倒計(jì)時(shí)功能,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-11-11
Android RecyclerView網(wǎng)格布局(支持多種分割線(xiàn))詳解(2)
這篇文章主要為大家詳細(xì)介紹了Android RecyclerView網(wǎng)格布局,支持多種分割線(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Android實(shí)現(xiàn)可復(fù)用的篩選頁(yè)面
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)可復(fù)用的篩選頁(yè)面,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06
Afianl框架里面的FinalBitmap加載網(wǎng)絡(luò)圖片
這篇文章主要介紹了Afianl框架里面的FinalBitmap加載網(wǎng)絡(luò)圖片的相關(guān)資料,需要的朋友可以參考下2015-07-07
Android開(kāi)發(fā)實(shí)現(xiàn)的導(dǎo)出數(shù)據(jù)庫(kù)到Excel表格功能【附源碼下載】
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)的導(dǎo)出數(shù)據(jù)庫(kù)到Excel表格功能,涉及Android數(shù)據(jù)庫(kù)及Excel表格相關(guān)操作技巧,并附帶完整源碼供讀者下載參考,需要的朋友可以參考下2018-03-03
Android 實(shí)現(xiàn)關(guān)機(jī)的多種方式
有段時(shí)間做系統(tǒng)hook時(shí)需要用到系統(tǒng)重啟,找了幾種重啟的方法,還有幾種關(guān)機(jī)的方法,總結(jié)一下,有此需求的同學(xué)可以選擇適合自己的方式2021-05-05

