调试中发现,同一软件在密度不同的时候竟有不同的表现。当密度为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);
}
...
定位这处代码,追踪发现是在BaseStatusBar.java中调用的
@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);
}
猜测这是显示调用搜索条的地方,定位追踪,发现果然会跳转到这段代码,再往上发现它的调用顺序为TabletStatusBar.java(3-2-1)
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中可以找到
2默认设置为2,所以会显示最近程序条。而在密度为120时,不显示的原因是因为values-sw600dp中的config.xml中这个默认值不同,为
0