调试中发现,同一软件在密度不同的时候竟有不同的表现。当密度为120时,长按home键会弹出搜索条,并且手指不放开,搜索条保持显示;而当密度为160时,长按home键会先弹出搜索条,然后搜索条消失,显示最近程序。使用工具发现搜索条的id为search_panel_container,找到这处地方SearchPanelView.java中
protected void onFinishInflate() { super.onFinishInflate(); mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mSearchTargetsContainer = findViewById(R.id.search_panel_container); ...
public void show(final boolean show, boolean animate) { if (!show) { final LayoutTransition transitioner = animate ? createLayoutTransitioner() : null; ((ViewGroup) mSearchTargetsContainer).setLayoutTransition(transitioner); } ...
@Override public void hideSearchPanel() { int msg = MSG_CLOSE_SEARCH_PANEL; mHandler.removeMessages(msg); mHandler.sendEmptyMessage(msg); }此处代码上方正好是
@Override public void showSearchPanel() { int msg = MSG_OPEN_SEARCH_PANEL; mHandler.removeMessages(msg); mHandler.sendEmptyMessage(msg); }
1、
@Override public void showSearchPanel() { super.showSearchPanel(); WindowManager.LayoutParams lp = (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams(); lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp); }2、
private Runnable mShowSearchPanel = new Runnable() { public void run() { showSearchPanel(); } };3、
private View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { switch(event.getAction()) { case MotionEvent.ACTION_DOWN: if (!shouldDisableNavbarGestures() && !inKeyguardRestrictedInputMode()) { mHandler.removeCallbacks(mShowSearchPanel); mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mHandler.removeCallbacks(mShowSearchPanel); break; } return false; } };至此,搜索条的显示搞清了,是由home键的监听器产生的。而最近程序的显示没有头绪,试着在BaseStatusBar.java中的
@Override public void toggleRecentApps() { int msg = (mRecentsPanel.getVisibility() == View.VISIBLE) ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL; mHandler.removeMessages(msg); mHandler.sendEmptyMessage(msg); }设置断点,代码会跳转到这边,发现是调用这段代码,一路追踪,在PhoneWindowManager.java中找到它的调用出处
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { ... if (keyCode == KeyEvent.KEYCODE_HOME) { ... if (down) { if (!mHomePressed && mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) { try { IStatusBarService statusbar = getStatusBarService(); if (statusbar != null) { statusbar.preloadRecentApps(); } } catch (RemoteException e) { Slog.e(TAG, "RemoteException when preloading recent apps", e); // re-acquire status bar service next time it is needed. mStatusBarService = null; } } if (repeatCount == 0) { mHomePressed = true; } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { if (!keyguardOn) { handleLongPressOnHome(); } } }到这步,真相大白,是通过mLongPressOnHomeBehavior的值去判断是否显示最近程序条,而mLongPressOnHomeBehavior是在handleLongPressOnHome中初始化的
private void handleLongPressOnHome() { // We can't initialize this in init() since the configuration hasn't been loaded yet. if (mLongPressOnHomeBehavior < 0) { mLongPressOnHomeBehavior = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior); if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING || mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) { mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING; } } if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) { performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS); // Eat the longpress so it won't dismiss the recent apps dialog when // the user lets go of the home key mHomeLongPressed = true; } if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) { showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS); } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) { try { IStatusBarService statusbar = getStatusBarService(); if (statusbar != null) { statusbar.toggleRecentApps(); } } catch (RemoteException e) { Slog.e(TAG, "RemoteException when showing recent apps", e); // re-acquire status bar service next time it is needed. mStatusBarService = null; } } }可以清楚的知道,mLongPressOnHomeBehavior的值是由config_longPressOnHomeBehavior设置的,而这个值是可配置的,在config.xml中可以找到
<!-- Control the behavior when the user long presses the home button. 0 - Nothing 1 - Recent apps dialog 2 - Recent apps view in SystemUI This needs to match the constants in policy/src/com/android/internal/policy/impl/PhoneWindowManager.java --> <integer name="config_longPressOnHomeBehavior">2</integer>默认设置为2,所以会显示最近程序条。而在密度为120时,不显示的原因是因为values-sw600dp中的config.xml中这个默认值不同,为
<!-- see comment in values/config.xml --> <integer name="config_longPressOnHomeBehavior">0</integer>