记录一下目前学习的。
长按power键会出现的对话框(其实是linearlayout),代码位置在
frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
1.添加按钮
加载哪些按钮,看for循环。想要自己加新的可以模仿的加。
/**
* Create the global actions dialog.
*
* @return A new dialog.
*/
private ActionsDialog createDialog() {
// Simple toggle style if there's no vibrator, otherwise use a tri-state
if (!mHasVibrator) {
mSilentModeAction = new SilentModeToggleAction();
} else {
mSilentModeAction = new SilentModeTriStateAction(mAudioManager, mHandler);
}
mAirplaneModeOn = new ToggleAction(
R.drawable.ic_lock_airplane_mode,
R.drawable.ic_lock_airplane_mode_off,
R.string.global_actions_toggle_airplane_mode,
R.string.global_actions_airplane_mode_on_status,
R.string.global_actions_airplane_mode_off_status) {
void onToggle(boolean on) {
if (mHasTelephony && Boolean.parseBoolean(
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
mIsWaitingForEcmExit = true;
// Launch ECM exit dialog
Intent ecmDialogIntent =
new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);
ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(ecmDialogIntent);
} else {
changeAirplaneModeSystemSetting(on);
}
}
@Override
protected void changeStateFromPress(boolean buttonOn) {
if (!mHasTelephony) return;
// In ECM mode airplane state cannot be changed
if (!(Boolean.parseBoolean(
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) {
mState = buttonOn ? State.TurningOn : State.TurningOff;
mAirplaneState = mState;
}
}
public boolean showDuringKeyguard() {
return true;
}
public boolean showBeforeProvisioning() {
return false;
}
};
onAirplaneModeChanged();
mItems = new ArrayList<Action>();
String[] defaultActions = mContext.getResources().getStringArray(
R.array.config_globalActionsList);
ArraySet<String> addedKeys = new ArraySet<String>();
mHasLogoutButton = false;
mHasLockdownButton = false;
for (int i = 0; i < defaultActions.length; i++) {
String actionKey = defaultActions[i];
if (addedKeys.contains(actionKey)) {
// If we already have added this, don't add it again.
continue;
}
if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
mItems.add(new PowerAction());
} else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
mItems.add(mAirplaneModeOn);
} else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
if (Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
mItems.add(new BugReportAction());
}
} else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {
if (mShowSilentToggle) {
mItems.add(mSilentModeAction);
}
} else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {
if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
addUsersToMenu(mItems);
}
} else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
mItems.add(getSettingsAction());
} else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0, getCurrentUser().id) != 0
&& shouldDisplayLockdown()) {
mItems.add(getLockdownAction());
mHasLockdownButton = true;
}
} else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
mItems.add(getVoiceAssistAction());
} else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
mItems.add(getAssistAction());
} else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
mItems.add(new RestartAction());
} else if (GLOBAL_ACTION_KEY_SCREENSHOT.equals(actionKey)) {
mItems.add(new ScreenshotAction());
} else if (GLOBAL_ACTION_KEY_LOGOUT.equals(actionKey)) {
if (mDevicePolicyManager.isLogoutEnabled()
&& getCurrentUser().id != UserHandle.USER_SYSTEM) {
mItems.add(new LogoutAction());
mHasLogoutButton = true;
}
} else if (GLOBAL_ACTION_KEY_EMERGENCY.equals(actionKey)) {
if (!mEmergencyAffordanceManager.needsEmergencyAffordance()) {
mItems.add(new EmergencyDialerAction());
}
} else if (GLOBAL_ACTION_KEY_BATTERY_SHELF_MODE.equals(actionKey)) {
mItems.add(new BatteryShelfModeAction());
}
else {
Log.e(TAG, "Invalid global action key " + actionKey);
}
// Add here so we don't add more than one.
addedKeys.add(actionKey);
}
2.布局
它在初始化的时候会去加载对应的布局,不同旋转角度不一样。
private int getGlobalActionsLayoutId(Context context) {
int rotation = RotationUtils.getRotation(context);
boolean useGridLayout = isForceGridEnabled(context)
|| (shouldUsePanel() && rotation == RotationUtils.ROTATION_NONE);
if (rotation == RotationUtils.ROTATION_SEASCAPE) {
if (useGridLayout) {
return com.android.systemui.R.layout.global_actions_grid_seascape;
} else {
return com.android.systemui.R.layout.global_actions_column_seascape;
}
} else {
if (useGridLayout) {
return com.android.systemui.R.layout.global_actions_grid;
} else {
return com.android.systemui.R.layout.global_actions_column;
}
}
}
当屏幕旋转的时候会走这,不是每次都走,会根据RotationUtils.getRotation来判断是否要刷新,可以追踪哪里调用这个onRotate
public void onRotate(int from, int to) {
if (mShowing) {
refreshDialog();
}
}
如果你发现对话框显示的位置和xml中定义的不一样,那是因为在代码中有重新修改了。
frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsColumnLayout.java
/**
* Snap this layout to align with the power button.
*/
@VisibleForTesting
protected void snapToPowerButton() {
int offset = getPowerButtonOffsetDistance();
switch (getCurrentRotation()) {
case (ROTATION_LANDSCAPE):
setPadding(offset, 0, 0, 0);
setGravity(Gravity.LEFT | Gravity.TOP);
break;
case (ROTATION_SEASCAPE):
setPadding(0, 0, offset, 0);
setGravity(Gravity.RIGHT | Gravity.BOTTOM);
break;
default:
setPadding(0, offset, 0, 0);
setGravity(Gravity.TOP | Gravity.RIGHT);
break;
}
}
/**
* Detach this layout from snapping to the power button and instead center along that edge.
*/
@VisibleForTesting
protected void centerAlongEdge() {
switch (getCurrentRotation()) {
case (ROTATION_LANDSCAPE):
setPadding(0, 0, 0, 0);
setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
break;
case (ROTATION_SEASCAPE):
setPadding(0, 0, 0, 0);
setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
break;
default:
setPadding(0, 0, 0, 0);
setGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
break;
}
}