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

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:horizontalGap="1px"  
  4.     android:keyWidth="9.7%p"  
  5.     android:verticalGap="3px" >  
  6.   
  7.     <Row android:verticalGap="18px" >  
  8.         <Key  
  9.             android:codes="-3"  
  10.             android:keyIcon="@drawable/ret"  
  11.             android:keyWidth="100%p" />  
  12.     </Row>  
  13.     。。。。。。。。。。。。。。。  
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 。。。。。。。。。。。。  
  2.     <Row android:keyHeight="40dp" >  
  3.         <Key  
  4.             android:codes="-1"  
  5.             android:keyEdgeFlags="left"  
  6.             android:keyIcon="@drawable/updata"  
  7.             android:keyWidth="9.55%p" />  
  8.         <Key  
  9.             android:codes="-4"  
  10.             android:keyLabel=".?&" />  
  11.         <Key  
  12.             android:codes="122"  
  13.             android:keyLabel="z" />  
  14.         <Key  
  15.             android:codes="120"  
  16.             android:keyLabel="x" />  
  17.         <Key  
  18.             android:codes="99"  
  19.             android:keyLabel="c" />  
  20.         <Key  
  21.             android:codes="118"  
  22.             android:keyLabel="v" />  
  23.         <Key  
  24.             android:codes="98"  
  25.             android:keyLabel="b" />  
  26.         <Key  
  27.             android:codes="110"  
  28.             android:keyLabel="n" />  
  29.         <Key  
  30.             android:codes="109"  
  31.             android:keyLabel="m" />  
  32.     </Row>  
  33.   
  34. </Keyboard>  

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

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:horizontalGap="1px"  
  4.     android:keyWidth="9.7%p"  
  5.     android:verticalGap="3px" >  
  6.   
  7.     <Row android:verticalGap="18px">  
  8.         <Key  
  9.             android:codes="-3"  
  10.             android:keyIcon="@drawable/ret"  
  11.             android:keyWidth="100%p"  
  12.             android:verticalGap="3px"  />  
  13.     </Row>  
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 。。。。。。。。。。。。。。。。。。。。。。<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">。。。。。。。。。。。。。。。。。。。</span>  
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1.  <Row android:keyHeight="40dp" >  
  2.     <Key  
  3.         android:codes="-1"  
  4.         android:isSticky="true"  
  5.         android:keyIcon="@drawable/updata" />  
  6.     <Key  
  7.         android:codes="-4"  
  8.         android:keyLabel="abc" />  
  9.     <Key  
  10.         android:codes="96"  
  11.         android:keyLabel="`" />  
  12.     <Key  
  13.         android:codes="32"  
  14.         android:isRepeatable="true"  
  15.         android:keyLabel="space"  
  16.         android:keyWidth="39%p" />  
  17.     <Key  
  18.         android:codes="46"  
  19.         android:keyLabel="." />  
  20.     <Key  
  21.         android:codes="44"  
  22.         android:keyLabel="," />  
  23. </Row>  
  24.   
  25. /Keyboard>  

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

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:horizontalGap="3px"  
  4.   
  5.     android:keyWidth="24.2%p"  
  6.     android:verticalGap="3px" >  
  7.   
  8.     <Row android:verticalGap="18px" >  
  9.         <Key  
  10.             android:codes="-3"  
  11.             android:keyIcon="@drawable/ret"  
  12.             android:keyWidth="100%p"  
  13.             android:verticalGap="3px" />  
  14.     </Row>  
  15.    
  16.  。。。。。。。。。。。。。  
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 。。。。。。。。。。。。。  
  2.     <Row android:keyHeight="50dp" >  
  3.         <Key  
  4.             android:codes="46"  
  5.             android:keyLabel="." />  
  6.         <Key  
  7.             android:codes="48"  
  8.             android:keyLabel="0" />  
  9.         <Key  
  10.             android:codes="-110"  
  11.             android:keyLabel="00" />  
  12.         <Key  
  13.             android:codes="-5"  
  14.             android:isRepeatable="true"  
  15.             android:keyEdgeFlags="right"  
  16.             android:keyIcon="@drawable/deletepng" />  
  17.     </Row>  
  18.   
  19. </Keyboard>  

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

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <Row <span style="color:#ff0000;"><strong>android:verticalGap="18px"</strong></span> >  
  2.         <Key  
  3.             android:codes="-3"  
  4.             android:keyIcon="@drawable/ret"  
  5.             android:keyWidth="100%p"  
  6.             android:verticalGap="3px" />  
  7.     </Row>  

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

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"  
  2.  android:horizontalGap="3px"  
  3.   
  4.     android:keyWidth="24.2%p"  
  5.     android:verticalGap="3px" </strong>  

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

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

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:mykeyboard="http://schemas.android.com/apk/res/com.example.testkeyboard"  
  3.     android:id="@+id/fulllayout"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:orientation="vertical" >  
  7.   
  8.    <com.example.testkeyboard.MyKeyboard// 自定义<span style="font-family: Arial, Helvetica, sans-serif;">EditText,继承于EditText,实现键盘implements OnKeyboardActionListener接口  
  9.         android:id="@+id/et"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="30dp"  
  12.         android:layout_marginTop="10dp"  
  13.  android:background="@drawable/gray_shape" //设置圆角效果  
  14.         android:gravity="center"  
  15.         android:hint="身份证号"  
  16.         android:singleLine="true"  
  17.         android:textColor="@color/black"  
  18.         android:textColorHint="#BABABA"  
  19.         mykeyboard:xml="@xml/amountinputkeyboard" />  //  
  20.   
  21.     <com.example.testkeyboard.MyKeyboard  
  22.         android:id="@+id/etChar"  
  23.         android:layout_width="match_parent"  
  24.         android:layout_height="30dp"  
  25.         android:layout_marginTop="10dp"  
  26.         android:background="@drawable/gray_shape"  
  27.         android:gravity="center"  
  28.         android:hint="字母和标点符号键盘"  
  29.         android:singleLine="true"  
  30.         android:textColor="@color/black"  
  31.         android:textColorHint="#BABABA"  
  32.         mykeyboard:xml="@xml/qwerty" />  
  33.   
  34. </LinearLayout>  
        键盘单独布局文件: res\layout\mykeyboardview.xml

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android"//系统自带的键盘布局文件  
  3.     android:id="@+id/keyboard_view"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="wrap_content"  
  6.     android:layout_alignParentBottom="true"  
  7.    <span style="color:#ff0000;"> android:background="@color/white"  //设置键盘的整个背景为白色</span>  
  8.     android:focusable="true"  
  9.     android:focusableInTouchMode="true"  
  10.     android:keyBackground="@drawable/d"  
  11.     android:keyTextColor="#A8AAAB"  
  12.     android:keyTextSize="20sp"  
  13.     android:labelTextSize="15sp"  
  14.     android:padding="2.5dp" />  
  15.   
  16. <!-- android:keyBackground="@drawable/data" -->  
      该类主要是让主控制类加载。

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

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.example.testkeyboard;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Method;  
  5. import java.security.SecureRandom;  
  6. import java.util.ArrayList;  
  7. import java.util.LinkedList;  
  8. import java.util.List;  
  9. import java.util.Random;  
  10.   
  11. import android.annotation.TargetApi;  
  12. import android.app.Activity;  
  13. import android.content.Context;  
  14. import android.content.res.TypedArray;  
  15. import android.graphics.Rect;  
  16. import android.inputmethodservice.Keyboard;  
  17. import android.inputmethodservice.Keyboard.Key;  
  18. import android.inputmethodservice.KeyboardView;  
  19. import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;  
  20. import android.os.Build;  
  21. import android.os.SystemClock;  
  22. import android.text.Editable;  
  23. import android.util.AttributeSet;  
  24. import android.util.DisplayMetrics;  
  25. import android.view.ActionMode;  
  26. import android.view.Display;  
  27. import android.view.Gravity;  
  28. import android.view.KeyEvent;  
  29. import android.view.LayoutInflater;  
  30. import android.view.Menu;  
  31. import android.view.MenuItem;  
  32. import android.view.MotionEvent;  
  33. import android.view.View;  
  34. import android.view.ViewGroup;  
  35. import android.view.Window;  
  36. import android.view.WindowManager;  
  37. import android.view.inputmethod.EditorInfo;  
  38. import android.view.inputmethod.InputMethodManager;  
  39. import android.widget.EditText;  
  40. import android.widget.PopupWindow;  
  41. import android.widget.PopupWindow.OnDismissListener;  
  42.   
  43. /** 
  44.  *  
  45.  * 自定义键盘,有按下效果 
  46.  * 
  47.  */  
  48. public class MyKeyboard extends EditText implements OnKeyboardActionListener {  
  49.   
  50.     private Keyboard k1;// 字母键盘  
  51.     private Keyboard k2;// 标点符号键盘  
  52.     public boolean isnun = false;// 是否标点符号键盘  
  53.     public boolean isupper = false;// 是否大写  
  54.   
  55.     private KeyboardView mKeyboardView;  
  56.     private Keyboard mKeyboard;  
  57.   
  58.     private Window mWindow;  
  59.     private View mDecorView;  
  60.     private View mContentView;  
  61.   
  62.     private PopupWindow mKeyboardWindow;  
  63.   
  64.     private boolean needcustomkeyboard = true// 是否启用自定义键盘  
  65.     private boolean randomkeys = false// 数字按键是否随机  
  66.   
  67.     private int scrolldis = 50// 输入框在键盘被弹出时,要被推上去的距离  
  68.   
  69.     public static int screenw = -1;// 未知宽高  
  70.     public static int screenh = -1;  
  71.     public static int screenh_nonavbar = -1// 不包含导航栏的高度  
  72.     public static int real_scontenth = -1// 实际内容高度, 计算公式:屏幕高度-导航栏高度-电量栏高度  
  73.   
  74.     public static float density = 1.0f;  
  75.     public static int densityDpi = 160;  
  76.   
  77.     /** 
  78.      * @param context 
  79.      * @param attrs 
  80.      */  
  81.     public MyKeyboard(Context context, AttributeSet attrs) {  
  82.         super(context, attrs);  
  83.         initAttributes(context);  
  84.         initKeyboard(context, attrs);  
  85.   
  86.         // TODO Auto-generated constructor stub  
  87.     }  
  88.   
  89.     /** 
  90.      * @param context 
  91.      * @param attrs 
  92.      * @param defStyle 
  93.      */  
  94.     public MyKeyboard(Context context, AttributeSet attrs, int defStyle) {  
  95.         super(context, attrs, defStyle);  
  96.         initAttributes(context);  
  97.         initKeyboard(context, attrs);  
  98.         // TODO Auto-generated constructor stub  
  99.     }  
  100.         //键盘初始化  
  101.     private void initKeyboard(Context context, AttributeSet attrs) {  
  102.   
  103.         TypedArray a = context.obtainStyledAttributes(attrs,  
  104.                 R.styleable.keyboard);  
  105.   
  106.         if (a.hasValue(R.styleable.keyboard_xml)) {  
  107.             needcustomkeyboard = true;  
  108.   
  109.             int xmlid = a.getResourceId(R.styleable.keyboard_xml, 0);  
  110.   
  111.             mKeyboard = new Keyboard(context, xmlid);  
  112.   
  113.             <span style="color:#ff0000;"><strong>mKeyboardView = (KeyboardView) LayoutInflater.from(context)  
  114.                     .inflate(R.layout.mykeyboardview, null);  //加载键盘布局</strong></span>  
  115.             if (a.hasValue(R.styleable.keyboard_randomkeys)) {  
  116.                 boolean random = a.getBoolean(R.styleable.keyboard_randomkeys,  
  117.                         false);  
  118.                 randomkeys = random;  
  119.   
  120.                 if (random) {  
  121.                     randomdigkey(mKeyboard);  
  122.                 }  
  123.             }  
  124.                         <span style="color:#ff0000;"><strong>//使用popupwindow在下方弹出键盘,设置弹出和隐藏的动画效果</strong></span>  
  125.             mKeyboardView.setKeyboard(mKeyboard);  
  126.             mKeyboardView.setEnabled(true);  
  127.             mKeyboardView.setPreviewEnabled(false);  
  128.             mKeyboardView.setOnKeyboardActionListener(this);  
  129.   
  130.             mKeyboardWindow = new PopupWindow(mKeyboardView,  
  131.                     ViewGroup.LayoutParams.MATCH_PARENT,  
  132.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
  133.             <strong><span style="color:#ff0000;">mKeyboardWindow.setAnimationStyle(R.style.AnimationFade);//设置动画效果,文件在资源里面,这里就不贴出来。</span></strong>  
  134.             // mKeyboardWindow.setBackgroundDrawable(new BitmapDrawable());  
  135.             // mKeyboardWindow.setOutsideTouchable(true);  
  136.             mKeyboardWindow.setOnDismissListener(new OnDismissListener() {  
  137.   
  138.                 @Override  
  139.                 public void onDismiss() {  
  140.                     // TODO Auto-generated method stub  
  141.                     if (scrolldis > 0) {  
  142.                         int temp = scrolldis;  
  143.                         scrolldis = 0;  
  144.                         if (null != mContentView) {  
  145.                             <span style="font-size:24px;color:#ff0000;"><strong>mContentView.scrollBy(0, -temp);//使布局整体向上顶的关键代码,使用布局的scrollBy重新滚动位置。</strong></span>  
  146.                         }  
  147.                     }  
  148.                 }  
  149.             });  
  150.         } else {  
  151.             needcustomkeyboard = false;  
  152.         }  
  153.   
  154.         a.recycle();  
  155.   
  156.     }  
  157.         //显示键盘,  
  158.     private void showKeyboard() {  
  159.         if (null != mKeyboardWindow) {  
  160.             if (!mKeyboardWindow.isShowing()) {  
  161.                 if (randomkeys) {  
  162.                     randomdigkey(mKeyboard);  
  163.                 }  
  164.   
  165.                 mKeyboardView.setKeyboard(mKeyboard);  
  166.   
  167.                 mKeyboardWindow.showAtLocation(this.mDecorView, Gravity.BOTTOM,  
  168.                         00);  
  169.                 mKeyboardWindow.update();  
  170.   
  171.                 if (null != mDecorView && null != mContentView) {  
  172.                     int[] pos = new int[2];  
  173.                     // 计算弹出的键盘的尺寸  
  174.                     getLocationOnScreen(pos);  
  175.                     float height = dpToPx(getContext(), 240);  
  176.   
  177.                     // int []hsmlpos=new int[2];  
  178.                     // mDecorView.getLocationOnScreen(hsmlpos);  
  179.   
  180.                     Rect outRect = new Rect();  
  181.                     // 然后该View有个getWindowVisibleDisplayFrame()方法可以获取到程序显示的区域,  
  182.                     // * 包括标题栏,但不包括状态栏。  
  183.                     mDecorView.getWindowVisibleDisplayFrame(outRect);// 获得view空间,也就是除掉标题栏  
  184.                     // outRect.top表示状态栏(通知栏)  
  185.                     int screen = real_scontenth;  
  186.                     scrolldis = (int) ((pos[1] + getMeasuredHeight() - outRect.top) - (screen - height));  
  187.   
  188.                     if (scrolldis > 0) {  
  189.                         mContentView.scrollBy(0, scrolldis);  
  190.                     }  
  191.                 }  
  192.   
  193.             }  
  194.         }  
  195.     }  
  196.         //隐藏键盘  
  197.     private void hideKeyboard() {  
  198.         if (null != mKeyboardWindow) {  
  199.             if (mKeyboardWindow.isShowing()) {  
  200.                 mKeyboardWindow.dismiss();  
  201.             }  
  202.         }  
  203.     }  
  204.         //隐藏系统的软键盘  
  205.     private void hideSysInput() {  
  206.         if (this.getWindowToken() != null) {  
  207.             InputMethodManager imm = (InputMethodManager) getContext()  
  208.                     .getSystemService(Context.INPUT_METHOD_SERVICE);  
  209.             imm.hideSoftInputFromWindow(this.getWindowToken(),  
  210.                     InputMethodManager.HIDE_NOT_ALWAYS);  
  211.         }  
  212.     }  
  213.        //edittext点击的监听事件,当点击了edittext则弹出键盘  
  214.     @Override  
  215.     public boolean onTouchEvent(MotionEvent event) {  
  216.         super.onTouchEvent(event);  
  217.         requestFocus();  
  218.         requestFocusFromTouch();  
  219.   
  220.         if (needcustomkeyboard) {  
  221.             hideSysInput();  
  222.             showKeyboard();  
  223.         }  
  224.   
  225.         return true;  
  226.     }  
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1.       //当点击手机的返回键,则隐藏键盘  
  2. @Override  
  3. public boolean onKeyDown(int keyCode, KeyEvent event) {  
  4.     if (keyCode == KeyEvent.KEYCODE_BACK) {  
  5.         if (null != mKeyboardWindow) {  
  6.             if (mKeyboardWindow.isShowing()) {  
  7.                 mKeyboardWindow.dismiss();  
  8.                 return true;  
  9.             }  
  10.         }  
  11.     }  
  12.   
  13.     return super.onKeyDown(keyCode, event);  
  14.   
  15. }  
  16.   
  17. @Override  
  18. public void onAttachedToWindow() {  
  19.     super.onAttachedToWindow();  
  20.   
  21.     this.mWindow = ((Activity) getContext()).getWindow();  
  22.     this.mDecorView = this.mWindow.getDecorView();  
  23.     this.mContentView = this.mWindow  
  24.             .findViewById(Window.ID_ANDROID_CONTENT);  
  25.   
  26.     hideSysInput();  
  27. }  
  28.   
  29. @Override  
  30. public void onDetachedFromWindow() {  
  31.     super.onDetachedFromWindow();  
  32.   
  33.     hideKeyboard();  
  34.   
  35.     mKeyboardWindow = null;  
  36.     mKeyboardView = null;  
  37.     mKeyboard = null;  
  38.   
  39.     mDecorView = null;  
  40.     mContentView = null;  
  41.     mWindow = null;  
  42. }  
  43.   
  44. @Override  
  45. public void onPress(int primaryCode) {  
  46.     // TODO Auto-generated method stub  
  47.   
  48. }  
  49.   
  50. @Override  
  51. public void onRelease(int primaryCode) {  
  52.     // TODO Auto-generated method stub  
  53.   
  54. }  
  55.        <span style="font-size:18px;color:#ff0000;"><strong>//自定义键盘每个按键的监听方法,必须实现,实现大小写切换、字母键盘和标点符号键盘之间的切换功能  
  56. @Override  
  57. public void onKey(int primaryCode, int[] keyCodes) {  
  58.     // TODO Auto-generated method stub  
  59.     Editable editable = this.getText();  
  60.     int start = this.getSelectionStart();  
  61.     if (primaryCode == Keyboard.KEYCODE_CANCEL) {// 隐藏键盘  
  62.         hideKeyboard();  
  63.     } else if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退  
  64.         if (editable != null && editable.length() > 0) {  
  65.             if (start > 0) {  
  66.                 editable.delete(start - 1, start);  
  67.             }  
  68.         }  
  69.     } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {// 大小写切换  
  70.         changeKey();  
  71.         mKeyboardView.setKeyboard(k1);  
  72.   
  73.     }  
  74.   
  75.     else if (primaryCode == Keyboard.KEYCODE_DONE) {// 标点符号键盘切换  
  76.         if (isnun) {  
  77.             isnun = false;  
  78.             mKeyboardView.setKeyboard(k1);  
  79.         } else {  
  80.             isnun = true;  
  81.             mKeyboardView.setKeyboard(k2);  
  82.         }  
  83.     }  
  84.   
  85.     else if (primaryCode == -110) {  
  86.         editable.insert(start, "00");  
  87.     } else if (primaryCode == -20000) {  
  88.         editable.insert(start, "200,000");  
  89.     } else if (primaryCode == -50000) {  
  90.         editable.insert(start, "5,000,000");  
  91.     } else if (primaryCode == -10000) {  
  92.         editable.insert(start, "10,000,000");  
  93.     } else if (0x0 <= primaryCode && primaryCode <= 0x7f) {  
  94.         // 可以直接输入的字符(如0-9,.),他们在键盘映射xml中的keycode值必须配置为该字符的ASCII码  
  95.         editable.insert(start, Character.toString((char) primaryCode));  
  96.     } else if (primaryCode > 0x7f) {  
  97.         Key mkey = getKeyByKeyCode(primaryCode);  
  98.         // 可以直接输入的字符(如0-9,.),他们在键盘映射xml中的keycode值必须配置为该字符的ASCII码  
  99.         editable.insert(start, mkey.label);  
  100.   
  101.     } else {  
  102.         // 其他一些暂未开放的键指令,如next到下一个输入框等指令  
  103.     }  
  104. }  
  105. lt;/strong></span>  
  106. /** 
  107.  * 键盘大小写切换 
  108.  */  
  109. private void changeKey() {  
  110.     List<Key> keylist = k1.getKeys();  
  111.     if (isupper) {// 大写切换小写  
  112.         isupper = false;  
  113.         for (Key key : keylist) {  
  114.             if (key.label != null && isword(key.label.toString())) {  
  115.                 key.label = key.label.toString().toLowerCase();  
  116.                 key.codes[0] = key.codes[0] + 32;  
  117.             }  
  118.         }  
  119.     } else {// 小写切换大写  
  120.         isupper = true;  
  121.         for (Key key : keylist) {  
  122.             if (key.label != null && isword(key.label.toString())) {  
  123.                 key.label = key.label.toString().toUpperCase();  
  124.                 key.codes[0] = key.codes[0] - 32;  
  125.             }  
  126.         }  
  127.     }  
  128. }  
  129.        //判断是否为字母  
  130. private boolean isword(String str) {  
  131.     String wordstr = "abcdefghijklmnopqrstuvwxyz";  
  132.     if (wordstr.indexOf(str.toLowerCase()) > -1) {  
  133.         return true;  
  134.     }  
  135.     return false;  
  136. }  
  137.   
  138. private Key getKeyByKeyCode(int keyCode) {  
  139.     if (null != mKeyboard) {  
  140.         List<Key> mKeys = mKeyboard.getKeys();  
  141.         for (int i = 0, size = mKeys.size(); i < size; i++) {  
  142.             Key mKey = mKeys.get(i);  
  143.   
  144.             int codes[] = mKey.codes;  
  145.   
  146.             if (codes[0] == keyCode) {  
  147.                 return mKey;  
  148.             }  
  149.         }  
  150.     }  
  151.   
  152.     return null;  
  153. }  
  154.   
  155. private void initAttributes(Context context) {  
  156.   
  157.     k1 = new Keyboard(context, R.xml.qwerty);  
  158.     k2 = new Keyboard(context, R.xml.qwerty2);  
  159.   
  160.     initScreenParams(context);  
  161.     this.setLongClickable(false);  
  162.     this.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);  
  163.     removeCopyAbility();  
  164.   
  165.     if (this.getText() != null) {  
  166.         this.setSelection(this.getText().length());  
  167.     }  
  168.   
  169.     this.setOnFocusChangeListener(new OnFocusChangeListener() {  
  170.   
  171.         @Override  
  172.         public void onFocusChange(View v, boolean hasFocus) {  
  173.             // TODO Auto-generated method stub  
  174.             if (!hasFocus) {  
  175.                 hideKeyboard();  
  176.             }  
  177.         }  
  178.     });  
  179.   
  180. }  
  181.   
  182. @TargetApi(11)  
  183. private void removeCopyAbility() {  
  184.     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {  
  185.         this.setCustomSelectionActionModeCallback(new ActionMode.Callback() {  
  186.   
  187.             @Override  
  188.             public boolean onCreateActionMode(ActionMode mode, Menu menu) {  
  189.                 return false;  
  190.             }  
  191.   
  192.             @Override  
  193.             public boolean onPrepareActionMode(ActionMode mode, Menu menu) {  
  194.                 return false;  
  195.             }  
  196.   
  197.             @Override  
  198.             public void onDestroyActionMode(ActionMode mode) {  
  199.   
  200.             }  
  201.   
  202.             @Override  
  203.             public boolean onActionItemClicked(ActionMode mode,  
  204.                     MenuItem item) {  
  205.                 return false;  
  206.             }  
  207.         });  
  208.     }  
  209. }  
  210.   
  211. private boolean isNumber(String str) {  
  212.     String wordstr = "0123456789";  
  213.     if (wordstr.indexOf(str) > -1) {  
  214.         return true;  
  215.     }  
  216.     return false;  
  217. }  
  218.        // 暂时未使用到,为了实现随机键盘布局  
  219. private void randomdigkey(Keyboard mKeyboard) {  
  220.     if (mKeyboard == null) {  
  221.         return;  
  222.     }  
  223.   
  224.     List<Key> keyList = mKeyboard.getKeys();  
  225.   
  226.     // 查找出0-9的数字键  
  227.     List<Key> newkeyList = new ArrayList<Key>();  
  228.     for (int i = 0, size = keyList.size(); i < size; i++) {  
  229.         Key key = keyList.get(i);  
  230.         CharSequence label = key.label;  
  231.         if (label != null && isNumber(label.toString())) {  
  232.             newkeyList.add(key);  
  233.         }  
  234.     }  
  235.   
  236.     int count = newkeyList.size();  
  237.   
  238.     List<KeyModel> resultList = new ArrayList<KeyModel>();  
  239.   
  240.     LinkedList<KeyModel> temp = new LinkedList<KeyModel>();  
  241.   
  242.     for (int i = 0; i < count; i++) {  
  243.         temp.add(new KeyModel(48 + i, i + ""));  
  244.     }  
  245.   
  246.     Random rand = new SecureRandom();  
  247.     rand.setSeed(SystemClock.currentThreadTimeMillis());  
  248.   
  249.     for (int i = 0; i < count; i++) {  
  250.         int num = rand.nextInt(count - i);  
  251.         KeyModel model = temp.get(num);  
  252.         resultList.add(new KeyModel(model.getCode(), model.getLable()));  
  253.         temp.remove(num);  
  254.     }  
  255.   
  256.     for (int i = 0, size = newkeyList.size(); i < size; i++) {  
  257.         Key newKey = newkeyList.get(i);  
  258.         KeyModel resultmodle = resultList.get(i);  
  259.         newKey.label = resultmodle.getLable();  
  260.         newKey.codes[0] = resultmodle.getCode();  
  261.     }  
  262.   
  263. }  
  264.   
  265. class KeyModel {  
  266.   
  267.     private Integer code;  
  268.     private String label;  
  269.   
  270.     public KeyModel(Integer code, String lable) {  
  271.         this.code = code;  
  272.         this.label = lable;  
  273.     }  
  274.   
  275.     public Integer getCode() {  
  276.         return code;  
  277.     }  
  278.   
  279.     public void setCode(Integer code) {  
  280.         this.code = code;  
  281.     }  
  282.   
  283.     public String getLable() {  
  284.         return label;  
  285.     }  
  286.   
  287.     public void setLabel(String lable) {  
  288.         this.label = lable;  
  289.     }  
  290.   
  291. }  
  292.   
  293. /** 
  294.  * 密度转换为像素值 
  295.  *  
  296.  * @param dp 
  297.  * @return 
  298.  */  
  299. public static int dpToPx(Context context, float dp) {  
  300.     final float scale = context.getResources().getDisplayMetrics().density;  
  301.     return (int) (dp * scale + 0.5f);  
  302. }  
  303.   
  304. private void initScreenParams(Context context) {  
  305.     DisplayMetrics dMetrics = new DisplayMetrics();  
  306.     WindowManager windowManager = (WindowManager) context  
  307.             .getSystemService(Context.WINDOW_SERVICE);  
  308.     Display display = windowManager.getDefaultDisplay();  
  309.     display.getMetrics(dMetrics);  
  310.   
  311.     screenw = dMetrics.widthPixels;  
  312.     screenh = dMetrics.heightPixels;  
  313.     density = dMetrics.density;  
  314.     densityDpi = dMetrics.densityDpi;  
  315.   
  316.     screenh_nonavbar = screenh;  
  317.   
  318.     int ver = Build.VERSION.SDK_INT;  
  319.   
  320.     // 新版本的android 系统有导航栏,造成无法正确获取高度  
  321.     if (ver == 13) {  
  322.         try {  
  323.             Method mt = display.getClass().getMethod("getRealHeight");  
  324.             screenh_nonavbar = (Integer) mt.invoke(display);  
  325.         } catch (Exception e) {  
  326.         }  
  327.     } else if (ver > 13) {  
  328.         try {  
  329.             Method mt = display.getClass().getMethod("getRawHeight");  
  330.             screenh_nonavbar = (Integer) mt.invoke(display);  
  331.         } catch (Exception e) {  
  332.         }  
  333.     }  
  334.   
  335.     real_scontenth = screenh_nonavbar - getStatusBarHeight(context);  
  336.   
  337. }  
  338.   
  339. /** 
  340.  * 电量栏高度 
  341.  *  
  342.  * @return 
  343.  */  
  344. public static int getStatusBarHeight(Context context) {  
  345.     Class<?> c = null;  
  346.     Object obj = null;  
  347.     Field field = null;  
  348.     int x = 0, sbar = 0;  
  349.     try {  
  350.         c = Class.forName("com.android.internal.R$dimen");  
  351.         obj = c.newInstance();  
  352.         field = c.getField("status_bar_height");  
  353.         x = Integer.parseInt(field.get(obj).toString());  
  354.         sbar = context.getResources().getDimensionPixelSize(x);  
  355.     } catch (Exception e1) {  
  356.         e1.printStackTrace();  
  357.     }  
  358.   
  359.     return sbar;  
  360. }  

          以上的文件已经解释的相当详细了,要完整的代码请转移到至此: 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————————————

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package client.verbank.mtp.allone.util;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Method;  
  5. import java.security.SecureRandom;  
  6. import java.util.ArrayList;  
  7. import java.util.LinkedList;  
  8. import java.util.List;  
  9. import java.util.Random;  
  10.   
  11. import android.annotation.TargetApi;  
  12. import android.app.Activity;  
  13. import android.content.Context;  
  14. import android.content.res.TypedArray;  
  15. import android.graphics.Rect;  
  16. import android.inputmethodservice.Keyboard;  
  17. import android.inputmethodservice.Keyboard.Key;  
  18. import android.inputmethodservice.KeyboardView;  
  19. import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;  
  20. import android.os.Build;  
  21. import android.os.SystemClock;  
  22. import android.text.Editable;  
  23. import android.util.AttributeSet;  
  24. import android.util.DisplayMetrics;  
  25. import android.view.ActionMode;  
  26. import android.view.Display;  
  27. import android.view.Gravity;  
  28. import android.view.KeyEvent;  
  29. import android.view.LayoutInflater;  
  30. import android.view.Menu;  
  31. import android.view.MenuItem;  
  32. import android.view.MotionEvent;  
  33. import android.view.View;  
  34. import android.view.ViewGroup;  
  35. import android.view.Window;  
  36. import android.view.WindowManager;  
  37. import android.view.inputmethod.EditorInfo;  
  38. import android.view.inputmethod.InputMethodManager;  
  39. import android.widget.EditText;  
  40. import android.widget.PopupWindow;  
  41. import android.widget.PopupWindow.OnDismissListener;  
  42. import client.verbank.mtp.allone.R;  
  43. import client.verbank.mtp.allone.consts.ISystemCommData;  
  44.   
  45. /** 
  46.  * 数字键盘(修改bug,金額輸入 .36 應該自動變成 0.36) 
  47.  *  
  48.  * @Project: FEIB_AndroidStation  
  49.  * @Title: MyKeyboardDigital.java  
  50.  * @Package client.verbank.mtp.allone.util  
  51.  * @Description: TODO  
  52.  * @author qiulinhe qiu.linhe@allone.cn  
  53.  * @date 2015年10月14日 上午11:04:48  
  54.  * @Copyright: 2015 www.allone.cn Inc. All rights reserved.  
  55.  * @version V3.0.0    
  56.  */  
  57. public class MyKeyboardDigital extends EditText implements  
  58.         OnKeyboardActionListener, ISystemCommData {  
  59.   
  60.     private Keyboard k1;// 字母键盘  
  61.     private Keyboard k2;// 标点符号键盘  
  62.     private Keyboard k3;// 数字键盘  
  63.     public boolean isnun = false;// 是否标点符号键盘  
  64.     public boolean isupper = false;// 是否大写  
  65.   
  66.     private KeyboardView mKeyboardView;  
  67.     private Keyboard mKeyboard;  
  68.   
  69.     private Window mWindow;  
  70.     private View mDecorView;  
  71.     private View mContentView;  
  72.   
  73.     private PopupWindow mKeyboardWindow;  
  74.   
  75.     private boolean needcustomkeyboard = true// 是否启用自定义键盘  
  76.     private boolean randomkeys = false// 数字按键是否随机  
  77.   
  78.     private int scrolldis = 450// 输入框在键盘被弹出时,要被推上去的距离  
  79.   
  80.     public static int screenw = -1;// 未知宽高  
  81.     public static int screenh = -1;  
  82.     public static int screenh_nonavbar = -1// 不包含导航栏的高度  
  83.     public static int real_scontenth = -1// 实际内容高度, 计算公式:屏幕高度-导航栏高度-电量栏高度  
  84.   
  85.     public static float density = 1.0f;  
  86.     public static int densityDpi = 160;  
  87.   
  88.     // 接收用户在系统设定界面的自定义金额  
  89.     String selfdig20 = "200,000";  
  90.     String orgindi20 = "200,000";  
  91.     // 接收用户在系统设定界面的自定义金额  
  92.     String selfdig50 = "500,000";  
  93.     String orgindi50 = "500,000";  
  94.     // 接收用户在系统设定界面的自定义金额  
  95.     String selfdig100 = "10,000,000";  
  96.     String orgindi100 = "10,000,000";  
  97.   
  98.     /** 
  99.      * @param context 
  100.      *  
  101.      * @param attrs 
  102.      */  
  103.     public MyKeyboardDigital(Context context, AttributeSet attrs) {  
  104.         super(context, attrs);  
  105.         initAttributes(context);  
  106.         initKeyboard(context, attrs);  
  107.   
  108.         // TODO Auto-generated constructor stub  
  109.     }  
  110.   
  111.     /** 
  112.      * @param context 
  113.      * @param attrs 
  114.      * @param defStyle 
  115.      */  
  116.     public MyKeyboardDigital(Context context, AttributeSet attrs, int defStyle) {  
  117.         super(context, attrs, defStyle);  
  118.   
  119.         selfdig20 = SharepreferencesUtilSystemSettings.getValue(getContext(),  
  120.                 System_key_SelfAmout2, "200,000");  
  121.         selfdig50 = SharepreferencesUtilSystemSettings.getValue(getContext(),  
  122.                 System_key_SelfAmout5, "500,000");  
  123.         selfdig100 = SharepreferencesUtilSystemSettings.getValue(getContext(),  
  124.                 System_key_SelfAmout10, "10,000,000");  
  125.         initAttributes(context);  
  126.         initKeyboard(context, attrs);  
  127.         // TODO Auto-generated constructor stub  
  128.     }  
  129.   
  130.     private void initKeyboard(Context context, AttributeSet attrs) {  
  131.         selfdig20 = SharepreferencesUtilSystemSettings.getValue(getContext(),  
  132.                 System_key_SelfAmout2, "200,000");  
  133.         selfdig50 = SharepreferencesUtilSystemSettings.getValue(getContext(),  
  134.                 System_key_SelfAmout5, "500,000");  
  135.         selfdig100 = SharepreferencesUtilSystemSettings.getValue(getContext(),  
  136.                 System_key_SelfAmout10, "10,000,000");  
  137.         TypedArray a = context.obtainStyledAttributes(attrs,  
  138.                 R.styleable.keyboard);  
  139.   
  140.         if (a.hasValue(R.styleable.keyboard_xml)) {  
  141.             needcustomkeyboard = true;  
  142.   
  143.             int xmlid = a.getResourceId(R.styleable.keyboard_xml, 0);  
  144.   
  145.             mKeyboard = new Keyboard(context, xmlid);  
  146.   
  147.             mKeyboardView = (KeyboardView) LayoutInflater.from(context)  
  148.                     .inflate(R.layout.mykeyboardviewdigit, null);  
  149.             if (a.hasValue(R.styleable.keyboard_randomkeys)) {  
  150.                 boolean random = a.getBoolean(R.styleable.keyboard_randomkeys,  
  151.                         false);  
  152.                 randomkeys = random;  
  153.   
  154.                 if (random) {  
  155.                     randomdigkey(mKeyboard);  
  156.                 }  
  157.             }  
  158.             selfdig20 = SharepreferencesUtilSystemSettings.getValue(  
  159.                     getContext(), System_key_SelfAmout2, "200,000");  
  160.             selfdig50 = SharepreferencesUtilSystemSettings.getValue(  
  161.                     getContext(), System_key_SelfAmout5, "500,000");  
  162.             selfdig100 = SharepreferencesUtilSystemSettings.getValue(  
  163.                     getContext(), System_key_SelfAmout10, "10,000,000");  
  164.             selfdigkey();  
  165.             // mKeyboardView.setKeyboard(mKeyboard);  
  166.             mKeyboardView.setEnabled(true);  
  167.             mKeyboardView.setPreviewEnabled(false);  
  168.             mKeyboardView.setOnKeyboardActionListener(this);  
  169.   
  170.             mKeyboardWindow = new PopupWindow(mKeyboardView,  
  171.                     ViewGroup.LayoutParams.MATCH_PARENT,  
  172.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
  173.             mKeyboardWindow.setAnimationStyle(R.style.AnimationFade);  
  174.             // mKeyboardWindow.setBackgroundDrawable(new BitmapDrawable());  
  175.             // mKeyboardWindow.setOutsideTouchable(true);  
  176.             mKeyboardWindow.setOnDismissListener(new OnDismissListener() {  
  177.   
  178.                 @Override  
  179.                 public void onDismiss() {  
  180.                     // TODO Auto-generated method stub  
  181.                     if (scrolldis > 0) {  
  182.                         int temp = scrolldis;  
  183.                         // scrolldis = 0;  
  184.                         if (null != mContentView) {  
  185.                             mContentView.scrollBy(0, -temp);  
  186.                         }  
  187.                     }  
  188.                 }  
  189.             });  
  190.         } else {  
  191.             needcustomkeyboard = false;  
  192.         }  
  193.   
  194.         a.recycle();  
  195.   
  196.     }  
  197.   
  198.     private void showKeyboard() {  
  199.         if (null != mKeyboardWindow) {  
  200.             if (!mKeyboardWindow.isShowing()) {  
  201.                 if (randomkeys) {  
  202.                     randomdigkey(mKeyboard);  
  203.                 }  
  204.   
  205.                 selfdig20 = SharepreferencesUtilSystemSettings.getValue(  
  206.                         getContext(), System_key_SelfAmout2, "200,000");  
  207.                 selfdig50 = SharepreferencesUtilSystemSettings.getValue(  
  208.                         getContext(), System_key_SelfAmout5, "500,000");  
  209.                 selfdig100 = SharepreferencesUtilSystemSettings.getValue(  
  210.                         getContext(), System_key_SelfAmout10, "10,000,000");  
  211.                 selfdigkey();  
  212.                 // mKeyboardView.setKeyboard(mKeyboard);  
  213.   
  214.                 mKeyboardWindow.setAnimationStyle(R.style.AnimBottom);  
  215.                 mKeyboardWindow.showAtLocation(this.mDecorView, Gravity.RIGHT  
  216.                         | Gravity.BOTTOM, 00);  
  217.                 mKeyboardWindow.update();  
  218.   
  219.                 if (null != mDecorView && null != mContentView) {  
  220.                     int[] pos = new int[2];  
  221.                     // 计算弹出的键盘的尺寸  
  222.                     getLocationOnScreen(pos);  
  223.                     float height = dpToPx(getContext(), 240);  
  224.   
  225.                     // int []hsmlpos=new int[2];  
  226.                     // mDecorView.getLocationOnScreen(hsmlpos);  
  227.   
  228.                     Rect outRect = new Rect();  
  229.                     // 然后该View有个getWindowVisibleDisplayFrame()方法可以获取到程序显示的区域,  
  230.                     // * 包括标题栏,但不包括状态栏。  
  231.                     mDecorView.getWindowVisibleDisplayFrame(outRect);// 获得view空间,也就是除掉标题栏  
  232.                     // outRect.top表示状态栏(通知栏)  
  233.                     int screen = real_scontenth;  
  234.                     // scrolldis = (int) ((pos[1] + getMeasuredHeight() -  
  235.                     // outRect.top)  
  236.                     // - (screen - height) + 500);  
  237.   
  238.                     if (scrolldis > 0) {  
  239.                         mContentView.scrollBy(0, scrolldis);  
  240.                     }  
  241.                 }  
  242.   
  243.             }  
  244.         }  
  245.     }  
  246.   
  247.     private void hideKeyboard() {  
  248.         if (null != mKeyboardWindow) {  
  249.             if (mKeyboardWindow.isShowing()) {  
  250.                 mKeyboardWindow.dismiss();  
  251.             }  
  252.         }  
  253.     }  
  254.   
  255.     private void hideSysInput() {  
  256.         if (this.getWindowToken() != null) {  
  257.             InputMethodManager imm = (InputMethodManager) getContext()  
  258.                     .getSystemService(Context.INPUT_METHOD_SERVICE);  
  259.             imm.hideSoftInputFromWindow(this.getWindowToken(), 0);  
  260.         }  
  261.     }  
  262.   
  263.     @Override  
  264.     public boolean onTouchEvent(MotionEvent event) {  
  265.         super.onTouchEvent(event);  
  266.         requestFocus();  
  267.         requestFocusFromTouch();  
  268.   
  269.         if (needcustomkeyboard) {  
  270.             hideSysInput();  
  271.             showKeyboard();  
  272.         }  
  273.   
  274.         return true;  
  275.     }  
  276.   
  277.     @Override  
  278.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  279.         if (keyCode == KeyEvent.KEYCODE_BACK) {  
  280.             if (null != mKeyboardWindow) {  
  281.                 if (mKeyboardWindow.isShowing()) {  
  282.                     mKeyboardWindow.dismiss();  
  283.                     return true;  
  284.                 }  
  285.             }  
  286.         }  
  287.   
  288.         return super.onKeyDown(keyCode, event);  
  289.   
  290.     }  
  291.   
  292.     @Override  
  293.     public void onAttachedToWindow() {  
  294.         super.onAttachedToWindow();  
  295.   
  296.         this.mWindow = ((Activity) getContext()).getWindow();  
  297.         this.mDecorView = this.mWindow.getDecorView();  
  298.         this.mContentView = this.mWindow  
  299.                 .findViewById(Window.ID_ANDROID_CONTENT);  
  300.   
  301.         hideSysInput();  
  302.     }  
  303.   
  304.     @Override  
  305.     public void onDetachedFromWindow() {  
  306.         super.onDetachedFromWindow();  
  307.   
  308.         hideKeyboard();  
  309.   
  310.         mKeyboardWindow = null;  
  311.         mKeyboardView = null;  
  312.         mKeyboard = null;  
  313.   
  314.         mDecorView = null;  
  315.         mContentView = null;  
  316.         mWindow = null;  
  317.     }  
  318.   
  319.     @Override  
  320.     public void onPress(int primaryCode) {  
  321.         // TODO Auto-generated method stub  
  322.   
  323.     }  
  324.   
  325.     @Override  
  326.     public void onRelease(int primaryCode) {  
  327.         // TODO Auto-generated method stub  
  328.   
  329.     }  
  330.   
  331.     @Override  
  332.     public void onKey(int primaryCode, int[] keyCodes) {  
  333.         // TODO Auto-generated method stub  
  334.         Editable editable = this.getText();  
  335.         int start = this.getSelectionStart();  
  336.         if (primaryCode == Keyboard.KEYCODE_CANCEL) {// 隐藏键盘  
  337.             hideKeyboard();  
  338.         } else if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退  
  339.             if (editable != null && editable.length() > 0) {  
  340.                 if (start > 0) {  
  341.                     editable.delete(start - 1, start);  
  342.                 }  
  343.             }  
  344.         } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {// 大小写切换  
  345.             changeKey();  
  346.             mKeyboardView.setKeyboard(k1);  
  347.   
  348.         }  
  349.   
  350.         else if (primaryCode == Keyboard.KEYCODE_DONE) {// 标点符号键盘切换  
  351.             if (isnun) {  
  352.                 isnun = false;  
  353.                 mKeyboardView.setKeyboard(k1);  
  354.             } else {  
  355.                 isnun = true;  
  356.                 mKeyboardView.setKeyboard(k2);  
  357.             }  
  358.         } else if (primaryCode == 46) {  
  359.   
  360.             // 当用户输入.3的时候自动转换为0.3  
  361.             if (editable != null && editable.length() > 0) {  
  362.                 if (start > 0) {  
  363.                     editable.insert(start, ".");  
  364.                 }  
  365.             } else {  
  366.                 editable.insert(start, "0.");  
  367.             }  
  368.   
  369.         }  
  370.   
  371.         else if (primaryCode == -110) {  
  372.             editable.insert(start, "00");  
  373.         } else if (primaryCode == -20000) {  
  374.             editable.insert(start, selfdig20);  
  375.         } else if (primaryCode == -50000) {  
  376.             editable.insert(start, selfdig50);  
  377.         } else if (primaryCode == -10000) {  
  378.             editable.insert(start, selfdig100);  
  379.         } else if (0x0 <= primaryCode && primaryCode <= 0x7f) {  
  380.             // 可以直接输入的字符(如0-9,.),他们在键盘映射xml中的keycode值必须配置为该字符的ASCII码  
  381.             editable.insert(start, Character.toString((char) primaryCode));  
  382.         } else if (primaryCode > 0x7f) {  
  383.             Key mkey = getKeyByKeyCode(primaryCode);  
  384.             // 可以直接输入的字符(如0-9,.),他们在键盘映射xml中的keycode值必须配置为该字符的ASCII码  
  385.             editable.insert(start, mkey.label);  
  386.   
  387.         } else {  
  388.             // 其他一些暂未开放的键指令,如next到下一个输入框等指令  
  389.         }  
  390.     }  
  391.   
  392.     // 数字键盘测试是否改变200,000和500,000让用户自定义  
  393.   
  394.     private void selfdigkey() {  
  395.         if (mKeyboard == null) {  
  396.             return;  
  397.         }  
  398.   
  399.         List<Key> keyList = k3.getKeys();  
  400.   
  401.         // 查找出0-9的数字键  
  402.         for (int i = 0, size = keyList.size(); i < size; i++) {  
  403.             Key key = keyList.get(i);  
  404.   
  405.             CharSequence label = key.label;  
  406.             // if (label != null && label.toString().equals(orgindi20)) {  
  407.             // keyList.get(i).label = selfdig;  
  408.             // orgindi20 = selfdig;  
  409.             // }  
  410.   
  411.             if (label != null && label.toString().equals(orgindi20)) {  
  412.                 keyList.get(i).label = selfdig20;  
  413.                 keyList.get(i).codes[0] = -20000;  
  414.                 orgindi20 = selfdig20;  
  415.             }  
  416.             if (label != null && label.toString().equals(orgindi50)) {  
  417.                 keyList.get(i).label = selfdig50;  
  418.                 keyList.get(i).codes[0] = -50000;  
  419.                 orgindi50 = selfdig50;  
  420.             }  
  421.             if (label != null && label.toString().equals(orgindi100)) {  
  422.                 keyList.get(i).label = selfdig100;  
  423.                 keyList.get(i).codes[0] = -10000;  
  424.                 orgindi100 = selfdig100;  
  425.             }  
  426.         }  
  427.   
  428.         mKeyboardView.setKeyboard(k3);  
  429.     }  
  430.   
  431.     /** 
  432.      * 键盘大小写切换 
  433.      */  
  434.     private void changeKey() {  
  435.         List<Key> keylist = k1.getKeys();  
  436.         if (isupper) {// 大写切换小写  
  437.             isupper = false;  
  438.             for (Key key : keylist) {  
  439.                 if (key.label != null && isword(key.label.toString())) {  
  440.                     key.label = key.label.toString().toLowerCase();  
  441.                     key.codes[0] = key.codes[0] + 32;  
  442.                 }  
  443.             }  
  444.         } else {// 小写切换大写  
  445.             isupper = true;  
  446.             for (Key key : keylist) {  
  447.                 if (key.label != null && isword(key.label.toString())) {  
  448.                     key.label = key.label.toString().toUpperCase();  
  449.                     key.codes[0] = key.codes[0] - 32;  
  450.                 }  
  451.             }  
  452.         }  
  453.     }  
  454.   
  455.     private boolean isword(String str) {  
  456.         String wordstr = "abcdefghijklmnopqrstuvwxyz";  
  457.         if (wordstr.indexOf(str.toLowerCase()) > -1) {  
  458.             return true;  
  459.         }  
  460.         return false;  
  461.     }  
  462.   
  463.     @Override  
  464.     public void onText(CharSequence text) {  
  465.         // TODO Auto-generated method stub  
  466.   
  467.     }  
  468.   
  469.     @Override  
  470.     public void swipeLeft() {  
  471.         // TODO Auto-generated method stub  
  472.   
  473.     }  
  474.   
  475.     @Override  
  476.     public void swipeRight() {  
  477.         // TODO Auto-generated method stub  
  478.   
  479.     }  
  480.   
  481.     @Override  
  482.     public void swipeDown() {  
  483.         // TODO Auto-generated method stub  
  484.   
  485.     }  
  486.   
  487.     @Override  
  488.     public void swipeUp() {  
  489.         // TODO Auto-generated method stub  
  490.   
  491.     }  
  492.   
  493.     private Key getKeyByKeyCode(int keyCode) {  
  494.         if (null != mKeyboard) {  
  495.             List<Key> mKeys = mKeyboard.getKeys();  
  496.             for (int i = 0, size = mKeys.size(); i < size; i++) {  
  497.                 Key mKey = mKeys.get(i);  
  498.   
  499.                 int codes[] = mKey.codes;  
  500.   
  501.                 if (codes[0] == keyCode) {  
  502.                     return mKey;  
  503.                 }  
  504.             }  
  505.         }  
  506.   
  507.         return null;  
  508.     }  
  509.   
  510.     private void initAttributes(Context context) {  
  511.   
  512.         k1 = new Keyboard(context, R.xml.qwerty);  
  513.         k2 = new Keyboard(context, R.xml.qwerty2);  
  514.         k3 = new Keyboard(context, R.xml.amountinputkeyboard);  
  515.   
  516.         initScreenParams(context);  
  517.         this.setLongClickable(false);  
  518.         this.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);  
  519.         removeCopyAbility();  
  520.   
  521.         if (this.getText() != null) {  
  522.             this.setSelection(this.getText().length());  
  523.         }  
  524.   
  525.         this.setOnFocusChangeListener(new OnFocusChangeListener() {  
  526.   
  527.             @Override  
  528.             public void onFocusChange(View v, boolean hasFocus) {  
  529.                 // TODO Auto-generated method stub  
  530.                 if (!hasFocus) {  
  531.                     hideKeyboard();  
  532.                 }  
  533.             }  
  534.         });  
  535.   
  536.     }  
  537.   
  538.     @TargetApi(11)  
  539.     private void removeCopyAbility() {  
  540.         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {  
  541.             this.setCustomSelectionActionModeCallback(new ActionMode.Callback() {  
  542.   
  543.                 @Override  
  544.                 public boolean onCreateActionMode(ActionMode mode, Menu menu) {  
  545.                     return false;  
  546.                 }  
  547.   
  548.                 @Override  
  549.                 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {  
  550.                     return false;  
  551.                 }  
  552.   
  553.                 @Override  
  554.                 public void onDestroyActionMode(ActionMode mode) {  
  555.   
  556.                 }  
  557.   
  558.                 @Override  
  559.                 public boolean onActionItemClicked(ActionMode mode,  
  560.                         MenuItem item) {  
  561.                     return false;  
  562.                 }  
  563.             });  
  564.         }  
  565.     }  
  566.   
  567.     private boolean isNumber(String str) {  
  568.         String wordstr = "0123456789";  
  569.         if (wordstr.indexOf(str) > -1) {  
  570.             return true;  
  571.         }  
  572.         return false;  
  573.     }  
  574.   
  575.     private void randomdigkey(Keyboard mKeyboard) {  
  576.         if (mKeyboard == null) {  
  577.             return;  
  578.         }  
  579.   
  580.         List<Key> keyList = mKeyboard.getKeys();  
  581.   
  582.         // 查找出0-9的数字键  
  583.         List<Key> newkeyList = new ArrayList<Key>();  
  584.         for (int i = 0, size = keyList.size(); i < size; i++) {  
  585.             Key key = keyList.get(i);  
  586.             CharSequence label = key.label;  
  587.             if (label != null && isNumber(label.toString())) {  
  588.                 newkeyList.add(key);  
  589.             }  
  590.         }  
  591.   
  592.         int count = newkeyList.size();  
  593.   
  594.         List<KeyModel> resultList = new ArrayList<KeyModel>();  
  595.   
  596.         LinkedList<KeyModel> temp = new LinkedList<KeyModel>();  
  597.   
  598.         for (int i = 0; i < count; i++) {  
  599.             temp.add(new KeyModel(48 + i, i + ""));  
  600.         }  
  601.   
  602.         Random rand = new SecureRandom();  
  603.         rand.setSeed(SystemClock.currentThreadTimeMillis());  
  604.   
  605.         for (int i = 0; i < count; i++) {  
  606.             int num = rand.nextInt(count - i);  
  607.             KeyModel model = temp.get(num);  
  608.             resultList.add(new KeyModel(model.getCode(), model.getLable()));  
  609.             temp.remove(num);  
  610.         }  
  611.   
  612.         for (int i = 0, size = newkeyList.size(); i < size; i++) {  
  613.             Key newKey = newkeyList.get(i);  
  614.             KeyModel resultmodle = resultList.get(i);  
  615.             newKey.label = resultmodle.getLable();  
  616.             newKey.codes[0] = resultmodle.getCode();  
  617.         }  
  618.   
  619.     }  
  620.   
  621.     class KeyModel {  
  622.   
  623.         private Integer code;  
  624.         private String label;  
  625.   
  626.         public KeyModel(Integer code, String lable) {  
  627.             this.code = code;  
  628.             this.label = lable;  
  629.         }  
  630.   
  631.         public Integer getCode() {  
  632.             return code;  
  633.         }  
  634.   
  635.         public void setCode(Integer code) {  
  636.             this.code = code;  
  637.         }  
  638.   
  639.         public String getLable() {  
  640.             return label;  
  641.         }  
  642.   
  643.         public void setLabel(String lable) {  
  644.             this.label = lable;  
  645.         }  
  646.   
  647.     }  
  648.   
  649.     /** 
  650.      * 密度转换为像素值 
  651.      *  
  652.      * @param dp 
  653.      * @return 
  654.      */  
  655.     public static int dpToPx(Context context, float dp) {  
  656.         final float scale = context.getResources().getDisplayMetrics().density;  
  657.         return (int) (dp * scale + 0.5f);  
  658.     }  
  659.   
  660.     private void initScreenParams(Context context) {  
  661.         DisplayMetrics dMetrics = new DisplayMetrics();  
  662.         WindowManager windowManager = (WindowManager) context  
  663.                 .getSystemService(Context.WINDOW_SERVICE);  
  664.         Display display = windowManager.getDefaultDisplay();  
  665.         display.getMetrics(dMetrics);  
  666.   
  667.         screenw = dMetrics.widthPixels;  
  668.         screenh = dMetrics.heightPixels;  
  669.         density = dMetrics.density;  
  670.         densityDpi = dMetrics.densityDpi;  
  671.   
  672.         screenh_nonavbar = screenh;  
  673.   
  674.         int ver = Build.VERSION.SDK_INT;  
  675.   
  676.         // 新版本的android 系统有导航栏,造成无法正确获取高度  
  677.         if (ver == 13) {  
  678.             try {  
  679.                 Method mt = display.getClass().getMethod("getRealHeight");  
  680.                 screenh_nonavbar = (Integer) mt.invoke(display);  
  681.             } catch (Exception e) {  
  682.             }  
  683.         } else if (ver > 13) {  
  684.             try {  
  685.                 Method mt = display.getClass().getMethod("getRawHeight");  
  686.                 screenh_nonavbar = (Integer) mt.invoke(display);  
  687.             } catch (Exception e) {  
  688.             }  
  689.         }  
  690.   
  691.         real_scontenth = screenh_nonavbar - getStatusBarHeight(context);  
  692.   
  693.     }  
  694.   
  695.     /** 
  696.      * 电量栏高度 
  697.      *  
  698.      * @return 
  699.      */  
  700.     public static int getStatusBarHeight(Context context) {  
  701.         Class<?> c = null;  
  702.         Object obj = null;  
  703.         Field field = null;  
  704.         int x = 0, sbar = 0;  
  705.         try {  
  706.             c = Class.forName("com.android.internal.R$dimen");  
  707.             obj = c.newInstance();  
  708.             field = c.getField("status_bar_height");  
  709.             x = Integer.parseInt(field.get(obj).toString());  
  710.             sbar = context.getResources().getDimensionPixelSize(x);  
  711.         } catch (Exception e1) {  
  712.             e1.printStackTrace();  
  713.         }  
  714.   
  715.         return sbar;  
  716.     }  
  717.   
  718. }  

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

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

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. DisplayMetrics dm = contextceshi.getResources()  
  2.                         .getDisplayMetrics();  
  3.                 int scalsize = (int) (80 * dm.density);  
  4.   
  5.                 if (scalsize > 0) {  
  6.                     int temp = scalsize;  
  7.                     // scrolldis = 0;  
  8.                     if (null != mContentView) {  
  9.                         mContentView.scrollBy(100, -temp);  
  10.                     }  
  11.                 }  


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

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

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:horizontalGap="1.2px"  
  4.     android:keyWidth="9.89%p"  
  5.     android:verticalGap="2px" >  
  6.   
  7.     <Row  
  8.         android:horizontalGap="-5px"  
  9.         android:keyHeight="28dp"  
  10.         android:verticalGap="2px" >  
  11.         <Key  
  12.             android:codes="-3"  
  13.             android:keyHeight="22dp"  
  14.             android:keyIcon="@drawable/keyboardblow"  
  15.             android:keyWidth="100%p" />  
  16.     </Row>
转自:http://blog.csdn.net/nihaoqiulinhe/article/details/48546265
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值