Android 自定义键盘 随机键盘(完全定制,向上顶布局,点击按钮进行隐藏)

     之前上传的另外一个自定义键盘,并没有实现键盘弹出的时候,布局向上自动调整。(网络上所有的自定义键盘都没有添加自适应的功能,而且布局没这么好看,上一个例子资源链接为:http://download.csdn.net/detail/omayyouhappy/9111809,这个资源绝对值10分,真的全网络唯一完美的自定义定制键盘,新的资源在这里:全网唯一定制键盘(向上改变布局)   ,接下来就仔细的讲讲我是如何完成自定义键盘的,我得吐槽一下,一开始为了做自定义键盘,网上的例子确实很有用,避免了重复造轮子,给了我很大的启示,也快速的知道如何使用google提供的自定义键盘类使用方法,介绍基本的键盘的情况,你可以到这篇博文来了解: 整个网络可能最完善的 Android 自定义键盘 问题汇总以及解决方案,只需要花几分钟时间,就可以制作一个基本的键盘,但这个键盘有很多缺点,是通过按钮隐藏布局的形式来隐藏键盘、有可能会出现遮挡住你所要输入的edittext情况,无法适应整个屏幕布局,这篇博文就是讲解如何解决这些问题的,那么开始吧:

   

                                                                                                          自定义键盘整个过程如下:

    1.第一步,根据你的需求,需要定制怎样的键盘,需要几行几列,准备好键盘按键的背景图片,键盘的尺寸,在res文件下,新建一个xml文件,下面放字母、数字、标点符号键盘的布局文件,我的需求是这样的:

      

     可以看到上述的键盘需要美工做的图片有几张:字母和数字的按键的基本背景(需要圆角)、删除按键、切换大小写的图标、点击隐藏键盘的下拉按键,设置键盘的布局为白色就可以大致实现上述的效果。这里我在写键盘文件的时候遇到几个难点,分享如下:

       A.按键之间的空隙和键盘整体高度,需要不断的调整,不可能一下子就可以布置好的,特别字母键盘里的删除键,高度是两个按键,所以需要反复调试。

      B.为了解决点击下拉按钮隐藏键盘的功能:放弃原先点击下拉按钮,隐藏整个键盘的布局的方案,而改用在键盘文件中再加一整行,只有一个按键,就是done,完成按钮,这是系统定义好的完成功能,code值为:  -3。(所以我们发现很多系统自动的比如切换大小写、删除功能、空格功能,都是已经定义好了code值,只需要找到对应的含义,直接定义使用就可以了。)

        字母布局文件如下(主要部分,代码可以到资源里下载):res\xml\qwerty.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="1px"
    android:keyWidth="9.7%p"
    android:verticalGap="3px" >

    <Row android:verticalGap="18px" >
        <Key
            android:codes="-3"
            android:keyIcon="@drawable/ret"
            android:keyWidth="100%p" />
    </Row>
    。。。。。。。。。。。。。。。
。。。。。。。。。。。。
    <Row android:keyHeight="40dp" >
        <Key
            android:codes="-1"
            android:keyEdgeFlags="left"
            android:keyIcon="@drawable/updata"
            android:keyWidth="9.55%p" />
        <Key
            android:codes="-4"
            android:keyLabel=".?&" />
        <Key
            android:codes="122"
            android:keyLabel="z" />
        <Key
            android:codes="120"
            android:keyLabel="x" />
        <Key
            android:codes="99"
            android:keyLabel="c" />
        <Key
            android:codes="118"
            android:keyLabel="v" />
        <Key
            android:codes="98"
            android:keyLabel="b" />
        <Key
            android:codes="110"
            android:keyLabel="n" />
        <Key
            android:codes="109"
            android:keyLabel="m" />
    </Row>

</Keyboard>


         标点符号键盘布局文件如下:res\xml\qwerty2.xml

 

 

<?xml version="1.0" encoding="UTF-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="1px"
    android:keyWidth="9.7%p"
    android:verticalGap="3px" >

    <Row android:verticalGap="18px">
        <Key
            android:codes="-3"
            android:keyIcon="@drawable/ret"
            android:keyWidth="100%p"
            android:verticalGap="3px"  />
    </Row>
。。。。。。。。。。。。。。。。。。。。。。<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">。。。。。。。。。。。。。。。。。。。</span>
     <Row android:keyHeight="40dp" >
        <Key
            android:codes="-1"
            android:isSticky="true"
            android:keyIcon="@drawable/updata" />
        <Key
            android:codes="-4"
            android:keyLabel="abc" />
        <Key
            android:codes="96"
            android:keyLabel="`" />
        <Key
            android:codes="32"
            android:isRepeatable="true"
            android:keyLabel="space"
            android:keyWidth="39%p" />
        <Key
            android:codes="46"
            android:keyLabel="." />
        <Key
            android:codes="44"
            android:keyLabel="," />
    </Row>

</Keyboard>


       数字键盘布局如下:(其中一些按键是自定义的,比如10,000,000,这是为了用户输入方便):res\xml\amountinputkeyboard.xml

 

 

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="3px"

    android:keyWidth="24.2%p"
    android:verticalGap="3px" >

    <Row android:verticalGap="18px" >
        <Key
            android:codes="-3"
            android:keyIcon="@drawable/ret"
            android:keyWidth="100%p"
            android:verticalGap="3px" />
    </Row>
 
 。。。。。。。。。。。。。
。。。。。。。。。。。。。
    <Row android:keyHeight="50dp" >
        <Key
            android:codes="46"
            android:keyLabel="." />
        <Key
            android:codes="48"
            android:keyLabel="0" />
        <Key
            android:codes="-110"
            android:keyLabel="00" />
        <Key
            android:codes="-5"
            android:isRepeatable="true"
            android:keyEdgeFlags="right"
            android:keyIcon="@drawable/deletepng" />
    </Row>

</Keyboard>


        上面的节点具体解释可以参照上篇博文,我分享一下我与网络最热那篇自定义键盘的区别:为了加一整行的点击隐藏按键,需要单独设置高度和间距,所以我们不在xml开头设置整体的键盘高度,而改在Row节点上进行单独的高度设置,这一点非常重要,如果设置整体的高度,就会出现最上面一行有多余的白色部分,影响美观:也就是下面这个:

 

 

<Row <span style="color:#ff0000;"><strong>android:verticalGap="18px"</strong></span> >
        <Key
            android:codes="-3"
            android:keyIcon="@drawable/ret"
            android:keyWidth="100%p"
            android:verticalGap="3px" />
    </Row>

 

 

 

        对于键盘之间的垂直和水平方向的间距多少合适,以及每个按键占据的百分比多少合适,都要根据你所使用的手机、按键背景图片大小、有几行按键来细心调整,在这段代码进行调整:

 

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

    android:keyWidth="24.2%p"
    android:verticalGap="3px" </strong>

 

 

 

      2.定义好了你所需要的键盘布局,已经完成了关键性的一步,下面就是如何在点击edit之后,隐藏系统键盘,弹出自定义键盘,点击按钮隐藏键盘等功能。

第二步,建立你所需要放置自定义键盘的主布局文件,如下:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mykeyboard="http://schemas.android.com/apk/res/com.example.testkeyboard"
    android:id="@+id/fulllayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

   <com.example.testkeyboard.MyKeyboard// 自定义<span style="font-family: Arial, Helvetica, sans-serif;">EditText,继承于EditText,实现键盘implements OnKeyboardActionListener接口
        android:id="@+id/et"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_marginTop="10dp"
 android:background="@drawable/gray_shape" //设置圆角效果
        android:gravity="center"
        android:hint="身份证号"
        android:singleLine="true"
        android:textColor="@color/black"
        android:textColorHint="#BABABA"
        mykeyboard:xml="@xml/amountinputkeyboard" />  //

    <com.example.testkeyboard.MyKeyboard
        android:id="@+id/etChar"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/gray_shape"
        android:gravity="center"
        android:hint="字母和标点符号键盘"
        android:singleLine="true"
        android:textColor="@color/black"
        android:textColorHint="#BABABA"
        mykeyboard:xml="@xml/qwerty" />

</LinearLayout>

        键盘单独布局文件: res\layout\mykeyboardview.xml

 

 

<?xml version="1.0" encoding="utf-8"?>
android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android"//系统自带的键盘布局文件
    android:id="@+id/keyboard_view"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
   <span style="color:#ff0000;"> android:background="@color/white"  //设置键盘的整个背景为白色</span>
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:keyBackground="@drawable/d"
    android:keyTextColor="#A8AAAB"
    android:keyTextSize="20sp"
    android:labelTextSize="15sp"
    android:padding="2.5dp" />

<!-- android:keyBackground="@drawable/data" -->

      该类主要是让主控制类加载。
 

 

 第三步:编写主控制类:主要显示键盘和控制键盘动画隐藏弹出效果,主控制类:src\com\example\testkeyboard\MyKeyboard.java,主要代码注释如下:

 

package com.example.testkeyboard;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.Keyboard.Key;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.os.Build;
import android.os.SystemClock;
import android.text.Editable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.ActionMode;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;

/**
 * 
 * 自定义键盘,有按下效果
 *
 */
public class MyKeyboard extends EditText implements OnKeyboardActionListener {

	private Keyboard k1;// 字母键盘
	private Keyboard k2;// 标点符号键盘
	public boolean isnun = false;// 是否标点符号键盘
	public boolean isupper = false;// 是否大写

	private KeyboardView mKeyboardView;
	private Keyboard mKeyboard;

	private Window mWindow;
	private View mDecorView;
	private View mContentView;

	private PopupWindow mKeyboardWindow;

	private boolean needcustomkeyboard = true; // 是否启用自定义键盘
	private boolean randomkeys = false; // 数字按键是否随机

	private int scrolldis = 50; // 输入框在键盘被弹出时,要被推上去的距离

	public static int screenw = -1;// 未知宽高
	public static int screenh = -1;
	public static int screenh_nonavbar = -1; // 不包含导航栏的高度
	public static int real_scontenth = -1; // 实际内容高度, 计算公式:屏幕高度-导航栏高度-电量栏高度

	public static float density = 1.0f;
	public static int densityDpi = 160;

	/**
	 * @param context
	 * @param attrs
	 */
	public MyKeyboard(Context context, AttributeSet attrs) {
		super(context, attrs);
		initAttributes(context);
		initKeyboard(context, attrs);

		// TODO Auto-generated constructor stub
	}

	/**
	 * @param context
	 * @param attrs
	 * @param defStyle
	 */
	public MyKeyboard(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initAttributes(context);
		initKeyboard(context, attrs);
		// TODO Auto-generated constructor stub
	}
        //键盘初始化
	private void initKeyboard(Context context, AttributeSet attrs) {

		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.keyboard);

		if (a.hasValue(R.styleable.keyboard_xml)) {
			needcustomkeyboard = true;

			int xmlid = a.getResourceId(R.styleable.keyboard_xml, 0);

			mKeyboard = new Keyboard(context, xmlid);

			<span style="color:#ff0000;"><strong>mKeyboardView = (KeyboardView) LayoutInflater.from(context)
					.inflate(R.layout.mykeyboardview, null);  //加载键盘布局</strong></span>
			if (a.hasValue(R.styleable.keyboard_randomkeys)) {
				boolean random = a.getBoolean(R.styleable.keyboard_randomkeys,
						false);
				randomkeys = random;

				if (random) {
					randomdigkey(mKeyboard);
				}
			}
                        <span style="color:#ff0000;"><strong>//使用popupwindow在下方弹出键盘,设置弹出和隐藏的动画效果</strong></span>
			mKeyboardView.setKeyboard(mKeyboard);
			mKeyboardView.setEnabled(true);
			mKeyboardView.setPreviewEnabled(false);
			mKeyboardView.setOnKeyboardActionListener(this);

			mKeyboardWindow = new PopupWindow(mKeyboardView,
					ViewGroup.LayoutParams.MATCH_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
			<strong><span style="color:#ff0000;">mKeyboardWindow.setAnimationStyle(R.style.AnimationFade);//设置动画效果,文件在资源里面,这里就不贴出来。</span></strong>
			// mKeyboardWindow.setBackgroundDrawable(new BitmapDrawable());
			// mKeyboardWindow.setOutsideTouchable(true);
			mKeyboardWindow.setOnDismissListener(new OnDismissListener() {

				@Override
				public void onDismiss() {
					// TODO Auto-generated method stub
					if (scrolldis > 0) {
						int temp = scrolldis;
						scrolldis = 0;
						if (null != mContentView) {
							<span style="font-size:24px;color:#ff0000;"><strong>mContentView.scrollBy(0, -temp);//使布局整体向上顶的关键代码,使用布局的scrollBy重新滚动位置。</strong></span>
						}
					}
				}
			});
		} else {
			needcustomkeyboard = false;
		}

		a.recycle();

	}
        //显示键盘,
	private void showKeyboard() {
		if (null != mKeyboardWindow) {
			if (!mKeyboardWindow.isShowing()) {
				if (randomkeys) {
					randomdigkey(mKeyboard);
				}

				mKeyboardView.setKeyboard(mKeyboard);

				mKeyboardWindow.showAtLocation(this.mDecorView, Gravity.BOTTOM,
						0, 0);
				mKeyboardWindow.update();

				if (null != mDecorView && null != mContentView) {
					int[] pos = new int[2];
					// 计算弹出的键盘的尺寸
					getLocationOnScreen(pos);
					float height = dpToPx(getContext(), 240);

					// int []hsmlpos=new int[2];
					// mDecorView.getLocationOnScreen(hsmlpos);

					Rect outRect = new Rect();
					// 然后该View有个getWindowVisibleDisplayFrame()方法可以获取到程序显示的区域,
					// * 包括标题栏,但不包括状态栏。
					mDecorView.getWindowVisibleDisplayFrame(outRect);// 获得view空间,也就是除掉标题栏
					// outRect.top表示状态栏(通知栏)
					int screen = real_scontenth;
					scrolldis = (int) ((pos[1] + getMeasuredHeight() - outRect.top) - (screen - height));

					if (scrolldis > 0) {
						mContentView.scrollBy(0, scrolldis);
					}
				}

			}
		}
	}
        //隐藏键盘
	private void hideKeyboard() {
		if (null != mKeyboardWindow) {
			if (mKeyboardWindow.isShowing()) {
				mKeyboardWindow.dismiss();
			}
		}
	}
        //隐藏系统的软键盘
	private void hideSysInput() {
		if (this.getWindowToken() != null) {
			InputMethodManager imm = (InputMethodManager) getContext()
					.getSystemService(Context.INPUT_METHOD_SERVICE);
			imm.hideSoftInputFromWindow(this.getWindowToken(),
					InputMethodManager.HIDE_NOT_ALWAYS);
		}
	}
       //edittext点击的监听事件,当点击了edittext则弹出键盘
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);
		requestFocus();
		requestFocusFromTouch();

		if (needcustomkeyboard) {
			hideSysInput();
			showKeyboard();
		}

		return true;
	}

       //当点击手机的返回键,则隐藏键盘
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (null != mKeyboardWindow) {
				if (mKeyboardWindow.isShowing()) {
					mKeyboardWindow.dismiss();
					return true;
				}
			}
		}

		return super.onKeyDown(keyCode, event);

	}

	@Override
	public void onAttachedToWindow() {
		super.onAttachedToWindow();

		this.mWindow = ((Activity) getContext()).getWindow();
		this.mDecorView = this.mWindow.getDecorView();
		this.mContentView = this.mWindow
				.findViewById(Window.ID_ANDROID_CONTENT);

		hideSysInput();
	}

	@Override
	public void onDetachedFromWindow() {
		super.onDetachedFromWindow();

		hideKeyboard();

		mKeyboardWindow = null;
		mKeyboardView = null;
		mKeyboard = null;

		mDecorView = null;
		mContentView = null;
		mWindow = null;
	}

	@Override
	public void onPress(int primaryCode) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onRelease(int primaryCode) {
		// TODO Auto-generated method stub

	}
        <span style="font-size:18px;color:#ff0000;"><strong>//自定义键盘每个按键的监听方法,必须实现,实现大小写切换、字母键盘和标点符号键盘之间的切换功能
	@Override
	public void onKey(int primaryCode, int[] keyCodes) {
		// TODO Auto-generated method stub
		Editable editable = this.getText();
		int start = this.getSelectionStart();
		if (primaryCode == Keyboard.KEYCODE_CANCEL) {// 隐藏键盘
			hideKeyboard();
		} else if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退
			if (editable != null && editable.length() > 0) {
				if (start > 0) {
					editable.delete(start - 1, start);
				}
			}
		} else if (primaryCode == Keyboard.KEYCODE_SHIFT) {// 大小写切换
			changeKey();
			mKeyboardView.setKeyboard(k1);

		}

		else if (primaryCode == Keyboard.KEYCODE_DONE) {// 标点符号键盘切换
			if (isnun) {
				isnun = false;
				mKeyboardView.setKeyboard(k1);
			} else {
				isnun = true;
				mKeyboardView.setKeyboard(k2);
			}
		}

		else if (primaryCode == -110) {
			editable.insert(start, "00");
		} else if (primaryCode == -20000) {
			editable.insert(start, "200,000");
		} else if (primaryCode == -50000) {
			editable.insert(start, "5,000,000");
		} else if (primaryCode == -10000) {
			editable.insert(start, "10,000,000");
		} else if (0x0 <= primaryCode && primaryCode <= 0x7f) {
			// 可以直接输入的字符(如0-9,.),他们在键盘映射xml中的keycode值必须配置为该字符的ASCII码
			editable.insert(start, Character.toString((char) primaryCode));
		} else if (primaryCode > 0x7f) {
			Key mkey = getKeyByKeyCode(primaryCode);
			// 可以直接输入的字符(如0-9,.),他们在键盘映射xml中的keycode值必须配置为该字符的ASCII码
			editable.insert(start, mkey.label);

		} else {
			// 其他一些暂未开放的键指令,如next到下一个输入框等指令
		}
	}
