- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我覆盖 View (openGL表面 View )的onKeyDown方法以捕获
所有按键。问题在于,在多个设备上,KEYCODE_DEL不是
被抓获。我尝试将onKeyListener添加到 View 中,并且捕获了除Backspace键之外的所有内容。
必须有一种方法来监听此按键事件,但是如何?
最佳答案
11/12/2014 UPDATE: Changed scope of fix to not limit to < API level 19, since at a third party keyboard still has the bug beyond 19.
1/9/2014 UPDATE: I've devised an approach, with code, to resolve all Google Keyboard (LatinIME) KEYCODE_DEL problems, specifically issues 42904 and 62306.
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.BaseInputConnection;
/**
*
* @author Carl Gunther
* There are bugs with the LatinIME keyboard's generation of KEYCODE_DEL events
* that this class addresses in various ways. These bugs appear when the app
* specifies TYPE_NULL, which is the only circumstance under which the app
* can reasonably expect to receive key events for KEYCODE_DEL.
*
* This class is intended for use by a view that overrides
* onCreateInputConnection() and specifies to the invoking IME that it wishes
* to use the TYPE_NULL InputType. This should cause key events to be returned
* to the view.
*
*/
public class InputConnectionAccomodatingLatinIMETypeNullIssues extends BaseInputConnection {
//This holds the Editable text buffer that the LatinIME mistakenly *thinks*
// that it is editing, even though the views that employ this class are
// completely driven by key events.
Editable myEditable = null;
//Basic constructor
public InputConnectionAccomodatingLatinIMETypeNullIssues(View targetView, boolean fullEditor) {
super(targetView, fullEditor);
}
//This method is called by the IME whenever the view that returned an
// instance of this class to the IME from its onCreateInputConnection()
// gains focus.
@Override
public Editable getEditable() {
//Some versions of the Google Keyboard (LatinIME) were delivered with a
// bug that causes KEYCODE_DEL to no longer be generated once the number
// of KEYCODE_DEL taps equals the number of other characters that have
// been typed. This bug was reported here as issue 62306.
//
// As of this writing (1/7/2014), it is fixed in the AOSP code, but that
// fix has not yet been released. Even when it is released, there will
// be many devices having versions of the Google Keyboard that include the bug
// in the wild for the indefinite future. Therefore, a workaround is required.
//
//This is a workaround for that bug which just jams a single garbage character
// into the internal buffer that the keyboard THINKS it is editing even
// though we have specified TYPE_NULL which *should* cause LatinIME to
// generate key events regardless of what is in that buffer. We have other
// code that attempts to ensure as the user edites that there is always
// one character remaining.
//
// The problem arises because when this unseen buffer becomes empty, the IME
// thinks that there is nothing left to delete, and therefore stops
// generating KEYCODE_DEL events, even though the app may still be very
// interested in receiving them.
//
//So, for example, if the user taps in ABCDE and then positions the
// (app-based) cursor to the left of A and taps the backspace key three
// times without any evident effect on the letters (because the app's own
// UI code knows that there are no letters to the left of the
// app-implemented cursor), and then moves the cursor to the right of the
// E and hits backspace five times, then, after E and D have been deleted,
// no more KEYCODE_DEL events will be generated by the IME because the
// unseen buffer will have become empty from five letter key taps followed
// by five backspace key taps (as the IME is unaware of the app-based cursor
// movements performed by the user).
//
// In other words, if your app is processing KEYDOWN events itself, and
// maintaining its own cursor and so on, and not telling the IME anything
// about the user's cursor position, this buggy processing of the hidden
// buffer will stop KEYCODE_DEL events when your app actually needs them -
// in whatever Android releases incorporate this LatinIME bug.
//
// By creating this garbage characters in the Editable that is initially
// returned to the IME here, we make the IME think that it still has
// something to delete, which causes it to keep generating KEYCODE_DEL
// events in response to backspace key presses.
//
// A specific keyboard version that I tested this on which HAS this
// problem but does NOT have the "KEYCODE_DEL completely gone" (issue 42904)
// problem that is addressed by the deleteSurroundingText() override below
// (the two problems are not both present in a single version) is
// 2.0.19123.914326a, tested running on a Nexus7 2012 tablet.
// There may be other versions that have issue 62306.
//
// A specific keyboard version that I tested this on which does NOT have
// this problem but DOES have the "KEYCODE_DEL completely gone" (issue
// 42904) problem that is addressed by the deleteSurroundingText()
// override below is 1.0.1800.776638, tested running on the Nexus10
// tablet. There may be other versions that also have issue 42904.
//
// The bug that this addresses was first introduced as of AOSP commit tag
// 4.4_r0.9, and the next RELEASED Android version after that was
// android-4.4_r1, which is the first release of Android 4.4. So, 4.4 will
// be the first Android version that would have included, in the original
// RELEASED version, a Google Keyboard for which this bug was present.
//
// Note that this bug was introduced exactly at the point that the OTHER bug
// (the one that is addressed in deleteSurroundingText(), below) was first
// FIXED.
//
// Despite the fact that the above are the RELEASES associated with the bug,
// the fact is that any 4.x Android release could have been upgraded by the
// user to a later version of Google Keyboard than was present when the
// release was originally installed to the device. I have checked the
// www.archive.org snapshots of the Google Keyboard listing page on the Google
// Play store, and all released updates listed there (which go back to early
// June of 2013) required Android 4.0 and up, so we can be pretty sure that
// this bug is not present in any version earlier than 4.0 (ICS), which means
// that we can limit this fix to API level 14 and up. And once the LatinIME
// problem is fixed, we can limit the scope of this workaround to end as of
// the last release that included the problem, since we can assume that
// users will not upgrade Google Keyboard to an EARLIER version than was
// originally included in their Android release.
//
// The bug that this addresses was FIXED but NOT RELEASED as of this AOSP
// commit:
//https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+
// /b41bea65502ce7339665859d3c2c81b4a29194e4/java/src/com/android
// /inputmethod/latin/LatinIME.java
// so it can be assumed to affect all of KitKat released thus far
// (up to 4.4.2), and could even affect beyond KitKat, although I fully
// expect it to be incorporated into the next release *after* API level 19.
//
// When it IS released, this method should be changed to limit it to no
// higher than API level 19 (assuming that the fix is released before API
// level 20), just in order to limit the scope of this fix, since poking
// 1024 characters into the Editable object returned here is of course a
// kluge. But right now the safest thing is just to not have an upper limit
// on the application of this kluge, since the fix for the problem it
// addresses has not yet been released (as of 1/7/2014).
if(Build.VERSION.SDK_INT >= 14) {
if(myEditable == null) {
myEditable = new EditableAccomodatingLatinIMETypeNullIssues(
EditableAccomodatingLatinIMETypeNullIssues.ONE_UNPROCESSED_CHARACTER);
Selection.setSelection(myEditable, 1);
}
else {
int myEditableLength = myEditable.length();
if(myEditableLength == 0) {
//I actually HAVE seen this be zero on the Nexus 10 with the keyboard
// that came with Android 4.4.2
// On the Nexus 10 4.4.2 if I tapped away from the view and then back to it, the
// myEditable would come back as null and I would create a new one. This is also
// what happens on other devices (e.g., the Nexus 6 with 4.4.2,
// which has a slightly later version of the Google Keyboard). But for the
// Nexus 10 4.4.2, the keyboard had a strange behavior
// when I tapped on the rack, and then tapped Done on the keyboard to close it,
// and then tapped on the rack AGAIN. In THAT situation,
// the myEditable would NOT be set to NULL but its LENGTH would be ZERO. So, I
// just append to it in that situation.
myEditable.append(
EditableAccomodatingLatinIMETypeNullIssues.ONE_UNPROCESSED_CHARACTER);
Selection.setSelection(myEditable, 1);
}
}
return myEditable;
}
else {
//Default behavior for keyboards that do not require any fix
return super.getEditable();
}
}
//This method is called INSTEAD of generating a KEYCODE_DEL event, by
// versions of Latin IME that have the bug described in Issue 42904.
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
//If targetSdkVersion is set to anything AT or ABOVE API level 16
// then for the GOOGLE KEYBOARD versions DELIVERED
// with Android 4.1.x, 4.2.x or 4.3.x, NO KEYCODE_DEL EVENTS WILL BE
// GENERATED BY THE GOOGLE KEYBOARD (LatinIME) EVEN when TYPE_NULL
// is being returned as the InputType by your view from its
// onCreateInputMethod() override, due to a BUG in THOSE VERSIONS.
//
// When TYPE_NULL is specified (as this entire class assumes is being done
// by the views that use it, what WILL be generated INSTEAD of a KEYCODE_DEL
// is a deleteSurroundingText(1,0) call. So, by overriding this
// deleteSurroundingText() method, we can fire the KEYDOWN/KEYUP events
// ourselves for KEYCODE_DEL. This provides a workaround for the bug.
//
// The specific AOSP RELEASES involved are 4.1.1_r1 (the very first 4.1
// release) through 4.4_r0.8 (the release just prior to Android 4.4).
// This means that all of KitKat should not have the bug and will not
// need this workaround.
//
// Although 4.0.x (ICS) did not have this bug, it was possible to install
// later versions of the keyboard as an app on anything running 4.0 and up,
// so those versions are also potentially affected.
//
// The first version of separately-installable Google Keyboard shown on the
// Google Play store site by www.archive.org is Version 1.0.1869.683049,
// on June 6, 2013, and that version (and probably other, later ones)
// already had this bug.
//
//Since this required at least 4.0 to install, I believe that the bug will
// not be present on devices running versions of Android earlier than 4.0.
//
//AND, it should not be present on versions of Android at 4.4 and higher,
// since users will not "upgrade" to a version of Google Keyboard that
// is LOWER than the one they got installed with their version of Android
// in the first place, and the bug will have been fixed as of the 4.4 release.
//
// The above scope of the bug is reflected in the test below, which limits
// the application of the workaround to Android versions between 4.0.x and 4.3.x.
//
//UPDATE: A popular third party keyboard was found that exhibits this same issue. It
// was not fixed at the same time as the Google Play keyboard, and so the bug in that case
// is still in place beyond API LEVEL 19. So, even though the Google Keyboard fixed this
// as of level 19, we cannot take out the fix based on that version number. And so I've
// removed the test for an upper limit on the version; the fix will remain in place ad
// infinitum - but only when TYPE_NULL is used, so it *should* be harmless even when
// the keyboard does not have the problem...
if((Build.VERSION.SDK_INT >= 14) // && (Build.VERSION.SDK_INT < 19)
&& (beforeLength == 1 && afterLength == 0)) {
//Send Backspace key down and up events to replace the ones omitted
// by the LatinIME keyboard.
return super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
&& super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
}
else {
//Really, I can't see how this would be invoked, given that we're using
// TYPE_NULL, for non-buggy versions, but in order to limit the impact
// of this change as much as possible (i.e., to versions at and above 4.0)
// I am using the original behavior here for non-affected versions.
return super.deleteSurroundingText(beforeLength, afterLength);
}
}
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
//Passing FALSE as the SECOND ARGUMENT (fullEditor) to the constructor
// will result in the key events continuing to be passed in to this
// view. Use our special BaseInputConnection-derived view
InputConnectionAccomodatingLatinIMETypeNullIssues baseInputConnection =
new InputConnectionAccomodatingLatinIMETypeNullIssues(this, false);
//In some cases an IME may be able to display an arbitrary label for a
// command the user can perform, which you can specify here. A null value
// here asks for the default for this key, which is usually something
// like Done.
outAttrs.actionLabel = null;
//Special content type for when no explicit type has been specified.
// This should be interpreted (by the IME that invoked
// onCreateInputConnection())to mean that the target InputConnection
// is not rich, it can not process and show things like candidate text
// nor retrieve the current text, so the input method will need to run
// in a limited "generate key events" mode. This disables the more
// sophisticated kinds of editing that use a text buffer.
outAttrs.inputType = InputType.TYPE_NULL;
//This creates a Done key on the IME keyboard if you need one
outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
return baseInputConnection;
}
this.setOnKeyListener(new OnKeyListener() {
@Override public
boolean onKey(View v, int keyCode, KeyEvent event) {
if(event.getAction() != KeyEvent.ACTION_DOWN) {
//We only look at ACTION_DOWN in this code, assuming that ACTION_UP is redundant.
// If not, adjust accordingly.
return false;
}
else if(event.getUnicodeChar() ==
(int)EditableAccomodatingLatinIMETypeNullIssues.ONE_UNPROCESSED_CHARACTER.charAt(0))
{
//We are ignoring this character, and we want everyone else to ignore it, too, so
// we return true indicating that we have handled it (by ignoring it).
return true;
}
//Now, just do your event handling as usual...
if(keyCode == KeyEvent.KEYCODE_ENTER) {
//Trap the Done key and close the keyboard if it is pressed (if that's what you want to do)
InputMethodManager imm = (InputMethodManager)
mainActivity.getSystemService(Context.INPUT_METHOD_SERVICE));
imm.hideSoftInputFromWindow(LetterRack.this.getWindowToken(), 0);
return true;
}
else if(keyCode == KeyEvent.KEYCODE_DEL) {
//Backspace key processing goes here...
return true;
}
else if((keyCode >= KeyEvent.KEYCODE_A) && (keyCode <= KeyEvent.KEYCODE_Z)) {
//(Or, use event.getUnicodeChar() if preferable to key codes).
//Letter processing goes here...
return true;
}
//Etc. } };
import android.text.SpannableStringBuilder;
public class EditableAccomodatingLatinIMETypeNullIssues extends SpannableStringBuilder {
EditableAccomodatingLatinIMETypeNullIssues(CharSequence source) {
super(source);
}
//This character must be ignored by your onKey() code.
public static CharSequence ONE_UNPROCESSED_CHARACTER = "/";
@Override
public SpannableStringBuilder replace(final int
spannableStringStart, final int spannableStringEnd, CharSequence replacementSequence,
int replacementStart, int replacementEnd) {
if (replacementEnd > replacementStart) {
//In this case, there is something in the replacementSequence that the IME
// is attempting to replace part of the editable with.
//We don't really care about whatever might already be in the editable;
// we only care about making sure that SOMETHING ends up in it,
// so that the backspace key will continue to work.
// So, start by zeroing out whatever is there to begin with.
super.replace(0, length(), "", 0, 0);
//We DO care about preserving the new stuff that is replacing the stuff in the
// editable, because this stuff might be sent to us as a keydown event. So, we
// insert the new stuff (typically, a single character) into the now-empty editable,
// and return the result to the caller.
return super.replace(0, 0, replacementSequence, replacementStart, replacementEnd);
}
else if (spannableStringEnd > spannableStringStart) {
//In this case, there is NOTHING in the replacementSequence, and something is
// being replaced in the editable.
// This is characteristic of a DELETION.
// So, start by zeroing out whatever is being replaced in the editable.
super.replace(0, length(), "", 0, 0);
//And now, we will place our ONE_UNPROCESSED_CHARACTER into the editable buffer, and return it.
return super.replace(0, 0, ONE_UNPROCESSED_CHARACTER, 0, 1);
}
// In this case, NOTHING is being replaced in the editable. This code assumes that there
// is already something there. This assumption is probably OK because in our
// InputConnectionAccomodatingLatinIMETypeNullIssues.getEditable() method
// we PLACE a ONE_UNPROCESSED_CHARACTER into the newly-created buffer. So if there
// is nothing replacing the identified part
// of the editable, and no part of the editable that is being replaced, then we just
// leave whatever is in the editable ALONE,
// and we can be confident that there will be SOMETHING there. This call to super.replace()
// in that case will be a no-op, except
// for the value it returns.
return super.replace(spannableStringStart, spannableStringEnd,
replacementSequence, replacementStart, replacementEnd);
}
}
关于android - Android-无法捕获软件中的退格键/删除键。键盘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18581636/
多个 ChildException catch block 和一个 Exception catch block 之间哪个更好? 更好,我的意思是以良好的实践方式。 举例说明: public stati
我正在尝试将脱机计算机记录在文本文件中,以便以后可以再次运行它们。似乎没有被记录或捕获。 function Get-ComputerNameChange { [CmdletBinding()]
我正在将 Scala 'try/catch' 测试代码转换为使用 'intercept' 有没有我不应该使用“拦截”的场景?使用 'intercept' 而不是 'try/catch' 的唯一好处是简
我对erlang很陌生,我正在尝试使用基本的try/catch语句来工作。我正在使用Webmachine处理一些请求,我真正想做的就是解析一些JSON数据并将其返回。如果JSON数据无效,我只想返回一
我不知道如何捕获删除按键。我发现在 ASCII 代码表中,它位于 127 位,但是 if (Key = #127) then 却无济于事。 然后我检查了 VK_DELETE 的值,它是 47。尝试使用
我很少在失败时对数据库查询使用唯一的错误消息 我经常使用简短的标准消息,例如“数据库错误/失败。请与网站管理员联系”或类似的消息。或自动发送给我 我正在寻找一种在PDO中全局设置一次try {}和ca
我有一个变量CompletableFuture completableFuture 。我希望能够使用任何类型的对象来完成它。例如:completableFuture.complete(new Stri
我认为这是基本的东西,但我不知道该怎么做。为什么我得到 IOException never throw in body of相应的 try 语句 public static void main(Str
我在此代码中遇到 JSON 异常: JSONObject jObject = new JSONObject(JSONString); pontosUsuario.setIdUsuari
我正在尝试打印出用单引号括起来的文本。 /bin/bash -lc '/home/CASPER_REPORTS/scripts/CASPER_gen_report.sh CASPER_1' /bin/
我这里遇到了一点问题。我想弄清楚如何捕获 IllegalArgumentException。对于我的程序,如果用户输入负整数,程序应该捕获 IllegalArgumentException 并询问用户
我无法理解 EJBTransactionRolledbackException。 我有实体: @Entity public class MyEntity { @Id @Generate
对于我给自己提出的以下挑战,如果社区的经验给我任何建议,我将不胜感激 - 即,这里有任何关于最佳方法/方向的指示吗? 要求 允许收集/实时监控从用户 Windows PC 到一组特定 IP 地址(或
我想在我的 ABAP 代码中捕获并处理 SAPSQL_DATA_LOSS。 我试过这个: try. SELECT * FROM (rtab_name) AS rtab
我知道捕获错误不是一个好的做法,但在这种情况下,这样做很重要。我正在尝试运行一个包含游戏一部分的 jar,但它给了我一个 unsatisfiedlink 错误,但这是有趣的部分:我正在使用这段代码:
我有一个表单页面,当我保存它时,它会覆盖数据库。表单页面中有一个文本框,允许用户输入 4000 个字符,但如果用户输入的字符超过此值,则会出现以下错误: ERROR 15:54:05 Abstrac
我想知道在python中绑定(bind)键的最简单方法 例如,默认的 python 控制台窗口出现并等待,然后在 psuedo -> if key "Y" is pressed: print (
下面是别人写的类。 我面临的问题是,当它进入parse method时与 null as the rawString ,它正在扔NumberFormatException 。 所以我想做的是,我应该捕
我有一个简单的脚本,可以捕获所有鼠标单击,除非您单击实际有效的内容。链接、Flash 视频等。我如何调整它,以便无论用户点击什么,在视频加载、新页面加载等之前,它都会发送我构建的简单 GET 请求?
我有一个带有一些选择列表的表单,当选择某些值时,这些列表将显示/隐藏更多输入字段。 问题是大多数用户都是数据输入人员,因此他们在输入数据时大量使用键盘,并且选择列表的 change 事件仅在焦点离开输
我是一名优秀的程序员,十分优秀!