Android 自定義鍵盤 隨機鍵盤(完全定製,向上頂佈局,點選按鈕進行隱藏)
之前上傳的另外一個自定義鍵盤,並沒有實現鍵盤彈出的時候,佈局向上自動調整。(網路上所有的自定義鍵盤都沒有新增自適應的功能,而且佈局沒這麼好看,上一個例子資源連結為:http://download.csdn.net/detail/omayyouhappy/9111809,這個資源絕對值10分,真的全網路唯一完美的自定義定製鍵盤,新的資源在這裡:全網唯一定製鍵盤(向上改變佈局)
,接下來就仔細的講講我是如何完成自定義鍵盤的,我得吐槽一下,一開始為了做自定義鍵盤,網上的例子確實很有用,避免了重複造輪子,給了我很大的啟示,也快速的知道如何使用google提供的自定義鍵盤類使用方法,介紹幾本的鍵盤的情況,你可以到這篇博文來了解:
自定義鍵盤整個過程如下:
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 [email protected]
* @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>
相關推薦
Android 自定義鍵盤 隨機鍵盤(完全定製,向上頂佈局,點選按鈕進行隱藏)
之前上傳的另外一個自定義鍵盤,並沒有實現鍵盤彈出的時候,佈局向上自動調整。(網路上所有的自定義鍵盤都沒有新增自適應的功能,而且佈局沒這麼好看,上一個例子資源連結為:http://download.csdn.net/detail/omayyouhappy/91118
Android 自定義輸入軟鍵盤
前言 在日常開發中,有的時候我們需要使用者輸入指定範圍的內容,除了給與充分的文字提示,更加人性化的就是定製一個自定義鍵盤。 Android的自定義鍵盤常用於密碼輸入時的安全鍵盤,比如支付寶支付時。 如上圖,在輸入體溫時,彈出一個自定義的體溫鍵盤,這樣既能人性化服務,也能規避
android自定義dialog,軟體鍵盤彈出擋住輸入區域解決
在做新浪oauth2.0認證時,裡面有一個自定義dialog的類。dialog中載入的是一一個webview。當鍵盤彈起的時候就會彈住輸入區域。 解決辦法: 在dialog的oncarete方法中加 getWindow().setSoftInputMode(WindowManager.LayoutPara
Android自定義數字密碼鍵盤
妙語皆隨晨曦出 2016-11-06 00:03 1.建立密碼鍵盤佈局layout/password_keyboard_view.xml EditText的屬性: android:inputType="numberSigned" 可輸入"+" "-"符號 表示正負 andr
Android 自定義橫向進度條(可動態設定最大值)
自定義橫向進度條 主佈局檔案中包 含 <LinearLayout android:id="@+id/linearlayout" android:layout_width="match_parent" androi
Android 自定義view --圓形百分比(進度條)
注:本文由於是在學習過程中寫的,存在大量問題(overdraw onDraw new物件),請讀者們不要被誤導!!解決辦法見後面的部落格。 起因 最近公司專案有需求需要用到輕量級圖表如下
android 自定義dialog的實現(自定義大小、去除黑色邊框等)
搜尋相關關鍵字網上一大堆實現,但是看完總覺得缺胳膊少腿,繞了不少彎路,終於弄好了自定義dialog。把自己整合的完整程式碼發上來。 要點: 1、設定自定義dialog的佈局檔案my_dialog.xml 2、設定一份自定義的樣式檔案styles_wx.xml,該檔案用於覆
Android自定義view第一彈(防小米計步)
廢話不多說,先上效果圖: 右上腳的計步(有動畫效果) 從來不說廢話,上程式碼: 一.自定義View 程式碼 /** * 計步View * Created by DYJ on 2017/8/3. */ public class RunningV
Android自定義文字選中模式(全選、複製,剪下,粘帖)
為了方便操作,在PC端我們常用的Ctrl+A(全選)/Ctrl+C(複製)/Ctrl+X(剪下)/Ctrl+V(粘帖)提高了我們的辦公效率。然後在手機端怎麼實現呢?我花了一天的時間研究了一下。 首先說一下TextView的選中,要想選中TextV
簡單談談android自定義相機的實現(上 android.hardware.Camera)
通常情況下,呼叫android系統相機基本上可以滿足拍照的需求,而自定義相機的需求一般來自於開發自己的相機應用,今天我們來簡單聊聊android自定義相機的實現,限於篇幅,我們上篇只討論android.hardware.Camera,下篇我會和大家一起討論一下a
Android自定義視訊播放器(三)
一、引言 在上文中,我們通過自定義控制面板的佈局,來實現自定義的播放控制,下面來對裡面的各個元件進行事件繫結。 @Override public void onClick(View v) { if ( v == btnVoice ) {
Android 自定義View--ProgressBar篇(一)
1、概述 1.1 目的 : 在我們的日常開發中,有很多Android UI介面上有一些特殊或者特別的控制元件與介面,是Android自帶的控制元件所不能滿足的,需要我們自己定製一些適合的控制元件來完成。 1.2 Android自定義View步驟 : 自定
Android自定義視訊播放器(六)
一、引言 現在已經差不多完成了一個自定義的視訊播放器,還有一個讓視訊全屏播放的按鈕事件沒有繫結,下面會介紹。此外還要一個非常重要的功能就是,已經寫好了自定義的播放器,那麼就應該能被其他應用調起,來播放視訊,下面來完善這兩個功能。 二、全屏按鈕事件
android自定義環形統計圖(帶動畫)
一、測試截圖 二、實現原理 package com.freedomanlib; import java.util.Timer; import java.util.TimerTask; import android.annotation.SuppressLint;
Android自定義視訊播放器(一)
一、引言 我們在開發Android多媒體應用時,有兩種方式來播放多媒體資源。第一種是使用隱式的Intent,來使用系統或者手機已經安裝的第三方播放器應用來播放音視訊,第二種是使用Android自帶的、我們自定義的播放器來播放,這種主要是採用Android提供的
android自定義view之地圖(一)
最近參加了一個比賽,要用到自己做一個自定義的小地圖,所以在網上查找了一些關於自定義view的有關資料,也瞭解了自定義控制元件的初步知識。 效果圖 第一階段我畫了一個自制的網格圖,點哪個網格就會哪個網格就會顯示。 工作環境圖 程式碼介紹
Android自定義效果——隨機抽獎
那天逛android開原始碼的時候,看到一個wheel menu的自定義效果,就是類似人家的那種轉盤抽獎,把人家工程看了下,覺得很好玩,但是不想在他上面改,於是就自己想了一個類似的隨即抽
Android自定義ActionBar背景顏色(從原始碼分析)
Android自定義ActionBar背景顏色 修改前後效果圖: 在style.xml里加一行程式碼搞定 <!-- Base application theme. --> <style name="AppTheme" parent="
android 自定義倒計時控制元件(圓形倒計時顯示)
先上效果圖 - 倒計時結束 程式碼塊 attr.xml 控制元件需要用到的屬性: <?xml version="1.0" encoding="utf-8"?> <resources> <de
Android 自定義相機獲取照片(螢幕適配)
1.在應用程式中自定義相機拍照的大體步驟如下: 1.檢測和訪問相機:檢測裝置是否支援拍照,然後發出訪問裝置相機請求。 2.建立一個預覽類:建立一個繼承自類SurfaceView和實現介面SurfaceHolder介面的相機預覽類,這個類用來預覽從相機得到