</strong></span>
	/**
	 * 键盘大小写切换
	 */
	private void changeKey() {
		List<Key> keylist = k1.getKeys();
		if (isupper) {// 大写切换小写
			isupper = false;
			for (Key key : keylist) {
				if (key.label != null && isword(key.label.toString())) {
					key.label = key.label.toString().toLowerCase();
					key.codes[0] = key.codes[0] + 32;
				}
			}
		} else {// 小写切换大写
			isupper = true;
			for (Key key : keylist) {
				if (key.label != null && isword(key.label.toString())) {
					key.label = key.label.toString().toUpperCase();
					key.codes[0] = key.codes[0] - 32;
				}
			}
		}
	}
        //判断是否为字母
	private boolean isword(String str) {
		String wordstr = "abcdefghijklmnopqrstuvwxyz";
		if (wordstr.indexOf(str.toLowerCase()) > -1) {
			return true;
		}
		return false;
	}

	private Key getKeyByKeyCode(int keyCode) {
		if (null != mKeyboard) {
			List<Key> mKeys = mKeyboard.getKeys();
			for (int i = 0, size = mKeys.size(); i < size; i++) {
				Key mKey = mKeys.get(i);

				int codes[] = mKey.codes;

				if (codes[0] == keyCode) {
					return mKey;
				}
			}
		}

		return null;
	}

	private void initAttributes(Context context) {

		k1 = new Keyboard(context, R.xml.qwerty);
		k2 = new Keyboard(context, R.xml.qwerty2);

		initScreenParams(context);
		this.setLongClickable(false);
		this.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
		removeCopyAbility();

		if (this.getText() != null) {
			this.setSelection(this.getText().length());
		}

		this.setOnFocusChangeListener(new OnFocusChangeListener() {

			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				// TODO Auto-generated method stub
				if (!hasFocus) {
					hideKeyboard();
				}
			}
		});

	}

	@TargetApi(11)
	private void removeCopyAbility() {
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			this.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

				@Override
				public boolean onCreateActionMode(ActionMode mode, Menu menu) {
					return false;
				}

				@Override
				public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
					return false;
				}

				@Override
				public void onDestroyActionMode(ActionMode mode) {

				}

				@Override
				public boolean onActionItemClicked(ActionMode mode,
						MenuItem item) {
					return false;
				}
			});
		}
	}

	private boolean isNumber(String str) {
		String wordstr = "0123456789";
		if (wordstr.indexOf(str) > -1) {
			return true;
		}
		return false;
	}
        // 暂时未使用到,为了实现随机键盘布局
	private void randomdigkey(Keyboard mKeyboard) {
		if (mKeyboard == null) {
			return;
		}

		List<Key> keyList = mKeyboard.getKeys();

		// 查找出0-9的数字键
		List<Key> newkeyList = new ArrayList<Key>();
		for (int i = 0, size = keyList.size(); i < size; i++) {
			Key key = keyList.get(i);
			CharSequence label = key.label;
			if (label != null && isNumber(label.toString())) {
				newkeyList.add(key);
			}
		}

		int count = newkeyList.size();

		List<KeyModel> resultList = new ArrayList<KeyModel>();

		LinkedList<KeyModel> temp = new LinkedList<KeyModel>();

		for (int i = 0; i < count; i++) {
			temp.add(new KeyModel(48 + i, i + ""));
		}

		Random rand = new SecureRandom();
		rand.setSeed(SystemClock.currentThreadTimeMillis());

		for (int i = 0; i < count; i++) {
			int num = rand.nextInt(count - i);
			KeyModel model = temp.get(num);
			resultList.add(new KeyModel(model.getCode(), model.getLable()));
			temp.remove(num);
		}

		for (int i = 0, size = newkeyList.size(); i < size; i++) {
			Key newKey = newkeyList.get(i);
			KeyModel resultmodle = resultList.get(i);
			newKey.label = resultmodle.getLable();
			newKey.codes[0] = resultmodle.getCode();
		}

	}

	class KeyModel {

		private Integer code;
		private String label;

		public KeyModel(Integer code, String lable) {
			this.code = code;
			this.label = lable;
		}

		public Integer getCode() {
			return code;
		}

		public void setCode(Integer code) {
			this.code = code;
		}

		public String getLable() {
			return label;
		}

		public void setLabel(String lable) {
			this.label = lable;
		}

	}

	/**
	 * 密度转换为像素值
	 * 
	 * @param dp
	 * @return
	 */
	public static int dpToPx(Context context, float dp) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dp * scale + 0.5f);
	}

	private void initScreenParams(Context context) {
		DisplayMetrics dMetrics = new DisplayMetrics();
		WindowManager windowManager = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		Display display = windowManager.getDefaultDisplay();
		display.getMetrics(dMetrics);

		screenw = dMetrics.widthPixels;
		screenh = dMetrics.heightPixels;
		density = dMetrics.density;
		densityDpi = dMetrics.densityDpi;

		screenh_nonavbar = screenh;

		int ver = Build.VERSION.SDK_INT;

		// 新版本的android 系统有导航栏,造成无法正确获取高度
		if (ver == 13) {
			try {
				Method mt = display.getClass().getMethod("getRealHeight");
				screenh_nonavbar = (Integer) mt.invoke(display);
			} catch (Exception e) {
			}
		} else if (ver > 13) {
			try {
				Method mt = display.getClass().getMethod("getRawHeight");
				screenh_nonavbar = (Integer) mt.invoke(display);
			} catch (Exception e) {
			}
		}

		real_scontenth = screenh_nonavbar - getStatusBarHeight(context);

	}

	/**
	 * 电量栏高度
	 * 
	 * @return
	 */
	public static int getStatusBarHeight(Context context) {
		Class<?> c = null;
		Object obj = null;
		Field field = null;
		int x = 0, sbar = 0;
		try {
			c = Class.forName("com.android.internal.R$dimen");
			obj = c.newInstance();
			field = c.getField("status_bar_height");
			x = Integer.parseInt(field.get(obj).toString());
			sbar = context.getResources().getDimensionPixelSize(x);
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		return sbar;
	}

}


          以上的文件已经解释的相当详细了,要完整的代码请转移到至此:android自定义键盘,关于其他的一些在布局自定义属性、和弹出和隐藏的效果知识,我就不讲解了,网上有相当多的资源,有问题欢迎指教,一直在分享自己解决每个实际问题的方法,请大家关注我,多多评论我的博文,让我们共同进步。其实这个向上顶的功能是开源中国的一位前辈的代码,链接如下:开源中国自定义键盘,非常感谢,有些代码还没有看懂,特别是计算屏幕大小、键盘大小、重新定位布局文件位置的,这些关键代码希望有人能够解释一下,在他的基础上我加了自己的东西和理解,再次感谢,希望让更多遇到同样的自定义键盘在困扰的同事和后面的新手,少走弯路,不要重复造轮子,我一直觉得是这样,“拿来主义'加上自己的创新,再次分享,让整个android开发环境变得更自由,更开放,我会持续分享在实际项目中遇到问题的解决方案,有需要资源的可以联系我。

 

         有时候真的很感谢网络上的这些前辈,基本上一开始的解决方案和思路,都得益于这些前辈,特别是csdn、安卓巴士、eoe、开源中国等这些专业的程序员网站,是这些网站的很多资源让我认识到一个个知识点,最终能够运用到自己实际的项目中来。
 

 

