1. 程式人生 > >自定義密碼框 讓你實現一格一格輸密碼

自定義密碼框 讓你實現一格一格輸密碼

我自己手頭一直用的IOS系統,寫這個密碼框的時候功能方面也參考了一個下蘋果的螢幕解鎖。這個密碼框也是修修改改兩三天才算完善,效果雖然實現了,但很多細節地方還是不太明白,還希望高人指點。

1.功能介紹及效果圖

做密碼框的時候考慮了兩個方案,一個方案是用6個EditText,另一個方案則是在EditText上畫5條線。因為我基本沒接觸過draw部分的程式碼,對語法都不瞭解,所以果斷選擇了第一種。接下來考慮密碼框需要實現的功能和使用者體驗的問題。

功能1:輸入密碼刪除密碼流暢

功能2:使用者點選任意密碼框焦點在正確的位置

功能3:輸入的密碼直接顯示為圓點

2.原始碼

[java] view plain
copyprint?
  1. package com.example.passwordview;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. import android.app.Activity;  
  5. import android.content.Context;  
  6. import android.os.Bundle;  
  7. import android.os.Handler;  
  8. import android.text.Editable;  
  9. import android.text.TextUtils;  
  10. import android.text.TextWatcher;  
  11. import android.util.Log;  
  12. import android.view.KeyEvent;  
  13. import android.view.View;  
  14. import android.view.View.OnClickListener;  
  15. import android.view.View.OnKeyListener;  
  16. import android.view.inputmethod.InputMethodManager;  
  17. import android.widget.Button;  
  18. import android.widget.EditText;  
  19. import android.widget.LinearLayout;  
  20. import android.widget.Toast;  
  21. public class MainActivity extends Activity implements TextWatcher{  
  22.     private EditText et_pwd1;  
  23.     private EditText et_pwd2;  
  24.     private EditText et_pwd3;  
  25.     private EditText et_pwd4;  
  26.     private EditText et_pwd5;  
  27.     private EditText et_pwd6;  
  28.     private List<EditText> et_group;  
  29.     private OnKeyListener onKeyListener;  
  30.     public int cursorPosition=0;  
  31.     private InputMethodManager imm;  
  32.     public Context context;  
  33.     private String[] password=new String[6];  
  34.     @Override  
  35.     protected void onCreate(Bundle savedInstanceState) {  
  36.         super.onCreate(savedInstanceState);  
  37.         setContentView(R.layout.httfund_enter_password);  
  38.         intiView();  
  39.         setListener();  
  40.         testcursorPosition();  
  41.     }  
  42.     public void intiView(){  
  43.         et_pwd1=(EditText)findViewById(R.id.et_pwd1);  
  44.         et_pwd2=(EditText)findViewById(R.id.et_pwd2);  
  45.         et_pwd3=(EditText)findViewById(R.id.et_pwd3);  
  46.         et_pwd4=(EditText)findViewById(R.id.et_pwd4);  
  47.         et_pwd5=(EditText)findViewById(R.id.et_pwd5);  
  48.         et_pwd6=(EditText)findViewById(R.id.et_pwd6);  
  49.         et_group=new ArrayList<EditText>();  
  50.         et_group.add(et_pwd1);  
  51.         et_group.add(et_pwd2);  
  52.         et_group.add(et_pwd3);  
  53.         et_group.add(et_pwd4);  
  54.         et_group.add(et_pwd5);  
  55.         et_group.add(et_pwd6);  
  56.     }  
  57.     /** 
  58.      * 輸入判斷,游標永遠在第一個空白格 
  59.      */  
  60.     public void testcursorPosition(){  
  61.         cursorPosition=0;  
  62.         for(EditText editView : et_group){  
  63.             editView.setFocusableInTouchMode(true);  
  64.         }  
  65.         for(EditText et : et_group){  
  66.             if(!TextUtils.isEmpty(et.getText().toString())){  
  67.                 ++cursorPosition;  
  68.             }else{  
  69.                 break;  
  70.             }  
  71.         }  
  72.             if(cursorPosition==6){  
  73.                 cursorPosition=5;  
  74.             }  
  75.             EditText et=et_group.get(cursorPosition);  
  76.             et.requestFocus();  
  77.             et.setSelection(et.getText().toString().length());  
  78.             imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);  
  79.             if(imm.isActive()){  
  80.                 imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);  
  81.         }  
  82.         setEditViewEnable();  
  83.     }  
  84.     /** 
  85.      * 設定EditView的Enable屬性 
  86.      * 僅將包含游標的EditView設定為true 
  87.      */  
  88.     public void setEditViewEnable(){  
  89.         int i=0;  
  90.         for(EditText et : et_group){  
  91.             if(i++!=cursorPosition){  
  92.                 et.setFocusableInTouchMode(false);  
  93.             }  
  94.         }  
  95.     }  
  96.     /** 
  97.      * 事件監聽 
  98.      */  
  99.     public void setListener(){  
  100.         /** 
  101.          * EditView 監聽軟鍵盤,監聽刪除鍵 
  102.          */  
  103.         onKeyListener=new OnKeyListener() {  
  104.             @Override  
  105.             public boolean onKey(View v, int keyCode, KeyEvent event) {  
  106.                 // TODO Auto-generated method stub  
  107.                 if(keyCode==KeyEvent.KEYCODE_DEL&&event.getAction()==KeyEvent.ACTION_DOWN){  
  108.                     testcursorPosition();  
  109.                     Log.d("pwd""刪除密碼"+Integer.toString(cursorPosition));  
  110.                     if(cursorPosition!=6&&cursorPosition!=0){  
  111.                         EditText et=et_group.get(cursorPosition);  
  112.                         if(TextUtils.isEmpty(et.getText().toString())){  
  113.                             et_group.get(cursorPosition-1).setText("");  
  114.                         }  
  115.                     }  
  116.                 }  
  117.                     return false;  
  118.             }  
  119.         };  
  120.         /** 
  121.          * EditView的點選事件 
  122.          */  
  123.         OnClickListener clickListener=new OnClickListener() {  
  124.             @Override  
  125.             public void onClick(View v) {  
  126.                 // TODO Auto-generated method stub  
  127.                 testcursorPosition();  
  128.             }  
  129.         };  
  130.         for(EditText et : et_group){  
  131.             et.addTextChangedListener(this);  
  132.             et.setOnKeyListener(onKeyListener);  
  133.             et.setOnClickListener(clickListener);  
  134.         }  
  135.     }  
  136.     @Override  
  137.     public void beforeTextChanged(CharSequence s, int start, int count,  
  138.             int after) {  
  139.         // TODO Auto-generated method stub  
  140.     }  
  141.     @Override  
  142.     public void onTextChanged(CharSequence s, int start, int before, int count) {  
  143.         // TODO Auto-generated method stub  
  144.         EditText et = et_group.get(cursorPosition);  
  145.         if(s.length()>1){  
  146.             s=s.toString().subSequence(01);  
  147.             et.setText(s);  
  148.             et.setSelection(s.length());  
  149.         }  
  150.         if(!TextUtils.isEmpty(et.getText().toString())&&  
  151.                 !et.getText().toString().equals("*")){  
  152.             password[cursorPosition]=et.getText().toString();  
  153.             et.setText("*");  
  154.         }else if(!et.getText().toString().equals("*")){  
  155.             password[cursorPosition]=et.getText().toString();  
  156.         }  
  157.         testcursorPosition();  
  158.     }  
  159.     @Override  
  160.     public void afterTextChanged(Editable s) {  
  161.         // TODO Auto-generated method stub  
  162.     }  
  163. }  
