在Android中,可以在他们到达具有焦点的子视图之前全局拦截关键事件吗?

时间:2013-02-15 08:29:23

标签: android events event-handling keyboard key

在大多数情况下,我希望关键事件由目前具有焦点的(子)视图处理,这是默认行为,也是我目前已经实现的。

但是,在某些非常具体的情况下,我想暂时拦截和处理所有关键事件(包括那些通常由子视图处理的事件),或者在我当前的活动中,或者在我的根视图中失败(它没有没关系,只要它们在全球范围内处理 - 我不关心像音量+/-这样的硬件按钮,因为无论如何都不会在我的任何子视图中处理这些按钮。)

对于 touch 事件,我们有onInterceptTouchEvent(),它允许ViewGroup在调度到子视图时观察触摸事件,并阻止子项接收这些事件(如果需要)他们想要的观点。

不幸的是,我找不到与onInterceptTouchEvent()类似的关键事件。我错过了一些明显的东西,或者这是操作系统中的实际不对称吗?

当然,我可以连接每个子视图的当前键事件处理程序代码,直接调用主活动上的方法来处理事件,如果它想要,并让该活动级方法返回一个布尔值表示是否处理了该事件。然后,当且仅当它调用的活动方法处理它时,子视图才能处理该事件。

但是我希望有一种更简洁的方法可以简单地拦截流向“层次结构”到子视图的路径,就像onInterceptTouchEvent()对触摸事件一样。

3 个答案:

答案 0 :(得分:0)

所有小部件/视图似乎都实现了KeyEvent.Callback,它具有按键,长按,多按键和按键调用的方法。所有这些方法都返回布尔值,解释如下:

  

如果您处理了该事件,请返回true。如果您想允许该活动   由下一个接收者处理,返回false。

我认为您可以尝试在父组件中覆盖这些方法。

另一个是dispatchKeyEvent() View,它处理焦点路径下的调度事件。也可以尝试覆盖这一点。

答案 1 :(得分:0)

覆盖dispatchKeyEventViewGroup的{​​{1}},该View是要禁用的public static class TvPrefsContainer extends FrameLayout { private boolean isActive; // i.e. will dispatch keyboard events to focused children // snip @Override public boolean dispatchKeyEvent(KeyEvent event) { return isActive && super.dispatchKeyEvent(event); } } public static class TvPrefs extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.tv_prefs); } } private void togglePrefsVis() { tvPrefsContainer.animate() .alpha(isPrefsVisible ? 0 : 1) .translationX(isPrefsVisible ? tvPrefsContainer.getMeasuredWidth() : 0) .start(); tvPrefsContainer.isActive = isPrefsVisible; isPrefsVisible = !isPrefsVisible; } 的祖先。

我正在使用以下〜。

{{1}}

答案 2 :(得分:0)

您可以将@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(android.R.id.content).getViewTreeObserver().addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() { @Override public void onGlobalFocusChanged(View oldFocus, View newFocus) { if (newFocus instanceof EditText) { ((EditText) newFocus).addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { //process whatever you want } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { } }); } } }); } 添加到根视图中。我们按照活动这样做:

EditText

当然,如果您对Application#registerActivityLifecycleCallbacks()以外的其他观点感兴趣,您必须弄清楚如何观察他们的变化。

如果您想将其全局添加到所有活动中,请使用{{1}}在您的所有活动中使用该代码。