我正在开发一个Android项目,我需要检查空格键何时被按下sos我可以执行某个功能.
问题是,它正在模拟器上工作,但不在我的实际设备上.我想这可能是因为我的模拟器使用的是物理键盘,而不是屏幕上的虚拟键盘,但在实际设备上进行测试时,它使用的是虚拟键盘.
我正在尝试调度keyevent
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE
&& event.getAction() == KeyEvent.ACTION_UP)
{
QueryEditor queryEditor = (QueryEditor)getSupportFragmentManager().findFragmentById(R.id.fragment_queryEditor);
queryEditor.formatQueryText();
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
我也试过按键
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
disconnectDatabase();
}
else if (keyCode == KeyEvent.KEYCODE_DEL)
{
QueryEditor queryEditor = (QueryEditor)getSupportFragmentManager().findFragmentById(R.id.fragment_queryEditor);
queryEditor.formatQueryText();
}
return super.onKeyDown(keyCode, event);
}
Run Code Online (Sandbox Code Playgroud)
除非按下后退按钮但我需要空格键来触发事件,否则这些都不会被触发.
感谢您的任何帮助,您可以提供.
UPDATE
下面是我如何创建QueryEditor Fragment并创建事件处理程序的代码
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
iQueryEditor = (IQueryEditor)this;
iErrorHandler = (IErrorHandler)this;
txtQueryEditor = (EditText)getActivity().findViewById(R.id.query_txtQueryEditor);
btnSubmitQuery = (ImageButton)getActivity().findViewById(R.id.query_btnPerformQuery);
btnClearQuery = (ImageButton)getActivity().findViewById(R.id.query_btnDeleteQuery);
txtQueryEditor.addTextChangedListener(new QueryTextChanged(getActivity(), txtQueryEditor, iQueryEditor));
setDatabaseUsed();
txtQueryEditor.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER))
|| actionId == EditorInfo.IME_ACTION_DONE)
{
executeQuery();
return true;
}
else if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP)
{
Toast.makeText(getActivity(), "Space Bar Pressed", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
});
btnSubmitQuery.setOnClickListener(mBtnSubmitQueryListener);
btnClearQuery.setOnClickListener(mBtnDeleteQueryListener);
}
Run Code Online (Sandbox Code Playgroud)
txtQueryEditor是我试图接收空格键事件的EditText.
部分答案在于KeyEvent API文档:
由于软输入方法可以使用多种创造性的输入文本方式,因此无法保证软键盘上的任何按键都会产生关键事件:这由IME自行决定,实际上不鼓励发送此类事件.您永远不应该依赖于在软输入方法上接收任何键的KeyEvent.特别是,默认软件键盘永远不会向任何针对Jelly Bean或更高版本的应用程序发送任何键事件,并且只会将删除和返回键的某些按键发送给目标为Ice Cream Sandwich或更早版本的应用程序.请注意,无论版本如何,其他软件输入方法都可能永远不会发送关键事件.如果您需要与软件键盘进行特定交互,请考虑使用IME_ACTION_DONE之类的编辑器操作,因为它可以让用户更清楚地了解应用程序对按键操作的反应.
以下是Google工程师留下的评论:
答案很简单.应用程序永远不应该依赖关键事件来管理用户输入.原因是,它会导致非常糟糕的用户体验.
首先,有太多的情况不起作用.它对CJK语言不起作用.它无法通过手势输入,语音输入或切换输入正常工作,或者开发人员未来可能提出的任何新的创造性输入方法.实际上,唯一可行的情况是仅针对最差输入体验的受限情况:传统的硬件键盘式输入方法,这种方式不适合移动时代.
这就是为什么Android定义了一个丰富的API,IME通过它与应用程序进行通信.它与方法无关,与语言无关,所有软件输入方法都在实现它.应用程序应该使用这个API,使用EditText是最简单的方法(下面将详细介绍).
请停止依赖传统的关键事件进行文本输入 - 全部.支持他们很好,但要求他们对每个人都不好.它打破了一致性,它将一些语言锁定在您的应用程序之外,并且它迫使用户进入比他们在Android上预期的更差的体验.正如评论#14所述,输入方法明显没有义务发送关键事件,尽管有些人可能会选择这样做.
有两种简单的方法来实现富文本输入API.两者都需要一些在Java领域完成的.第一个是简单地使用EditText.如果您的应用需要自己进行渲染,则可以将其子类化(如果适合您),或者在对文本进行任何更改时将其隐藏.您还可以使用DynamicLayout和Editable来实现相同的效果.另一种可能是直接通过扩展BaseInputConnection实现InputConnection API,但是这是一个LOT的辛勤工作,一般只需要由有关于文本编辑,像一个IDE或文字处理非常特殊的需求的应用程序来完成.
您的 Activity 中的此实现应该有效:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) {
Log.d("test", "[Dispatch] Space bar pressed! " + event);
return true;
}
return super.dispatchKeyEvent(event);
}
Run Code Online (Sandbox Code Playgroud)
与您的代码的区别在于,我正在调用super.dispatchKeyEvent()除 SPACE_BAR 之外的所有其他键。如果dispatchKeyEvent返回trueonKeyUp()则不会被触发。因此,如果您只想监视空格键事件,只需注释行//return true;
如果你使用方法,它也会很好地工作onKeyUp()。不要使用onKeyDown(),如果用户手指握得太久,可能会被调用几次。
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SPACE) {
Log.d("test", "Space bar pressed!");
return true;
}
return super.onKeyUp(keyCode, event);
}
Run Code Online (Sandbox Code Playgroud)
这里我使用类似的方法。如果您的 if 语句为 true,则处理事件并返回 true。对于其余的钥匙,请致电super.onKeyUp();
至少,但最重要的是,如果您有拥有当前焦点的视图(例如 EditText)并且为该视图显示键盘,则根本不会调用上面的代码(在 Activity 中)。如果是这种情况,您必须实现侦听器TextView.OnEditorActionListener并注册该视图调用setOnEditorActionListener(TextView.OnEditorActionListener l)。
viewWithFocus.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) {
Log.d("test", "[Editor] Space bar pressed! " + event);
//TODO implement your action here
return true;//remove this line if you want edit text to create space
}
return false;
}
});
Run Code Online (Sandbox Code Playgroud)
作为替代方案,您可以覆盖此视图并onKepUp()像上面一样实现。
更新
上述解决方案适用于硬件键盘。抱歉没有更仔细地检查这一点。
来自 Android 文档
注意:当使用 KeyEvent 类和相关 API 处理键盘事件时,您应该预期此类键盘事件仅来自硬件键盘。您永远不应该依赖于接收软输入法(屏幕键盘)上任何键的按键事件。
然而,我找到了如何克服这个问题。我基于 SearchView 组件进行了研究,发现以下代码可以完成这项工作:
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
char last = s.charAt(s.length()-1);
if (' ' == last) {
Log.i("test", "space pressed");
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
Run Code Online (Sandbox Code Playgroud)
对于 IME 操作,请继续使用TextView.OnEditorActionListener.
| 归档时间: |
|
| 查看次数: |
8578 次 |
| 最近记录: |