—————————————————————————————分割线2015年9月21日10:42:48——————————————————

增加随机生成26个字母和标题符号功能:

// 随机字母
private void randomalpkey(Keyboard mKeyboard) {
List<Key> keyList = mKeyboard.getKeys();
// 查找出a-z的数字键
List<Key> newkeyList = new ArrayList<Key>();
for (int i = 0; i < keyList.size(); i++) {
if (keyList.get(i).label != null
&& isword(keyList.get(i).label.toString())) {
newkeyList.add(keyList.get(i));
}
}
// 数组长度
int count = newkeyList.size();
// 结果集
List<KeyModel> resultList = new ArrayList<KeyModel>();
// 用一个LinkedList作为中介
LinkedList<KeyModel> temp = new LinkedList<KeyModel>();
// 初始化temp
for (int i = 0; i < count - 1; i++) {
temp.add(new KeyModel(97 + i, "" + (char) (97 + i)));
}
temp.add(new KeyModel(64, "" + (char) 64));// .
// 取数
Random rand = new Random();
for (int i = 0; i < count; i++) {
int num = rand.nextInt(count - i);
resultList.add(new KeyModel(temp.get(num).getCode(), temp.get(num)
.getLable()));
temp.remove(num);
}
for (int i = 0; i < newkeyList.size(); i++) {
newkeyList.get(i).label = resultList.get(i).getLable();
newkeyList.get(i).codes[0] = resultList.get(i).getCode();
}


mKeyboardView.setKeyboard(mKeyboard);
}


