Android Custom Keyboard 예제2


직전에 포스팅했던것은 Custom Keyboard에서 Cursor 처리와 백스페이스 처리가 안되었었다.

그러다가 http://www.fampennings.nl/maarten/android/09keyboard/index.htm  여기서

어느정도 Cursor 처리와 백스페이스 처리가 된 hex custom keyboard 를 발견하게 된다.

기능 또한 매우 좋고 잘 정리가 되었으나,  이것 또한 Cusor 처리가 약간 미흡한 부분이 있었다.


그래서 내가 필요한것은 number custom keyboard 이고,  Cursor 처리가 필요하지 않게 만들었다.

EditText를 선택하면 selectAll() 하여 모두선택하고,

사용자가 입력한 키보드값을 처음부터 입력하도록 하였고,

Copy & Paste 기능을 이용할 수 있도록 하였다.





1. MainActivity.java


   
public class MainActivity extends Activity {

	CustomNumKeyboard mCustomNumKeyboard;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mCustomNumKeyboard = new CustomNumKeyboard(this, R.id.keyboardview, R.xml.numkbd);
		mCustomNumKeyboard.registerEditText(R.id.edittext0);
		// mCustomNumKeyboard.registerEditText(R.id.edittext1);
		// mCustomNumKeyboard.registerEditText(R.id.edittext2);
		mCustomNumKeyboard.registerEditText(R.id.edittext3);
		mCustomNumKeyboard.registerEditText(R.id.edittext4);
	}

	@Override
	public void onBackPressed() {
		// NOTE Trap the back key: when the CustomKeyboard is still visible hide
		// it, only when it is invisible, finish activity
		if (mCustomNumKeyboard.isCustomKeyboardVisible())
			mCustomNumKeyboard.hideCustomKeyboard();
		else
			this.finish();
	}

}


2. CustomNumKeyboard.java


   
class CustomNumKeyboard {

    /** A link to the KeyboardView that is used to render this CustomKeyboard. */
    private KeyboardView mKeyboardView;
    /** A link to the activity that hosts the {@link #mKeyboardView}. */
    private Activity     mHostActivity;

