13

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

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

对于触摸事件,我们有 onInterceptTouchEvent(),它允许 ViewGroup 在触摸事件被分派到子视图时观察它们,并阻止它们预期的子视图接收这些事件(在需要时)。

不幸的是,对于关键事件,我找不到任何类似于 onInterceptTouchEvent() 的东西。我是否遗漏了一些明显的东西,或者这是操作系统中的实际不对称?

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

但我希望有一种更简洁的方法来简单地拦截流量“向下”到子视图的层次结构,就像 onInterceptTouchEvent() 对触摸事件所做的那样。

4

3 回答 3

1

您可以添加OnGlobalFocusChangeListener到您的根视图。让我们为每个活动执行此操作:

@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()中,请在所有活动中使用该代码。

于 2017-10-09T10:22:04.143 回答
0

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

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

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

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

于 2013-02-15T08:45:05.697 回答
0

覆盖dispatchKeyEvent在要禁用ViewGroup的 s 的祖先的 a 中。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;
}
于 2014-12-02T01:17:28.487 回答