1. 程式人生 > >Android 自定義數字鍵盤(三)自定義輸入框

Android 自定義數字鍵盤(三)自定義輸入框

Android 自定義數字鍵盤(一)
Android 自定義數字鍵盤(二)隨機數字

Demo地址:https://github.com/danfengfirst/KeyDemo
這篇部落格是在上面兩篇部落格的基礎上修改的一個相對比較完整的demo,寫完前面兩篇我嘗試使用過用pop彈出介面,但是焦點方面總是有問題,就參考了樑肖的思路,改用了Activity,為了思路清晰,沒有給輸入框自定義屬性,效果演示如下(錄的好像有點卡,動畫效果跟點選的時候卡了,錄製原因,正常執行不卡哈):
這裡寫圖片描述

思路:

主要是三個方面:
1、自定義EidtText輸入框,重寫onTextChanged()方法來監聽文字並進行重新整理+圓點繪製
2、注意自定義的EditTextView獲取焦點時隱藏鍵盤,顯示自己定義的鍵盤,還有Editable的使用
3、對自定義鍵盤的點選事件監聽回撥,回撥中分了兩個方法一個插入資料,一個刪除資料,通過方法名字應該看得出來。

  //對按鍵的輸入與刪除事件進行監聽
        mKeyView.setOnKeyPressListener(new NumKeyView.OnKeyPressListener() {
            @Override
            public void onInertKey(String text) {
                //這裡不可以直接使用mEditText來進行append,否則會顯示數字
                if (editable.length() < 6) {
                    mPasswordStr.append(text);
                    editable.append(text);
                }
            }
            @Override
public void onDeleteKey() { if (editable.length() > 0) { int length = editable.length(); editable.delete(length - 1, length); mPasswordStr.delete(length - 1, length); } } });

程式碼

自定義輸入框

程式碼很少也很容易理解

public class PassWordEdit extends EditText {
    //控制元件寬度與高度
    private int mWidth;
    private int mHeight;
    private Paint mPaint;
    //輸入密碼長度
    private int mPassWordLength;

    public PassWordEdit(Context context) {
        this(context, null);
    }

    public PassWordEdit(Context context, AttributeSet attrs) {
        super(context, attrs);
        //初始化
        mPaint=new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(getResources().getColor(R.color.deepgray));
        mPaint.setStrokeWidth(2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //為了繪製矩形邊框設定畫筆為空心的
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(new RectF(0+mPaint.getStrokeWidth(),0,mWidth-mPaint.getStrokeWidth(),mHeight),mPaint);
        mPaint.setStyle(Paint.Style.FILL);
        int width=(int)(mWidth/6.0);
        //繪製中間豎線
        for (int i=1;i<=5;i++){
            canvas.drawLine(width*i,0,width*i,mHeight,mPaint);
        }
        //繪製中間圓點
        for (int j=0;j<mPassWordLength;j++){
            canvas.drawCircle(width/2+width*j,mHeight/2,5.0f,mPaint);
        }
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        //進行監聽,文字改變的時候重新整理介面
        if (text.length()!=mPassWordLength){
            mPassWordLength=text.length();
        }
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(mWidth, mHeight);
    }
}

Activity呼叫

注意上面思路中提到的三點就可以

public class KeyDemo extends AppCompatActivity implements View.OnClickListener, View.OnFocusChangeListener {
    private PassWordEdit mEditText;
    private NumKeyView mKeyView;
    private Button mButtonEnsure;
    private ImageView mImageViewCancle;
    private StringBuffer mPasswordStr;

