我正在开发一个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;
}
}
我也试过了按键
@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);
}
除非按下后退按钮但我需要空格键来触发事件,否则这些都不会被触发。
感谢您提供的任何帮助。
更新
下面是关于如何创建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);
}
txtQueryEditor是我试图接收空格键事件的EditText。
答案 0 :(得分:7)
部分答案在于KeyEvent API documentation:
由于软输入法可以使用多种创造性的输入方式 文字,无法保证软键盘上的任何按键都会 生成一个关键事件:这由IME自行决定,并且在 不鼓励发送此类事件的事实。你永远不应该依赖 接收软输入法上任何键的KeyEvents。特别是, 默认软件键盘永远不会向任何键事件发送任何键事件 应用程序目标是Jelly Bean或更高版本,并且只会发送事件 对于一些按下删除键和返回键到应用程序 目标冰淇淋三明治或更早。请注意其他软件 无论版本如何,输入方法都不会发送关键事件。 如果需要,请考虑使用IME_ACTION_DONE之类的编辑器操作 与软件键盘的特定交互,因为它提供了更多 用户对应用程序如何对密钥作出反应的可见性 印刷机。
以下是Google工程师留下的comment:
答案很简单。应用程序永远依赖于密钥 用于管理用户输入的事件。原因是,它导致了 用户体验很差。
首先,有太多的情况不起作用。它 对CJK语言不适用。这是行不通的 正确的手势输入,或语音输入,或切换 输入,或开发人员可能提出的任何新的创造性输入方法 在将来。事实上,唯一可行的情况是 最差投入经验的限制性案例:遗产 硬件键盘式输入法,这是一个不合适的 移动时代。
这就是Android定义IME通信的丰富API的原因 到应用程序。它与方法无关,与语言无关,并且 所有软件输入方法都在实现它。应用程序是 应该使用这个API,使用EditText是最简单的 这样做的方式(更多内容见下文)。
请停止依赖旧密钥事件进行文字输入 - 全部。它 很好地支持他们,但要求他们对每个人都不好。它 打破一致性,它会锁定你的应用程序中的一些语言 迫使用户进入比他们预期的更糟糕的体验 Android系统。正如注释#14所述,输入方法是明确的 虽然有些人可能会选择,但根本没有义务发送关键事件 这样做。
实现富文本输入API有两种简单的方法。 两者都需要一些在Java领域完成的。第一个是 简单地使用EditText。如果您的应用需要自己进行渲染,那么您 如果适合您,可以将其子类化,或者在您使用时隐藏它 呈现文本的任何更改。你也可以使用DynamicLayout和 可编辑达到同样的效果。另一种可能性是 通过扩展直接实现InputConnection API BaseInputConnection,但这是一个辛苦工作的 LOT 应该 通常只需要具有非常具体的应用程序来完成 关于文本编辑的需求,如IDE或文字处理器。
答案 1 :(得分:3)
您的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);
}
您的代码的不同之处在于我为除SPACE_BAR之外的所有其他键调用super.dispatchKeyEvent()
。如果dispatchKeyEvent返回true onKeyUp()
则不会被触发。因此,如果您只想监视空格键事件,只需注释行//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);
}
这里我使用类似的方法。如果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;
}
});
作为替代方案,您可以覆盖此视图并像上面一样实施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) {
}
});
对于IME操作,请继续使用TextView.OnEditorActionListener
。
答案 2 :(得分:-1)
我尝试了dispatchkeyevents和onkeydown两种方法,而对于软键盘,它们都没有用。 Atleast不在nexus 7.唯一有效的解决方案是在edittext中添加一个textwatcher。以下是代码:
public class MainActivity extends ActionBarActivity {
EditText editText1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = (EditText) findViewById(R.id.editText1);
editText1.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
String lastChar = s.toString().substring(s.length() - 1);
if (lastChar.equals(" ")) {
Toast.makeText(MainActivity.this, "space bar pressed",
Toast.LENGTH_SHORT).show();
}
}
});
}
}