BACK按键流程
来源:互联网 发布:淘宝怎么交保证金 编辑:程序博客网 时间:2024/06/03 21:37
事件被派发到View层次结构的根节点DecorView开始分析,这里我们先来看看DecorView#dispatchKeyEvent方法,代码如下:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
final int keyCode = event.getKeyCode();
final int action = event.getAction();
final boolean isDown = action == KeyEvent.ACTION_DOWN;
/// 1. 第一次down事件的时候,处理panel的快捷键
if (isDown && (event.getRepeatCount() == 0)) {
// First handle chording of panel key: if a panel key is held
// but not released, try to execute a shortcut in it.
if ((mPanelChordingKey > 0) && (mPanelChordingKey != keyCode)){
boolean handled = dispatchKeyShortcutEvent(event);
if (handled) { return true; }
}
// If a panel is open, perform a shortcut on it without the
// chorded panel key
if ((mPreparedPanel != null) && mPreparedPanel.isOpen) {
if (performPanelShortcut(mPreparedPanel, keyCode, event, 0)) { returntrue; }
}
}
/// 2. 这里是我们本文的重点,当window没destroy且其Callback非空的话,交给其Callback处理
if (!isDestroyed()) {
// Activity、Dialog都是Callback接口的实现
final Callback cb = getCallback();
// mFeatureId < 0 表示是application的DecorView,比如Activity、Dialog
final boolean handled = cb != null && mFeatureId < 0 ?cb.dispatchKeyEvent(event) //派发给callback的方法 : super.dispatchKeyEvent(event);
// 否则直接派发到ViewGroup#dispatchKeyEvent(View层次结构)
if (handled) {
return true;
// 如果被上面的步骤处理了则直接返回true,不再往下传递
}
}
/// 3. 这是key事件的最后一步,如果到这一步还没处理掉,则派发到PhoneWindow对应的onKeyDown, onKeyUp方法
return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(),event) : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event); }
frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindow.java
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
final int keyCode = event.getKeyCode();
final int action = event.getAction();
final boolean isDown = action == KeyEvent.ACTION_DOWN;
if (isDown && (event.getRepeatCount() == 0)) {
// First handle chording ofpanel key: if a panel key is held
// but not released, try toexecute a shortcut in it.
if ((mPanelChordingKey > 0)&& (mPanelChordingKey != keyCode)) {
boolean handled =dispatchKeyShortcutEvent(event);
if (handled) {
return true;
}
}
// If a panel is open, performa shortcut on it without the
// chorded panel key
if ((mPreparedPanel != null)&& mPreparedPanel.isOpen) {
if(performPanelShortcut(mPreparedPanel, keyCode, event, 0)) {
return true;
}
}
}
if (!isDestroyed()) {
final Callback cb =getCallback();
final boolean handled = cb !=null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
:super.dispatchKeyEvent(event);
if (handled) {
return true;
}
}
return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(),event)
:PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);
}
Activity层的(callback)dispatchKeyEvent
frameworks\base\core\java\android\app\Activity.java
public boolean dispatchKeyEvent(KeyEvent event){
onUserInteraction();
// Let action bars open menus in response to the menu key prioritizedover
// the window handling it
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU &&
mActionBar != null &&mActionBar.onMenuKeyEvent(event)) {
return true;
}
Window win = getWindow();
if (win.superDispatchKeyEvent(event)){
return true;
}
View decor = mDecor;
if (decor == null) decor = win.getDecorView();
return event.dispatch(this, decor != null
? decor.getKeyDispatcherState(): null, this);
}
调用frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindow.java
public booleansuperDispatchKeyEvent(KeyEvent event) {
// Give priority to closing actionmodes if applicable.
if (event.getKeyCode() ==KeyEvent.KEYCODE_BACK) {
final int action =event.getAction();
// Back cancels action modesfirst.
if (mActionMode != null) {
if (action ==KeyEvent.ACTION_UP) {
mActionMode.finish();
}
return true;
}
}
return super.dispatchKeyEvent(event);
}
Viewgroup层的frameworks\base\core\java\android\view\ ViewGroup.java
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onKeyEvent(event, 1);
}
if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
== (PFLAG_FOCUSED |PFLAG_HAS_BOUNDS)) {
if (super.dispatchKeyEvent(event)) {
return true;
}
} else if (mFocused != null && (mFocused.mPrivateFlags &PFLAG_HAS_BOUNDS)
== PFLAG_HAS_BOUNDS) {
if (mFocused.dispatchKeyEvent(event)) {
return true;
}
}
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 1);
}
return false;
}
View层frameworks\base\core\java\android\view\view.java
public boolean dispatchKeyEvent(KeyEventevent) {
if (mInputEventConsistencyVerifier !=null) {
mInputEventConsistencyVerifier.onKeyEvent(event, 0);
}
// Give any attached key listener afirst crack at the event.
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null &&li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&&li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
return true;
}
if (event.dispatch(this, mAttachInfo !=null
? mAttachInfo.mKeyDispatchState: null, this)) {
return true;
}
if (mInputEventConsistencyVerifier !=null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
return false;
}
KeyEvent的dispatch
frameworks\base\core\java\android\view\KeyEvent.java
public final boolean dispatch(Callbackreceiver, DispatcherState state,
Object target) {
switch (mAction) {
...
case ACTION_UP:
if (DEBUG) Log.v(TAG,"Key up to " + target +" in " + state
+ ": " + this);
if (state != null) {
state.handleUpEvent(this);
}
return receiver.onKeyUp(mKeyCode, this);
...
}
return false;
}
frameworks\base\core\java\android\view\view.java
public boolean onKeyUp(int keyCode,KeyEvent event) {
if (KeyEvent.isConfirmKey(keyCode)) {
if ((mViewFlags & ENABLED_MASK) == DISABLED) {
return true;
}
if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
setPressed(false);
if (!mHasPerformedLongPress) {
// This is a tap, so removethe longpress check
removeLongPressCallback();
return performClick();
}
}
}
return false;
}
public void setPressed(boolean pressed) {
final boolean needsRefresh = pressed != ((mPrivateFlags &PFLAG_PRESSED) == PFLAG_PRESSED);
if (pressed) {
mPrivateFlags |= PFLAG_PRESSED;
} else {
mPrivateFlags &= ~PFLAG_PRESSED;
}
if (needsRefresh) {
refreshDrawableState();
}
dispatchSetPressed(pressed);
}
Activity对应的onKeyDown,onKeyUp方法
frameworks\base\core\java\android\app\Dialog.java
public boolean onKeyUp(int keyCode,KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
&& !event.isCanceled()){
onBackPressed();
return true;
}
return false;
}
- BACK按键流程
- android back按键 一点技巧
- Android 按键屏蔽, Back, Home....
- Android 监听Back、Home按键
- Android back按键基础开发
- Android popupWindow响应back按键并关闭
- Android popupWindow响应back按键并关闭
- 关于程序响应 HOME 及 BACK 按键
- Android popupWindow响应back按键并关闭
- android 彻底关闭应用程序(back按键)
- Android popupWindow响应back按键并关闭
- Android popupWindow响应back按键并关闭
- Android popupWindow响应back按键并关闭
- 复写back按键让activity后台运行
- 监听back按键,再次点击退出应用
- 在Fragment中监听返回BACK按键
- MTK 按键处理流程
- 按键触摸屏流程分析
- anaconda的安装与使用
- oracle笔记总结
- [转载]Android APK反编译就这么简单 详解(附图)
- C++ 运算符重载
- 【机器学习-西瓜书】九、聚类:性能度量;距离计算
- BACK按键流程
- 在Ubuntu下利用AndroidStudio查看源码
- order by、group by、distinct、having、group_concat、concat
- sql数据库操作
- 51Nod 1089 最长回文子串 V2(Manacher算法)
- centos 7.2 迁移 mysql 数据库文件
- 关于WSAEWOULDBLOCK错误
- 前端基础
- Shell脚本实现俄罗斯方块流程