Android自定義View之六位密碼框
今天是我第一次寫技術部落格,本人也是小菜鳥一枚,工作不滿一年,部落格內容也比較簡單,對專業知識瞭解不夠深入,寫部落格的原因一來是為了分享,而來也是激勵自己,如果內容有什麼錯誤問題,請大家指教糾正。
今天要講的是六位密碼輸入框。先上程式碼。首先是layout.xml檔案
以上程式碼比較簡單,這裡六個EditText下面的TextView暫時不看。出來的效果是六個框框。<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="55dip" android:gravity="center" android:layout_gravity="center" android:orientation="horizontal"> <FrameLayout android:layout_width="wrap_content" android:layout_height="fill_parent" > <EditText android:id="@+id/e1" android:layout_width="45dip" android:layout_height="fill_parent" android:background="@drawable/topayl" android:gravity="center" android:inputType="numberPassword" android:maxLength="1" /> <TextView android:id="@+id/heng1" android:layout_width="15dip" android:layout_height="2dip" android:layout_gravity="center" android:background="@color/black" android:gravity="center" android:visibility="gone" /> </FrameLayout> <FrameLayout android:layout_width="wrap_content" android:layout_height="fill_parent" > <EditText android:id="@+id/e2" android:layout_width="45dip" android:layout_height="fill_parent" android:background="@drawable/topaym" android:gravity="center" android:inputType="numberPassword" android:maxLength="1" /> <TextView android:id="@+id/heng2" android:layout_width="15dip" android:layout_height="2dip" android:layout_gravity="center" android:background="@color/black" android:gravity="center" android:visibility="gone" /> </FrameLayout> <FrameLayout android:layout_width="wrap_content" android:layout_height="fill_parent" > <EditText android:id="@+id/e3" android:layout_width="45dip" android:layout_height="fill_parent" android:background="@drawable/topaym" android:gravity="center" android:inputType="numberPassword" android:maxLength="1" /> <TextView android:id="@+id/heng3" android:layout_width="15dip" android:layout_height="2dip" android:layout_gravity="center" android:background="@color/black" android:gravity="center" android:visibility="gone" /> </FrameLayout> <FrameLayout android:layout_width="wrap_content" android:layout_height="fill_parent" > <EditText android:id="@+id/e4" android:layout_width="45dip" android:layout_height="fill_parent" android:background="@drawable/topaym" android:gravity="center" android:inputType="numberPassword" android:maxLength="1" /> <TextView android:id="@+id/heng4" android:layout_width="15dip" android:layout_height="2dip" android:layout_gravity="center" android:background="@color/black" android:gravity="center" android:visibility="gone" /> </FrameLayout> <FrameLayout android:layout_width="wrap_content" android:layout_height="fill_parent" > <EditText android:id="@+id/e5" android:layout_width="45dip" android:layout_height="fill_parent" android:background="@drawable/topaym" android:gravity="center" android:inputType="numberPassword" android:maxLength="1" /> <TextView android:id="@+id/heng5" android:layout_width="15dip" android:layout_height="2dip" android:layout_gravity="center" android:background="@color/black" android:gravity="center" android:visibility="gone" /> </FrameLayout> <FrameLayout android:layout_width="wrap_content" android:layout_height="fill_parent" > <EditText android:id="@+id/e6" android:layout_width="45dip" android:layout_height="fill_parent" android:background="@drawable/topayr" android:gravity="center" android:inputType="numberPassword" android:maxLength="1" /> <TextView android:id="@+id/heng6" android:layout_width="15dip" android:layout_height="2dip" android:layout_gravity="center" android:background="@color/black" android:gravity="center" android:visibility="gone" /> </FrameLayout> </LinearLayout>
下面是自定義View的程式碼
/** * Created by HYQ on 2016/3/3. */ public class SixPwdView extends LinearLayout{ private Context context; private SixPwdListener listener; private EditText e1,e2,e3,e4,e5,e6; private String s_e1, s_e2, s_e3, s_e4, s_e5, s_e6; private onKeyListeners onkeylistener; public SixPwdView(Context context) { super(context); this.context = context; } public SixPwdView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; initView(); } public void clear_edit() { e1.setText(""); e2.setText(""); e3.setText(""); e4.setText(""); e5.setText(""); e6.setText(""); } /** * 取消e6的焦點 */ public void clearLastFouse(){ e6.setFocusable(false); e6.setFocusableInTouchMode(false); e6.clearFocus(); } public void getLastFouse(){ e6.setFocusable(true); e6.setFocusableInTouchMode(true); e6.requestFocus(); e6.findFocus(); } //初始化view private void initView() { View view = LayoutInflater.from(context).inflate(R.layout.six_pwd_layout,this); LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT); params.height = (int) context.getResources().getDimension(R.dimen.dp52); view.setLayoutParams(params); e1 = (EditText)view.findViewById(R.id.e1); e2 = (EditText)view.findViewById(R.id.e2); e3 = (EditText)view.findViewById(R.id.e3); e4 = (EditText)view.findViewById(R.id.e4); e5 = (EditText)view.findViewById(R.id.e5); e6 = (EditText)view.findViewById(R.id.e6); onkeylistener = new onKeyListeners(); e1.setOnKeyListener(onkeylistener); e2.setOnKeyListener(onkeylistener); e3.setOnKeyListener(onkeylistener); e4.setOnKeyListener(onkeylistener); e5.setOnKeyListener(onkeylistener); e6.setOnKeyListener(onkeylistener); e1.setCursorVisible(false); e2.setCursorVisible(false); e3.setCursorVisible(false); e4.setCursorVisible(false); e5.setCursorVisible(false); e6.setCursorVisible(false); clear_focuse(); setaddTextChangedListener(); } private void setaddTextChangedListener(){ e1.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 (e1.getText().toString().equals("")) { // heng1.setVisibility(View.VISIBLE); } else { s_e1 = e1.getText().toString(); e2_focuse(); } } }); e2.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 (e2.getText().toString().equals("")) { } else { s_e2 = e2.getText().toString(); e3_focuse(); } } }); e3.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 (e3.getText().toString().equals("")) { } else { s_e3 = e3.getText().toString(); e4_focuse(); } } }); e4.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 (e4.getText().toString().equals("")) { } else { s_e4 = e4.getText().toString(); e5_focuse(); } } }); e5.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 (e5.getText().toString().equals("")) { } else { s_e5 = e5.getText().toString(); last_focuse(); } } }); e6.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 (e6.getText().toString().equals("")) { } else { e6.setFocusable(false); s_e6 = e6.getText().toString(); isfirstallwrite(); } } }); } public void setLastFocuse(){ e6.setFocusable(true); e6.setFocusableInTouchMode(true); e6.requestFocus(); e6.findFocus(); } public void getLockTime(){ e1.setFocusable(false); e2.setFocusable(false); e3.setFocusable(false); e4.setFocusable(false); e5.setFocusable(false); e6.setFocusable(false); } String eString = ""; private void isfirstallwrite() { if (!TextUtils.isEmpty(s_e1) && !TextUtils.isEmpty(s_e2) && !TextUtils.isEmpty(s_e3) && !TextUtils.isEmpty(s_e4) && !TextUtils.isEmpty(s_e5) && !TextUtils.isEmpty(s_e6)) { //getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); eString = s_e1 + s_e2 + s_e3 + s_e4 + s_e5 + s_e6; if (listener != null) { listener.onInputComplete(eString); } } } /** * 點選刪除按鈕監聽 * * @author * */ class onKeyListeners implements android.view.View.OnKeyListener { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DEL) { if (event.getAction() != KeyEvent.ACTION_UP) { return true; } if (e6.isFocused()) { if (!TextUtils.isEmpty(e6.getText())) { e6.setText(""); } else { e6.clearFocus(); e5_focuse(); e5.setText(""); } } else if (e5.isFocused()) { if (!TextUtils.isEmpty(e5.getText())) { e5.setText(""); } else { e5.clearFocus(); e4_focuse(); e4.setText(""); } } else if (e4.isFocused()) { if (!TextUtils.isEmpty(e4.getText())) { e4.setText(""); } else { e4.clearFocus(); e3_focuse(); e3.setText(""); } } else if (e3.isFocused()) { if (!TextUtils.isEmpty(e3.getText())) { e3.setText(""); } else { e3.clearFocus(); e2_focuse(); e2.setText(""); } } else if (e2.isFocused()) { if (!TextUtils.isEmpty(e2.getText())) { e2.setText(""); } else { e2.clearFocus(); clear_focuse(); e1.setText(""); } } return true; } return false; } } private void e2_focuse() { e2.setFocusable(true); e2.setFocusableInTouchMode(true); e2.requestFocus(); e2.findFocus(); e1.setFocusable(false); e3.setFocusable(false); e4.setFocusable(false); e5.setFocusable(false); e6.setFocusable(false); } public void clear_focuse() { e1.setFocusable(true); e1.setFocusableInTouchMode(true); e1.requestFocus(); e1.findFocus(); InputMethodManager inputManager = (InputMethodManager) e1.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.showSoftInput(e1, 0); e2.setFocusable(false); e3.setFocusable(false); e4.setFocusable(false); e5.setFocusable(false); e6.setFocusable(false); } private void e3_focuse() { e3.setFocusable(true); e3.setFocusableInTouchMode(true); e3.requestFocus(); e3.findFocus(); e2.setFocusable(false); e1.setFocusable(false); e4.setFocusable(false); e5.setFocusable(false); e6.setFocusable(false); } private void e4_focuse() { e4.setFocusable(true); e4.setFocusableInTouchMode(true); e4.requestFocus(); e4.findFocus(); e2.setFocusable(false); e3.setFocusable(false); e1.setFocusable(false); e5.setFocusable(false); e6.setFocusable(false); } private void e5_focuse() { e5.setFocusable(true); e5.setFocusableInTouchMode(true); e5.requestFocus(); e5.findFocus(); e2.setFocusable(false); e3.setFocusable(false); e4.setFocusable(false); e1.setFocusable(false); e6.setFocusable(false); } public void last_focuse() { e6.setFocusable(true); e6.setFocusableInTouchMode(true); e6.requestFocus(); e6.findFocus(); e2.setFocusable(false); e3.setFocusable(false); e4.setFocusable(false); e5.setFocusable(false); e1.setFocusable(false); } public void setListener(SixPwdListener listener) { this.listener = listener; } public interface SixPwdListener{ void onInputComplete(String passWord); } }
很顯然,在這個View裡,首先setaddTextChangedListener()這個方法控制view的焦點,當e1中有資料值,立馬剝奪焦點讓給e2,當e2有資料值時,立馬剝奪焦點讓給e3,如此層層遞進,直到e6,當e6有資料時,通過isfirstallwrite()這個方法收集到6個EditText裡的值,也就是6位密碼,然後通過介面SixPwdListener傳出去,至於要對六位密碼做什麼處理,可以自行定義。這裡要注意的是,當e6獲取到值時,我這裡做的處理是直接把e6的焦點設定為false,即e6.setFocusable(false),這裡有一個問題,我這裡自定義六位密碼框,在前五個EditText時,按軟鍵盤的刪除鍵框內的資料是可以清楚的,只有當e6輸入完成時不可以清楚,應為我的需求是輸入到第六位完成後直接有跳轉處理,所以當碰到輸入完六位密碼想刪除更改時,也就是在
e6.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 (e6.getText().toString().equals("")) {
} else {
e6.setFocusable(false);
s_e6 = e6.getText().toString();
isfirstallwrite();
}
}
});
}
這裡afterTextChanged(Editable s) 裡,各位可以使得e6有焦點,改成
@Override
public void afterTextChanged(Editable s) {
if (e6.getText().toString().equals("")) {
} else {
e6.setFocusable(false);
s_e6 = e6.getText().toString();
setLastFocuse();
isfirstallwrite(); } }
其中的setLastFocuse()方法如下:
public void setLastFocuse(){
e6.setFocusable(true);
e6.setFocusableInTouchMode(true);
e6.requestFocus();
e6.findFocus();
}
其實這個自定義View總體來說比較簡單,有點基礎的一看就懂,這裡還要說的是,如果在editText輸入完資料後,不剝奪焦點的話,他會有一段過度時間才會讓數字變成圓點。剝奪的焦點的話會立馬變,所以在e6處先剝奪焦點後在設定setFocusable為true.不知道我這麼說大家聽得懂不。。。嗚嗚嗚,文筆不好咩.