1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > android 自定义数字软键盘 android -自定义数目字软键盘的设计与实现(1)

android 自定义数字软键盘 android -自定义数目字软键盘的设计与实现(1)

时间:2023-06-08 17:09:02

相关推荐

android 自定义数字软键盘 android -自定义数目字软键盘的设计与实现(1)

android --自定义数字软键盘的设计与实现(1)

相信很多情况下我们看到过一些数字的输入,弹出来的并不是系统自带的键盘。这就是自定义的软键盘,软键盘的一个好处就是简单,操作方便。如何实现一个自定义的软键盘呢??其实这个过程是比较简单的,只要把几个关键的原理搞明白了,你就会发现真的很简单,很方便!看一下效果图:

这篇博客主要介绍一下实现的相关原理,下一节就会把具体实现的步骤和大家分享一下!

实现软键盘主要用到了系统的两个类Keyboard和KeyboardView:

Keyboard类源码的介绍是:Listener for virtual keyboard events.即用于监听虚拟键盘。

至于Keyboard类的映射机制,这里就不需要说了,本人感觉也没必要了解的太深,这里要介绍一些他,在接下来需要的几个重要的内容。我们看一下他的源码:

package com.android.inputmethod.keyboard;

import android.util.Log;

import android.util.SparseArray;

import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;

import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;

import com.android.inputmethod.keyboard.internal.KeyboardParams;

import com.android.inputmethod.latin.CollectionUtils;

/**

* Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard

* consists of rows of keys.

*

The layout file for a keyboard contains XML that looks like the following snippet:

*

* <Keyboard

*latin:keyWidth="%10p"

*latin:keyHeight="50px"

*latin:horizontalGap="2px"

*latin:verticalGap="2px" >

* <Row latin:keyWidth="32px" >

*<Key latin:keyLabel="A" />

*...

* </Row>

* ...

* </Keyboard>

*

*/

public class Keyboard {

private static final String TAG = Keyboard.class.getSimpleName();

/** Some common keys code. Must be positive.

* These should be aligned with values/keycodes.xml

*/

public static final int CODE_ENTER = '\n';

public static final int CODE_TAB = '\t';

public static final int CODE_SPACE = ' ';

public static final int CODE_PERIOD = '.';

public static final int CODE_DASH = '-';

public static final int CODE_SINGLE_QUOTE = '\'';

public static final int CODE_DOUBLE_QUOTE = '"';

public static final int CODE_QUESTION_MARK = '?';

public static final int CODE_EXCLAMATION_MARK = '!';

// TODO: Check how this should work for right-to-left languages. It seems to stand

// that for rtl languages, a closing parenthesis is a left parenthesis. Is this

// managed by the font? Or is it a different char?

public static final int CODE_CLOSING_PARENTHESIS = ')';

public static final int CODE_CLOSING_SQUARE_BRACKET = ']';

public static final int CODE_CLOSING_CURLY_BRACKET = '}';

public static final int CODE_CLOSING_ANGLE_BRACKET = '>';

/** Special keys code. Must be negative.

* These should be aligned with KeyboardCodesSet.ID_TO_NAME[],

* KeyboardCodesSet.DEFAULT[] and KeyboardCodesSet.RTL[]

*/

public static final int CODE_SHIFT = -1;

public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;

public static final int CODE_OUTPUT_TEXT = -3;

public static final int CODE_DELETE = -4;

public static final int CODE_SETTINGS = -5;

public static final int CODE_SHORTCUT = -6;

public static final int CODE_ACTION_ENTER = -7;

public static final int CODE_ACTION_NEXT = -8;

public static final int CODE_ACTION_PREVIOUS = -9;

public static final int CODE_LANGUAGE_SWITCH = -10;

public static final int CODE_RESEARCH = -11;

// Code value representing the code is not specified.

public static final int CODE_UNSPECIFIED = -12;

public final KeyboardId mId;

public final int mThemeId;

/** Total height of the keyboard, including the padding and keys */

public final int mOccupiedHeight;

/** Total width of the keyboard, including the padding and keys */

public final int mOccupiedWidth;

/** The padding above the keyboard */

public final int mTopPadding;

/** Default gap between rows */

public final int mVerticalGap;

/** Per keyboard key visual parameters */

public final KeyVisualAttributes mKeyVisualAttributes;

public final int mMostCommonKeyHeight;

public final int mMostCommonKeyWidth;

/** More keys keyboard template */

public final int mMoreKeysTemplate;

/** Maximum column for more keys keyboard */

public final int mMaxMoreKeysKeyboardColumn;

/** Array of keys and icons in this keyboard */

public final Key[] mKeys;

public final Key[] mShiftKeys;

public final Key[] mAltCodeKeysWhileTyping;

public final KeyboardIconsSet mIconsSet;

private final SparseArray mKeyCache = CollectionUtils.newSparseArray();

private final ProximityInfo mProximityInfo;

private final boolean mProximityCharsCorrectionEnabled;

public Keyboard(final KeyboardParams params) {

/// M: @{

ProximityInfo tmp;

/// @}

mId = params.mId;

mThemeId = params.mThemeId;

mOccupiedHeight = params.mOccupiedHeight;

mOccupiedWidth = params.mOccupiedWidth;

mMostCommonKeyHeight = params.mMostCommonKeyHeight;

mMostCommonKeyWidth = params.mMostCommonKeyWidth;

mMoreKeysTemplate = params.mMoreKeysTemplate;

mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn;

mKeyVisualAttributes = params.mKeyVisualAttributes;

mTopPadding = params.mTopPadding;

mVerticalGap = params.mVerticalGap;

mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]);

mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]);

mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray(

new Key[params.mAltCodeKeysWhileTyping.size()]);

mIconsSet = params.mIconsSet;

/// M: Modified by MTK to avoid OOME thrown to DVM on LCA

// since there is an int array sized about 32KB allocated

// within ProximityInfo constructor. @{

try {

tmp = new ProximityInfo(params.mId.mLocale.toString(),

params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,

mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);

} catch (OutOfMemoryError e) {

Log.w(TAG, "OutOfMemoryError at ProximityInfo");

/// M: It`s dangerous here, since this approach will generate

// a proximity useless, this will cause no responce on VK.

// TODO: It`s better to unbind LatinIME here or provide another

// keyboard here.

tmp = ProximityInfo.createDummyProximityInfo();

}

mProximityInfo = tmp;

/// @}

mProximityCharsCorrectionEnabled = params.mProximityCharsCorrectionEnabled;

}

public boolean hasProximityCharsCorrection(final int code) {

if (!mProximityCharsCorrectionEnabled) {

return false;

}

// Note: The native code has the main keyboard layout only at this moment.

// TODO: Figure out how to handle proximity characters information of all layouts.

final boolean canAssumeNativeHasProximityCharsInfoOfAllKeys = (

mId.mElementId == KeyboardId.ELEMENT_ALPHABET

|| mId.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED);

return canAssumeNativeHasProximityCharsInfoOfAllKeys || Character.isLetter(code);

}

public ProximityInfo getProximityInfo() {

return mProximityInfo;

}

public Key getKey(final int code) {

if (code == CODE_UNSPECIFIED) {

return null;

}

synchronized (mKeyCache) {

final int index = mKeyCache.indexOfKey(code);

if (index >= 0) {

return mKeyCache.valueAt(index);

}

for (final Key key : mKeys) {

if (key.mCode == code) {

mKeyCache.put(code, key);

return key;

}

}

mKeyCache.put(code, null);

return null;

}

}

public boolean hasKey(final Key aKey) {

if (mKeyCache.indexOfValue(aKey) >= 0) {

return true;

}

for (final Key key : mKeys) {

if (key == aKey) {

mKeyCache.put(key.mCode, key);

return true;

}

}

return false;

}