package com.example.passwordview;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;

public class MainActivity extends Activity implements TextWatcher{

	private EditText et_pwd1;
	private EditText et_pwd2;
	private EditText et_pwd3;
	private EditText et_pwd4;
	private EditText et_pwd5;
	private EditText et_pwd6;
	private List<EditText> et_group;
	private OnKeyListener onKeyListener;
	public int cursorPosition=0;
	private InputMethodManager imm;
	public Context context;
	private String[] password=new String[6];
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.httfund_enter_password);
		intiView();
		setListener();
		testcursorPosition();
	}
	
	public void intiView(){
		et_pwd1=(EditText)findViewById(R.id.et_pwd1);
		et_pwd2=(EditText)findViewById(R.id.et_pwd2);
		et_pwd3=(EditText)findViewById(R.id.et_pwd3);
		et_pwd4=(EditText)findViewById(R.id.et_pwd4);
		et_pwd5=(EditText)findViewById(R.id.et_pwd5);
		et_pwd6=(EditText)findViewById(R.id.et_pwd6);
		
		et_group=new ArrayList<EditText>();
		et_group.add(et_pwd1);
		et_group.add(et_pwd2);
		et_group.add(et_pwd3);
		et_group.add(et_pwd4);
		et_group.add(et_pwd5);
		et_group.add(et_pwd6);
		
	}
	
	/**
	 * 輸入判斷,游標永遠在第一個空白格
	 */
	public void testcursorPosition(){
		cursorPosition=0;
		for(EditText editView : et_group){
			editView.setFocusableInTouchMode(true);
		}
		
		for(EditText et : et_group){
			if(!TextUtils.isEmpty(et.getText().toString())){
				++cursorPosition;
				
			}else{
				break;
			}
		}
		
			if(cursorPosition==6){
				cursorPosition=5;
			}
			EditText et=et_group.get(cursorPosition);
			et.requestFocus();
			et.setSelection(et.getText().toString().length());
			
			imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
			if(imm.isActive()){
				imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
			
			
		}
		setEditViewEnable();
	}
	/**
	 * 設定EditView的Enable屬性
	 * 僅將包含游標的EditView設定為true
	 */
	public void setEditViewEnable(){
		int i=0;
		for(EditText et : et_group){
			if(i++!=cursorPosition){
				et.setFocusableInTouchMode(false);
			}
		}
	}
	/**
	 * 事件監聽
	 */
	public void setListener(){
		/**
		 * EditView 監聽軟鍵盤,監聽刪除鍵
		 */
		onKeyListener=new OnKeyListener() {
			@Override
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				// TODO Auto-generated method stub
				if(keyCode==KeyEvent.KEYCODE_DEL&&event.getAction()==KeyEvent.ACTION_DOWN){
					testcursorPosition();
					Log.d("pwd", "刪除密碼"+Integer.toString(cursorPosition));
					if(cursorPosition!=6&&cursorPosition!=0){
						EditText et=et_group.get(cursorPosition);
						if(TextUtils.isEmpty(et.getText().toString())){
							et_group.get(cursorPosition-1).setText("");
						}
					}
				}
					return false;
				
			}
		};
		/**
		 * EditView的點選事件
		 */
		OnClickListener clickListener=new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				testcursorPosition();
			}
		};
		
		for(EditText et : et_group){
			et.addTextChangedListener(this);
			et.setOnKeyListener(onKeyListener);
			et.setOnClickListener(clickListener);
		}
	}
	
	@Override
	public void beforeTextChanged(CharSequence s, int start, int count,
			int after) {
		// TODO Auto-generated method stub
	}

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
		// TODO Auto-generated method stub
		EditText et = et_group.get(cursorPosition);
		if(s.length()>1){
			s=s.toString().subSequence(0, 1);
			et.setText(s);
			et.setSelection(s.length());
		}
		
		if(!TextUtils.isEmpty(et.getText().toString())&&
				!et.getText().toString().equals("*")){
			password[cursorPosition]=et.getText().toString();
			et.setText("*");
		}else if(!et.getText().toString().equals("*")){
			password[cursorPosition]=et.getText().toString();
		}
		
		testcursorPosition();
	}

	@Override
	public void afterTextChanged(Editable s) {
		// TODO Auto-generated method stub
	}
}


程式碼並不難,testcursorPosition用來檢測游標應該在的正確位置。InputMethodManager用於顯示軟鍵盤,設定成HIDE_IMPLICIT_ONLY唯一的一個問題就是可能彈出密碼框的時候會自動彈出軟鍵盤,這個軟鍵盤在彈出後會彈回,但是解決了在輸入密碼的時候軟鍵盤彈出彈回影響使用者體驗的問題。在onTextChanged對EditText的長度進行了限制。把數字顯示成“*”

整個邏輯跑通之後最大的問題就是輸入密碼變圓點,如果不直接設定成*號,密碼框變成圓點的過程會很長,而且時間不定,體驗非常差。

下載地址 :http://download.csdn.net/detail/u013107635/8026475