/**
* 标点符号键盘-随机
*/
private void randomInterpunctionkey(Keyboard mKeyboard) {
List<Key> keyList = mKeyboard.getKeys();


// 查找出标点符号的数字键
List<Key> newkeyList = new ArrayList<Key>();
for (int i = 0; i < keyList.size(); i++) {
if (keyList.get(i).label != null
&& isInterpunction(keyList.get(i).label.toString())) {
newkeyList.add(keyList.get(i));
}
}
// 数组长度
int count = newkeyList.size();
// 结果集
List<KeyModel> resultList = new ArrayList<KeyModel>();
// 用一个LinkedList作为中介
LinkedList<KeyModel> temp = new LinkedList<KeyModel>();


// 初始化temp
temp.add(new KeyModel(33, "" + (char) 33));
temp.add(new KeyModel(34, "" + (char) 34));
temp.add(new KeyModel(35, "" + (char) 35));
temp.add(new KeyModel(36, "" + (char) 36));
temp.add(new KeyModel(37, "" + (char) 37));
temp.add(new KeyModel(38, "" + (char) 38));
temp.add(new KeyModel(39, "" + (char) 39));
temp.add(new KeyModel(40, "" + (char) 40));
temp.add(new KeyModel(41, "" + (char) 41));
temp.add(new KeyModel(42, "" + (char) 42));
temp.add(new KeyModel(43, "" + (char) 43));
temp.add(new KeyModel(45, "" + (char) 45));
temp.add(new KeyModel(47, "" + (char) 47));
temp.add(new KeyModel(58, "" + (char) 58));
temp.add(new KeyModel(59, "" + (char) 59));
temp.add(new KeyModel(60, "" + (char) 60));
temp.add(new KeyModel(61, "" + (char) 61));
temp.add(new KeyModel(62, "" + (char) 62));
temp.add(new KeyModel(63, "" + (char) 63));
temp.add(new KeyModel(91, "" + (char) 91));
temp.add(new KeyModel(92, "" + (char) 92));
temp.add(new KeyModel(93, "" + (char) 93));
temp.add(new KeyModel(94, "" + (char) 94));
temp.add(new KeyModel(95, "" + (char) 95));
temp.add(new KeyModel(96, "" + (char) 96));
temp.add(new KeyModel(123, "" + (char) 123));
temp.add(new KeyModel(124, "" + (char) 124));
temp.add(new KeyModel(125, "" + (char) 125));
temp.add(new KeyModel(126, "" + (char) 126));


// 取数
Random rand = new Random();
for (int i = 0; i < count; i++) {
int num = rand.nextInt(count - i);
resultList.add(new KeyModel(temp.get(num).getCode(), temp.get(num)
.getLable()));
temp.remove(num);
}
for (int i = 0; i < newkeyList.size(); i++) {
newkeyList.get(i).label = resultList.get(i).getLable();
newkeyList.get(i).codes[0] = resultList.get(i).getCode();
}


mKeyboardView.setKeyboard(mKeyboard);
}

 

 