public static boolean isLetterCode(final int code) {

return code >= CODE_SPACE;

}

@Override

public String toString() {

return mId.toString();

}

/**

* Returns the array of the keys that are closest to the given point.

* @param x the x-coordinate of the point

* @param y the y-coordinate of the point

* @return the array of the nearest keys to the given point. If the given

* point is out of range, then an array of size zero is returned.

*/

public Key[] getNearestKeys(final int x, final int y) {

// Avoid dead pixels at edges of the keyboard

final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1));

final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1));

return mProximityInfo.getNearestKeys(adjustedX, adjustedY);

}

public static String printableCode(final int code) {

switch (code) {

case CODE_SHIFT: return "shift";

case CODE_SWITCH_ALPHA_SYMBOL: return "symbol";

case CODE_OUTPUT_TEXT: return "text";

case CODE_DELETE: return "delete";

case CODE_SETTINGS: return "settings";

case CODE_SHORTCUT: return "shortcut";

case CODE_ACTION_ENTER: return "actionEnter";

case CODE_ACTION_NEXT: return "actionNext";

case CODE_ACTION_PREVIOUS: return "actionPrevious";

case CODE_LANGUAGE_SWITCH: return "languageSwitch";

case CODE_UNSPECIFIED: return "unspec";

case CODE_TAB: return "tab";

case CODE_ENTER: return "enter";

default:

if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code);

if (code < CODE_SPACE) return String.format("'\\u%02x'", code);

if (code < 0x100) return String.format("'%c'", code);

return String.format("'\\u%04x'", code);

}

}

}

我们在设置每一个按键的code时,就是根据keyboard类中定义的一些属性,比如回退,删除,清空等都是固定。

知道了

public static final int CODE_SHIFT = -1;

public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;

public static final int CODE_OUTPUT_TEXT = -3;

public static final int CODE_DELETE = -4;

public static final int CODE_SETTINGS = -5;

public static final int CODE_SHORTCUT = -6;

public static final int CODE_ACTION_ENTER = -7;

public static final int CODE_ACTION_NEXT = -8;

public static final int CODE_ACTION_PREVIOUS = -9;

public static final int CODE_LANGUAGE_SWITCH = -10;

public static final int CODE_RESEARCH = -11;

// Code value representing the code is not specified.

public static final int CODE_UNSPECIFIED = -12;

我们就不会有太多的疑惑了!也是说,我们自定义的每一个按键都将会有一个codes值,比如回退我们就写成:

在监听就是:if (primaryCode == Keyboard.KEYCODE_DELETE){}.这就表示,监听回退事件了!

KeyboardView类源码的介绍是:A view that renders a virtual {@link Keyboard}. It handles rendering of keys and detecting key presses and touch movements.即它处理绘制钥匙和检测按键和触摸动作。这个类的代码比较多,我们就不贴出来,它里面有很多方法,在我们自定义的软键盘很多属性,就需要我们用这个类来设置比如:

keyboardView = (KeyboardView) act.findViewById(R.id.keyboard_view);

keyboardView.setKeyboard(k);

keyboardView.setEnabled(true);

keyboardView.setPreviewEnabled(true);

keyboardView.setVisibility(View.VISIBLE);

keyboardView.setOnKeyboardActionListener(listener);

了解一些源码,就可以是我们知道我们为什么要这样写,为什么要这样做了!

我们还需要建一个xml文件,来布局我们的视图,一般是在res文件夹中建一个名为xml的文件夹,在里面新建立一个xml布局文件。

每一个按键的属性主要包括android:codes=" " android:keyLabel=" "。activity就是根据codes的值来监听的。一些可以自定义设置,一些需要是keyboard中设置好的,要保持一致。

好了,今天就先说到这里,下次再继续说建立一个完整的项目实例的过程!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。