    /** The key (code) handler. */
    private OnKeyboardActionListener mOnKeyboardActionListener = new OnKeyboardActionListener() {

        public final static int CodeDelete   = -5; // Keyboard.KEYCODE_DELETE
        public final static int CodeCancel   = -3; // Keyboard.KEYCODE_CANCEL
        public final static int CodePrev     = 55000;
        public final static int CodeAllLeft  = 55001;
        public final static int CodeLeft     = 55002;
        public final static int CodeRight    = 55003;
        public final static int CodeAllRight = 55004;
        public final static int CodeNext     = 55005;
        public final static int CodeClear    = 55006;
        public final static int CodeCopy		= 55007;
        public final static int CodePaste		= 55008;
        public String CopyValue = "";

        @Override public void onKey(int primaryCode, int[] keyCodes) {
            // NOTE We can say '' in the xml file; all codes come in keyCodes, the first in this list in primaryCode
            // Get the EditText and its Editable
            View focusCurrent = mHostActivity.getWindow().getCurrentFocus();
            if( focusCurrent==null || focusCurrent.getClass()!=EditText.class ) return;
            EditText edittext = (EditText) focusCurrent;
            Editable editable = edittext.getText();
            int start = edittext.getSelectionStart();
            // Apply the key to the edittext
            if( primaryCode==CodeCancel ) {
                hideCustomKeyboard();
            } else if( primaryCode==CodeDelete ) {
                if( editable!=null && start>0 ) editable.delete(start - 1, start);
                if(edittext.hasSelection() == true){	// 마스킹된 상태이면 모두 지움
                	edittext.setText(Character.toString((char) primaryCode));
                }
            } else if( primaryCode==CodeClear ) {
                if( editable!=null ) editable.clear();
            } else if( primaryCode==CodeLeft ) {
                if( start>0 ) edittext.setSelection(start - 1);
            } else if( primaryCode==CodeRight ) {
                if (start < edittext.length()) edittext.setSelection(start + 1);
            } else if( primaryCode==CodeAllLeft ) {
                edittext.setSelection(0);
            } else if( primaryCode==CodeAllRight ) {
                edittext.setSelection(edittext.length());
            } else if( primaryCode==CodePrev ) {
                View focusNew= edittext.focusSearch(View.FOCUS_BACKWARD);
                if( focusNew!=null ) focusNew.requestFocus();
            } else if( primaryCode==CodeNext ) {
                View focusNew= edittext.focusSearch(View.FOCUS_FORWARD);
                if( focusNew!=null ) focusNew.requestFocus();
            }else if(primaryCode == CodeCopy){
            	CopyValue = edittext.getText().toString();
            	if(CopyValue != null && CopyValue != ""){
            		Toast.makeText(mHostActivity, CopyValue+"을 복사하였습니다.", Toast.LENGTH_SHORT).show();
            		myKeys.get(12).label = CopyValue;
            		mKeyboardView.invalidateKey(12);
            	}

            }else if(primaryCode == CodePaste){
            	if(CopyValue != null && CopyValue != ""){
            		edittext.setText(CopyValue);
            		edittext.setSelection(edittext.length());
            	}
            } else { // insert character
            	if(edittext.hasSelection() == true){	// 마스킹된 상태이면 기존값을 지우고, 현재 입력된 키보드값만 입력함.
            		Toast.makeText(mHostActivity, "Selected", Toast.LENGTH_SHORT).show();
            		edittext.setText(Character.toString((char) primaryCode));
            		edittext.setSelection(edittext.length());		// 커서를 마지막으로 이동
            	}else{
                	editable.insert(start, Character.toString((char) primaryCode));            		
            	}

            }
        }

        @Override public void onPress(int arg0) {
        }

        @Override public void onRelease(int primaryCode) {
        }

        @Override public void onText(CharSequence text) {
        }

        @Override public void swipeDown() {
        }

        @Override public void swipeLeft() {
        }

        @Override public void swipeRight() {
        }

        @Override public void swipeUp() {
        }
    };

    /**
     * Create a custom keyboard, that uses the KeyboardView (with resource id viewid) of the host activity,
     * and load the keyboard layout from xml file layoutid (see {@link Keyboard} for description).
     * Note that the host activity must have a KeyboardView in its layout (typically aligned with the bottom of the activity).
     * Note that the keyboard layout xml file may include key codes for navigation; see the constants in this class for their values.
     * Note that to enable EditText's to use this custom keyboard, call the {@link #registerEditText(int)}.
     *
     * @param host The hosting activity.
     * @param viewid The id of the KeyboardView.
     * @param layoutid The id of the xml file containing the keyboard layout.
     */
    public ListmyKeys = null;
    public CustomNumKeyboard(Activity host, int viewid, int layoutid) {
        mHostActivity= host;
        mKeyboardView= (KeyboardView)mHostActivity.findViewById(viewid);
        mKeyboardView.setKeyboard(new Keyboard(mHostActivity, layoutid));
        mKeyboardView.setPreviewEnabled(false); // NOTE Do not show the preview balloons
        mKeyboardView.setOnKeyboardActionListener(mOnKeyboardActionListener);
        // Hide the standard keyboard initially
        mHostActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        
        myKeys = mKeyboardView.getKeyboard().getKeys();
    }

    /** Returns whether the CustomKeyboard is visible. */
    public boolean isCustomKeyboardVisible() {
        return mKeyboardView.getVisibility() == View.VISIBLE;
    }