——————————————————————————————分割线  向上顶布局主类修改2015年10月15日13:44:59————————————

 

package client.verbank.mtp.allone.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.Keyboard.Key;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.os.Build;
import android.os.SystemClock;
import android.text.Editable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.ActionMode;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;
import client.verbank.mtp.allone.R;
import client.verbank.mtp.allone.consts.ISystemCommData;

/**
 * 数字键盘(修改bug,金額輸入 .36 應該自動變成 0.36)
 * 
 * @Project: FEIB_AndroidStation 
 * @Title: MyKeyboardDigital.java 
 * @Package client.verbank.mtp.allone.util 
 * @Description: TODO 
 * @author qiulinhe qiu.linhe@allone.cn 
 * @date 2015年10月14日 上午11:04:48 
 * @Copyright: 2015 www.allone.cn Inc. All rights reserved. 
 * @version V3.0.0   
 */
public class MyKeyboardDigital extends EditText implements
		OnKeyboardActionListener, ISystemCommData {

	private Keyboard k1;// 字母键盘
	private Keyboard k2;// 标点符号键盘
	private Keyboard k3;// 数字键盘
	public boolean isnun = false;// 是否标点符号键盘
	public boolean isupper = false;// 是否大写

	private KeyboardView mKeyboardView;
	private Keyboard mKeyboard;

	private Window mWindow;
	private View mDecorView;
	private View mContentView;

	private PopupWindow mKeyboardWindow;

	private boolean needcustomkeyboard = true; // 是否启用自定义键盘
	private boolean randomkeys = false; // 数字按键是否随机

	private int scrolldis = 450; // 输入框在键盘被弹出时,要被推上去的距离

	public static int screenw = -1;// 未知宽高
	public static int screenh = -1;
	public static int screenh_nonavbar = -1; // 不包含导航栏的高度
	public static int real_scontenth = -1; // 实际内容高度, 计算公式:屏幕高度-导航栏高度-电量栏高度

	public static float density = 1.0f;
	public static int densityDpi = 160;

	// 接收用户在系统设定界面的自定义金额
	String selfdig20 = "200,000";
	String orgindi20 = "200,000";
	// 接收用户在系统设定界面的自定义金额
	String selfdig50 = "500,000";
	String orgindi50 = "500,000";
	// 接收用户在系统设定界面的自定义金额
	String selfdig100 = "10,000,000";
	String orgindi100 = "10,000,000";

	/**
	 * @param context
	 * 
	 * @param attrs
	 */
	public MyKeyboardDigital(Context context, AttributeSet attrs) {
		super(context, attrs);
		initAttributes(context);
		initKeyboard(context, attrs);

		// TODO Auto-generated constructor stub
	}

	/**
	 * @param context
	 * @param attrs
	 * @param defStyle
	 */
	public MyKeyboardDigital(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		selfdig20 = SharepreferencesUtilSystemSettings.getValue(getContext(),
				System_key_SelfAmout2, "200,000");
		selfdig50 = SharepreferencesUtilSystemSettings.getValue(getContext(),
				System_key_SelfAmout5, "500,000");
		selfdig100 = SharepreferencesUtilSystemSettings.getValue(getContext(),
				System_key_SelfAmout10, "10,000,000");
		initAttributes(context);
		initKeyboard(context, attrs);
		// TODO Auto-generated constructor stub
	}

	private void initKeyboard(Context context, AttributeSet attrs) {
		selfdig20 = SharepreferencesUtilSystemSettings.getValue(getContext(),
				System_key_SelfAmout2, "200,000");
		selfdig50 = SharepreferencesUtilSystemSettings.getValue(getContext(),
				System_key_SelfAmout5, "500,000");
		selfdig100 = SharepreferencesUtilSystemSettings.getValue(getContext(),
				System_key_SelfAmout10, "10,000,000");
		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.keyboard);

		if (a.hasValue(R.styleable.keyboard_xml)) {
			needcustomkeyboard = true;

			int xmlid = a.getResourceId(R.styleable.keyboard_xml, 0);

			mKeyboard = new Keyboard(context, xmlid);

			mKeyboardView = (KeyboardView) LayoutInflater.from(context)
					.inflate(R.layout.mykeyboardviewdigit, null);
			if (a.hasValue(R.styleable.keyboard_randomkeys)) {
				boolean random = a.getBoolean(R.styleable.keyboard_randomkeys,
						false);
				randomkeys = random;

				if (random) {
					randomdigkey(mKeyboard);
				}
			}
			selfdig20 = SharepreferencesUtilSystemSettings.getValue(
					getContext(), System_key_SelfAmout2, "200,000");
			selfdig50 = SharepreferencesUtilSystemSettings.getValue(
					getContext(), System_key_SelfAmout5, "500,000");
			selfdig100 = SharepreferencesUtilSystemSettings.getValue(
					getContext(), System_key_SelfAmout10, "10,000,000");
			selfdigkey();
			// mKeyboardView.setKeyboard(mKeyboard);
			mKeyboardView.setEnabled(true);
			mKeyboardView.setPreviewEnabled(false);
			mKeyboardView.setOnKeyboardActionListener(this);

			mKeyboardWindow = new PopupWindow(mKeyboardView,
					ViewGroup.LayoutParams.MATCH_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
			mKeyboardWindow.setAnimationStyle(R.style.AnimationFade);
			// mKeyboardWindow.setBackgroundDrawable(new BitmapDrawable());
			// mKeyboardWindow.setOutsideTouchable(true);
			mKeyboardWindow.setOnDismissListener(new OnDismissListener() {

				@Override
				public void onDismiss() {
					// TODO Auto-generated method stub
					if (scrolldis > 0) {
						int temp = scrolldis;
						// scrolldis = 0;
						if (null != mContentView) {
							mContentView.scrollBy(0, -temp);
						}
					}
				}
			});
		} else {
			needcustomkeyboard = false;
		}

		a.recycle();

	}

	private void showKeyboard() {
		if (null != mKeyboardWindow) {
			if (!mKeyboardWindow.isShowing()) {
				if (randomkeys) {
					randomdigkey(mKeyboard);
				}

				selfdig20 = SharepreferencesUtilSystemSettings.getValue(
						getContext(), System_key_SelfAmout2, "200,000");
				selfdig50 = SharepreferencesUtilSystemSettings.getValue(
						getContext(), System_key_SelfAmout5, "500,000");
				selfdig100 = SharepreferencesUtilSystemSettings.getValue(
						getContext(), System_key_SelfAmout10, "10,000,000");
				selfdigkey();
				// mKeyboardView.setKeyboard(mKeyboard);

				mKeyboardWindow.setAnimationStyle(R.style.AnimBottom);
				mKeyboardWindow.showAtLocation(this.mDecorView, Gravity.RIGHT
						| Gravity.BOTTOM, 0, 0);
				mKeyboardWindow.update();

				if (null != mDecorView && null != mContentView) {
					int[] pos = new int[2];
					// 计算弹出的键盘的尺寸
					getLocationOnScreen(pos);
					float height = dpToPx(getContext(), 240);

					// int []hsmlpos=new int[2];
					// mDecorView.getLocationOnScreen(hsmlpos);

					Rect outRect = new Rect();
					// 然后该View有个getWindowVisibleDisplayFrame()方法可以获取到程序显示的区域,
					// * 包括标题栏,但不包括状态栏。
					mDecorView.getWindowVisibleDisplayFrame(outRect);// 获得view空间,也就是除掉标题栏
					// outRect.top表示状态栏(通知栏)
					int screen = real_scontenth;
					// scrolldis = (int) ((pos[1] + getMeasuredHeight() -
					// outRect.top)
					// - (screen - height) + 500);

					if (scrolldis > 0) {
						mContentView.scrollBy(0, scrolldis);
					}
				}

			}
		}
	}

	private void hideKeyboard() {
		if (null != mKeyboardWindow) {
			if (mKeyboardWindow.isShowing()) {
				mKeyboardWindow.dismiss();
			}
		}
	}

	private void hideSysInput() {
		if (this.getWindowToken() != null) {
			InputMethodManager imm = (InputMethodManager) getContext()
					.getSystemService(Context.INPUT_METHOD_SERVICE);
			imm.hideSoftInputFromWindow(this.getWindowToken(), 0);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);
		requestFocus();
		requestFocusFromTouch();

		if (needcustomkeyboard) {
			hideSysInput();
			showKeyboard();
		}

		return true;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (null != mKeyboardWindow) {
				if (mKeyboardWindow.isShowing()) {
					mKeyboardWindow.dismiss();
					return true;
				}
			}
		}

		return super.onKeyDown(keyCode, event);

	}

	@Override
	public void onAttachedToWindow() {
		super.onAttachedToWindow();

		this.mWindow = ((Activity) getContext()).getWindow();
		this.mDecorView = this.mWindow.getDecorView();
		this.mContentView = this.mWindow
				.findViewById(Window.ID_ANDROID_CONTENT);

		hideSysInput();
	}

	@Override
	public void onDetachedFromWindow() {
		super.onDetachedFromWindow();

		hideKeyboard();

		mKeyboardWindow = null;
		mKeyboardView = null;
		mKeyboard = null;

		mDecorView = null;
		mContentView = null;
		mWindow = null;
	}

	@Override
	public void onPress(int primaryCode) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onRelease(int primaryCode) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onKey(int primaryCode, int[] keyCodes) {
		// TODO Auto-generated method stub
		Editable editable = this.getText();
		int start = this.getSelectionStart();
		if (primaryCode == Keyboard.KEYCODE_CANCEL) {// 隐藏键盘
			hideKeyboard();
		} else if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退
			if (editable != null && editable.length() > 0) {
				if (start > 0) {
					editable.delete(start - 1, start);
				}
			}
		} else if (primaryCode == Keyboard.KEYCODE_SHIFT) {// 大小写切换
			changeKey();
			mKeyboardView.setKeyboard(k1);

		}

		else if (primaryCode == Keyboard.KEYCODE_DONE) {// 标点符号键盘切换
			if (isnun) {
				isnun = false;
				mKeyboardView.setKeyboard(k1);
			} else {
				isnun = true;
				mKeyboardView.setKeyboard(k2);
			}
		} else if (primaryCode == 46) {

			// 当用户输入.3的时候自动转换为0.3
			if (editable != null && editable.length() > 0) {
				if (start > 0) {
					editable.insert(start, ".");
				}
			} else {
				editable.insert(start, "0.");
			}

		}

		else if (primaryCode == -110) {
			editable.insert(start, "00");
		} else if (primaryCode == -20000) {
			editable.insert(start, selfdig20);
		} else if (primaryCode == -50000) {
			editable.insert(start, selfdig50);
		} else if (primaryCode == -10000) {
			editable.insert(start, selfdig100);
		} else if (0x0 <= primaryCode && primaryCode <= 0x7f) {
			// 可以直接输入的字符(如0-9,.),他们在键盘映射xml中的keycode值必须配置为该字符的ASCII码
			editable.insert(start, Character.toString((char) primaryCode));
		} else if (primaryCode > 0x7f) {
			Key mkey = getKeyByKeyCode(primaryCode);
			// 可以直接输入的字符(如0-9,.),他们在键盘映射xml中的keycode值必须配置为该字符的ASCII码
			editable.insert(start, mkey.label);

		} else {
			// 其他一些暂未开放的键指令,如next到下一个输入框等指令
		}
	}

	// 数字键盘测试是否改变200,000和500,000让用户自定义

	private void selfdigkey() {
		if (mKeyboard == null) {
			return;
		}

		List<Key> keyList = k3.getKeys();

		// 查找出0-9的数字键
		for (int i = 0, size = keyList.size(); i < size; i++) {
			Key key = keyList.get(i);

			CharSequence label = key.label;
			// if (label != null && label.toString().equals(orgindi20)) {
			// keyList.get(i).label = selfdig;
			// orgindi20 = selfdig;
			// }

			if (label != null && label.toString().equals(orgindi20)) {
				keyList.get(i).label = selfdig20;
				keyList.get(i).codes[0] = -20000;
				orgindi20 = selfdig20;
			}
			if (label != null && label.toString().equals(orgindi50)) {
				keyList.get(i).label = selfdig50;
				keyList.get(i).codes[0] = -50000;
				orgindi50 = selfdig50;
			}
			if (label != null && label.toString().equals(orgindi100)) {
				keyList.get(i).label = selfdig100;
				keyList.get(i).codes[0] = -10000;
				orgindi100 = selfdig100;
			}
		}

		mKeyboardView.setKeyboard(k3);
	}

	/**
	 * 键盘大小写切换
	 */
	private void changeKey() {
		List<Key> keylist = k1.getKeys();
		if (isupper) {// 大写切换小写
			isupper = false;
			for (Key key : keylist) {
				if (key.label != null && isword(key.label.toString())) {
					key.label = key.label.toString().toLowerCase();
					key.codes[0] = key.codes[0] + 32;
				}
			}
		} else {// 小写切换大写
			isupper = true;
			for (Key key : keylist) {
				if (key.label != null && isword(key.label.toString())) {
					key.label = key.label.toString().toUpperCase();
					key.codes[0] = key.codes[0] - 32;
				}
			}
		}
	}

	private boolean isword(String str) {
		String wordstr = "abcdefghijklmnopqrstuvwxyz";
		if (wordstr.indexOf(str.toLowerCase()) > -1) {
			return true;
		}
		return false;
	}

	@Override
	public void onText(CharSequence text) {
		// TODO Auto-generated method stub

	}

	@Override
	public void swipeLeft() {
		// TODO Auto-generated method stub

	}

	@Override
	public void swipeRight() {
		// TODO Auto-generated method stub

	}

	@Override
	public void swipeDown() {
		// TODO Auto-generated method stub

	}

	@Override
	public void swipeUp() {
		// TODO Auto-generated method stub

	}

	private Key getKeyByKeyCode(int keyCode) {
		if (null != mKeyboard) {
			List<Key> mKeys = mKeyboard.getKeys();
			for (int i = 0, size = mKeys.size(); i < size; i++) {
				Key mKey = mKeys.get(i);

				int codes[] = mKey.codes;

				if (codes[0] == keyCode) {
					return mKey;
				}
			}
		}

		return null;
	}

	private void initAttributes(Context context) {

		k1 = new Keyboard(context, R.xml.qwerty);
		k2 = new Keyboard(context, R.xml.qwerty2);
		k3 = new Keyboard(context, R.xml.amountinputkeyboard);

		initScreenParams(context);
		this.setLongClickable(false);
		this.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
		removeCopyAbility();

		if (this.getText() != null) {
			this.setSelection(this.getText().length());
		}

		this.setOnFocusChangeListener(new OnFocusChangeListener() {

			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				// TODO Auto-generated method stub
				if (!hasFocus) {
					hideKeyboard();
				}
			}
		});

	}

	@TargetApi(11)
	private void removeCopyAbility() {
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			this.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

				@Override
				public boolean onCreateActionMode(ActionMode mode, Menu menu) {
					return false;
				}

				@Override
				public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
					return false;
				}

				@Override
				public void onDestroyActionMode(ActionMode mode) {

				}

				@Override
				public boolean onActionItemClicked(ActionMode mode,
						MenuItem item) {
					return false;
				}
			});
		}
	}

	private boolean isNumber(String str) {
		String wordstr = "0123456789";
		if (wordstr.indexOf(str) > -1) {
			return true;
		}
		return false;
	}

	private void randomdigkey(Keyboard mKeyboard) {
		if (mKeyboard == null) {
			return;
		}

		List<Key> keyList = mKeyboard.getKeys();

		// 查找出0-9的数字键
		List<Key> newkeyList = new ArrayList<Key>();
		for (int i = 0, size = keyList.size(); i < size; i++) {
			Key key = keyList.get(i);
			CharSequence label = key.label;
			if (label != null && isNumber(label.toString())) {
				newkeyList.add(key);
			}
		}

		int count = newkeyList.size();

		List<KeyModel> resultList = new ArrayList<KeyModel>();

		LinkedList<KeyModel> temp = new LinkedList<KeyModel>();

		for (int i = 0; i < count; i++) {
			temp.add(new KeyModel(48 + i, i + ""));
		}

		Random rand = new SecureRandom();
		rand.setSeed(SystemClock.currentThreadTimeMillis());

		for (int i = 0; i < count; i++) {
			int num = rand.nextInt(count - i);
			KeyModel model = temp.get(num);
			resultList.add(new KeyModel(model.getCode(), model.getLable()));
			temp.remove(num);
		}

		for (int i = 0, size = newkeyList.size(); i < size; i++) {
			Key newKey = newkeyList.get(i);
			KeyModel resultmodle = resultList.get(i);
			newKey.label = resultmodle.getLable();
			newKey.codes[0] = resultmodle.getCode();
		}

	}

	class KeyModel {

		private Integer code;
		private String label;

		public KeyModel(Integer code, String lable) {
			this.code = code;
			this.label = lable;
		}

		public Integer getCode() {
			return code;
		}

		public void setCode(Integer code) {
			this.code = code;
		}

		public String getLable() {
			return label;
		}

		public void setLabel(String lable) {
			this.label = lable;
		}

	}

	/**
	 * 密度转换为像素值
	 * 
	 * @param dp
	 * @return
	 */
	public static int dpToPx(Context context, float dp) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dp * scale + 0.5f);
	}

	private void initScreenParams(Context context) {
		DisplayMetrics dMetrics = new DisplayMetrics();
		WindowManager windowManager = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		Display display = windowManager.getDefaultDisplay();
		display.getMetrics(dMetrics);

		screenw = dMetrics.widthPixels;
		screenh = dMetrics.heightPixels;
		density = dMetrics.density;
		densityDpi = dMetrics.densityDpi;

		screenh_nonavbar = screenh;

		int ver = Build.VERSION.SDK_INT;

		// 新版本的android 系统有导航栏,造成无法正确获取高度
		if (ver == 13) {
			try {
				Method mt = display.getClass().getMethod("getRealHeight");
				screenh_nonavbar = (Integer) mt.invoke(display);
			} catch (Exception e) {
			}
		} else if (ver > 13) {
			try {
				Method mt = display.getClass().getMethod("getRawHeight");
				screenh_nonavbar = (Integer) mt.invoke(display);
			} catch (Exception e) {
			}
		}

		real_scontenth = screenh_nonavbar - getStatusBarHeight(context);

	}

	/**
	 * 电量栏高度
	 * 
	 * @return
	 */
	public static int getStatusBarHeight(Context context) {
		Class<?> c = null;
		Object obj = null;
		Field field = null;
		int x = 0, sbar = 0;
		try {
			c = Class.forName("com.android.internal.R$dimen");
			obj = c.newInstance();
			field = c.getField("status_bar_height");
			x = Integer.parseInt(field.get(obj).toString());
			sbar = context.getResources().getDimensionPixelSize(x);
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		return sbar;
	}

}