    private ToastUtil mToast;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.keyboard_pop);
        init();
    }

    private void init() {
        mEditText = (PassWordEdit) findViewById(R.id.passWordEdit);//自定義密碼輸入框
        mKeyView = (NumKeyView) findViewById(R.id.keyboardview);//自定義鍵盤
        mButtonEnsure = (Button) findViewById(R.id.bt_ensure);//確定按鈕
        mImageViewCancle = (ImageView) findViewById(R.id.im_cancle);//取消按鈕
        mEditText.setInputType(InputType.TYPE_NULL);//隱藏鍵盤
        mKeyView.setRandomKeyBoard(true);//設定隨機數字鍵盤
        mToast = new ToastUtil(getApplicationContext());
        addListener();
        mEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());//隱藏文字,不加這行程式碼會顯示輸入文字


    }

    private void addListener() {
        mEditText.setOnFocusChangeListener(this);
        mButtonEnsure.setOnClickListener(this);
        mImageViewCancle.setOnClickListener(this);
        mEditText.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                showKeyBoard();
                return false;
            }
        });
        final Editable editable = mEditText.getText();
        //對按鍵的輸入與刪除事件進行監聽
        mKeyView.setOnKeyPressListener(new NumKeyView.OnKeyPressListener() {
            @Override
            public void onInertKey(String text) {
                //這裡不可以直接使用mEditText來進行append,否則會顯示數字
                if (editable.length() < 6) {
                    mPasswordStr.append(text);
                    editable.append(text);
                }
            }
            @Override
            public void onDeleteKey() {
                if (editable.length() > 0) {
                    int length = editable.length();
                    editable.delete(length - 1, length);
                    mPasswordStr.delete(length - 1, length);
                }
            }
        });
    }



    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.bt_ensure:
                if (mPasswordStr.length() <= 0) {
                    mToast.showToastCenter("請輸入有效密碼");
                }
                if (mPasswordStr.length() == 6) {
                    Intent intent = new Intent();
                    intent.putExtra("data", mPasswordStr.toString());
                    setResult(RESULT_OK, intent);
                    finish();
                }
                break;
            case R.id.im_cancle:
                finish();
                break;
            default:
                break;
        }
    }

    @Override
    public void onFocusChange(View view, boolean hasfocus) {
        mPasswordStr = new StringBuffer();
        if (hasfocus) {
            hideSoftKeyBoard();
            showKeyBoard();
        } else {
            hideKeyBoard();
        }
    }
    public void hideSoftKeyBoard() {
        InputMethodManager im = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
        im.hideSoftInputFromInputMethod(getCurrentFocus().getWindowToken(), InputMethodManager.RESULT_HIDDEN);
    }

    public void showKeyBoard() {
        if (mKeyView != null && (mKeyView.getVisibility() == View.INVISIBLE || mKeyView.getVisibility() == View.GONE)) {
            mKeyView.setVisibility(View.VISIBLE);
        }
    }

    public void hideKeyBoard() {
        if (mKeyView != null && (mKeyView.getVisibility() == View.VISIBLE)) {
            mKeyView.setVisibility(View.GONE);
        }
    }

}

佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/transparent_half_half_half"
    android:gravity="bottom"
    android:orientation="vertical">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:padding="10dp">

        <ImageView
            android:id="@+id/im_cancle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:src="@drawable/guanbixiao" />

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"
            android:text="請輸入支付密碼"
            android:textSize="24sp" />

        <TextView
            android:id="@+id/tv_tip"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_title"
            android:gravity="center_horizontal"
            android:text="您的手機不在常用地區登入,為保障您的資金安全,請輸入支付密碼"
            android:textColor="@color/colorAccent"
            android:textSize="22sp" />
        <包名+PassWordEdit
            android:id="@+id/passWordEdit"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginTop="5dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_below="@+id/tv_tip"
            android:layout_weight="1"
            android:background="#ffffff"
            android:maxLength="6"
            android:textColor="@color/colorAccent" />
        <Button
            android:id="@+id/bt_ensure"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/passWordEdit"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="20dp"
            android:background="@drawable/btbg"
            android:text="確定" />

    </RelativeLayout>

    <包名+NumKeyView
        android:id="@+id/keyboardview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:keyBackground="@color/colorAccent"
        app:deleteDrawable="@drawable/keyboard_backspace"
        app:gbColor="#eeeeee" />
</LinearLayout>

其他部分

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void popkeyboard(View view){
        Intent intent=new Intent(MainActivity.this,KeyDemo.class);
        startActivityForResult(intent,0x11);
        overridePendingTransition(R.anim.showanim,R.anim.dismissanim);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode==RESULT_OK){
            String text=data.getExtras().getString("data");
            ToastUtil toastUtil=new ToastUtil(getApplicationContext());
            toastUtil.showToastCenter(text);

        }
    }
}

動畫(用的之前的)
show

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0"
        android:fromYDelta="100%"
        android:toXDelta="0"
        android:toYDelta="0"
        android:duration="1000"
        ></translate>

</set>

dismiss

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
    android:toXDelta="0"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toYDelta="100%"
    android:duration="1000"
    ></translate>
</set>