    /** Make the CustomKeyboard visible, and hide the system keyboard for view v. */
    public void showCustomKeyboard( View v ) {
        mKeyboardView.setVisibility(View.VISIBLE);
        mKeyboardView.setEnabled(true);
        if( v!=null ) ((InputMethodManager)mHostActivity.getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
    }

    /** Make the CustomKeyboard invisible. */
    public void hideCustomKeyboard() {
        mKeyboardView.setVisibility(View.GONE);
        mKeyboardView.setEnabled(false);
    }

    /**
     * Register EditText with resource id resid (on the hosting activity) for using this custom keyboard.
     *
     * @param resid The resource id of the EditText that registers to the custom keyboard.
     */
    public void registerEditText(int resid) {
        // Find the EditText 'resid'
        EditText edittext= (EditText)mHostActivity.findViewById(resid);
        // Make the custom keyboard appear
        edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
            // NOTE By setting the on focus listener, we can show the custom keyboard when the edit box gets focus, but also hide it when the edit box loses focus
            @Override public void onFocusChange(View v, boolean hasFocus) {
                if( hasFocus ){
                	showCustomKeyboard(v); 
                }else{
                	hideCustomKeyboard();
                }
            }
        });
        edittext.setOnClickListener(new OnClickListener() {
            // NOTE By setting the on click listener, we can show the custom keyboard again, by tapping on an edit box that already had focus (but that had the keyboard hidden).
            @Override public void onClick(View v) {
                showCustomKeyboard(v);
            }
        });
        // Disable standard keyboard hard way
        // NOTE There is also an easy way: 'edittext.setInputType(InputType.TYPE_NULL)' (but you will not have a cursor, and no 'edittext.setCursorVisible(true)' doesn't work )
        edittext.setOnTouchListener(new OnTouchListener() {
            @Override public boolean onTouch(View v, MotionEvent event) {
                EditText edittext = (EditText) v;
                int inType = edittext.getInputType();       // Backup the input type
                edittext.setInputType(InputType.TYPE_NULL); // Disable standard keyboard
                edittext.onTouchEvent(event);               // Call native handler
                edittext.setInputType(inType);              // Restore input type
//                edittext.setSelection(edittext.length());		// 커서를 맨 마지막으로 이동
                edittext.selectAll();								// 모든 텍스트를 마스킹
                
                return true; // Consume touch event
            }
        });
        // Disable spell check (hex strings look like words to Android)
        edittext.setInputType(edittext.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    }

}

3. numkbd.xml


<?xml version="1.0" encoding="utf-8"?>

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"

    android:keyWidth="12.50%p"

    android:keyHeight="10%p">

<!--

    android:horizontalGap="0.50%p"

    android:verticalGap="0.50%p"

    NOTE When we add a horizontalGap in pixels, this interferes with keyWidth in percentages adding up to 100%

    NOTE When we have a horizontalGap (on Keyboard level) of 0, this make the horizontalGap (on Key level) to move from after the key to before the key... (I consider this a bug) 

 -->

    

    <Row>

        <Key

            android:codes="49"

            android:keyEdgeFlags="left"

            android:keyLabel="1" />

        <Key

            android:codes="50"

            android:keyLabel="2" />

        <Key

            android:codes="51"

            android:keyLabel="3" />

        <Key

            android:codes="52"

            android:keyLabel="4" />

        <Key

            android:codes="53"

            android:keyLabel="5" />

        <Key

            android:codes="54"

            android:keyLabel="6" />

        <Key

            android:codes="55"

            android:keyLabel="7" />

        <Key

            android:codes="56"

            android:keyLabel="8" />

        <Key

            android:codes="57"

            android:keyLabel="9" />

        <Key

            android:codes="48"

            android:keyLabel="0" />

        <Key

            android:codes="-5"

android:keyIcon="@drawable/sym_keyboard_delete" android:isRepeatable="true"

android:horizontalGap="3.25%p"             

            />

        <Key android:codes="55007" android:keyLabel="COPY" />

        <Key android:codes="55008" android:keyLabel="PASTE" android:keyEdgeFlags="right" />

        

    </Row>



</Keyboard>












09Keyboard.zip




+ Recent posts