================================分割线,更新时间====================================

因为上述自定义的键盘在很多手机上,向上推的高度是固定的,由于分辨率的原因,所以有些还是会挡住下面的按钮,所以我找到了一个先计算出手机的密度,再乘以一个固定的数值,然后将界面整体向上移动:

 

	DisplayMetrics dm = contextceshi.getResources()
							.getDisplayMetrics();
					int scalsize = (int) (80 * dm.density);

					if (scalsize > 0) {
						int temp = scalsize;
						// scrolldis = 0;
						if (null != mContentView) {
							mContentView.scrollBy(100, -temp);
						}
					}

 

 

=====================================分割线更新时间2016年3月16日11:00:11===============================================================

 

 

上述的键盘布局,你会发现第一行只有一个下拉的按键就是隐藏键盘,但这个如果有了整体背景之后,横竖的间距就有出现,这样你从美工那里拿来的图片,设置成这个按键的背景之后,就会发现无法覆盖整体的背景,所以呢,我们需要设置他的横竖屏的间距,关键是可以设置成负值,这样就能自由调整。如下代码:

 

<?xml version="1.0" encoding="UTF-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="1.2px"
    android:keyWidth="9.89%p"
    android:verticalGap="2px" >

    <Row
        android:horizontalGap="-5px"
        android:keyHeight="28dp"
        android:verticalGap="2px" >
        <Key
            android:codes="-3"
            android:keyHeight="22dp"
            android:keyIcon="@drawable/keyboardblow"
            android:keyWidth="100%p" />
    </Row>

 

 

 

 

 

 

 

 

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值