在大多数情况下,我希望关键事件由目前具有焦点的(子)视图处理,这是默认行为,也是我目前已经实现的。
但是,在某些非常具体的情况下,我想暂时拦截和处理所有关键事件(包括那些通常由子视图处理的事件),或者在我当前的活动中,或者在我的根视图中失败(它没有没关系,只要它们在全球范围内处理 - 我不关心像音量+/-这样的硬件按钮,因为无论如何都不会在我的任何子视图中处理这些按钮。)
对于 touch 事件,我们有onInterceptTouchEvent(),它允许ViewGroup在调度到子视图时观察触摸事件,并阻止子项接收这些事件(如果需要)他们想要的观点。
不幸的是,我找不到与onInterceptTouchEvent()类似的关键事件。我错过了一些明显的东西,或者这是操作系统中的实际不对称吗?
当然,我可以连接每个子视图的当前键事件处理程序代码,直接调用主活动上的方法来处理事件,如果它想要,并让该活动级方法返回一个布尔值表示是否处理了该事件。然后,当且仅当它调用的活动方法不处理它时,子视图才能处理该事件。
但是我希望有一种更简洁的方法可以简单地拦截流向“层次结构”到子视图的路径,就像onInterceptTouchEvent()对触摸事件一样。
答案 0 :(得分:0)
所有小部件/视图似乎都实现了KeyEvent.Callback
,它具有按键,长按,多按键和按键调用的方法。所有这些方法都返回布尔值,解释如下:
如果您处理了该事件,请返回true。如果您想允许该活动 由下一个接收者处理,返回false。
我认为您可以尝试在父组件中覆盖这些方法。
另一个是dispatchKeyEvent()
View
,它处理焦点路径下的调度事件。也可以尝试覆盖这一点。
答案 1 :(得分:0)
覆盖dispatchKeyEvent
中ViewGroup
的{{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}}在您的所有活动中使用该代码。