需求: 导航栏添加截屏和电源键图标,控制截屏和用于设备重启关机功能。设置中添加延时截屏和控制截屏图标显示开关。
1. 导航栏添加图标
1.1 添加布局文件和图标icon
在layout目录下添加nav_power.xml和screenshot.xml文件
- frameworks/base/packages/SystemUI/res/layout/nav_power.xml
<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.statusbar.policy.KeyButtonView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_power"
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:layout_weight="0"
android:scaleType="center"
android:contentDescription="@string/accessibility_home"
android:paddingStart="@dimen/navigation_key_padding"
android:paddingEnd="@dimen/navigation_key_padding"
/>
- frameworks/base/packages/SystemUI/res/layout/screenshot.xml
<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.statusbar.policy.KeyButtonView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/screenshot"
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:layout_weight="0"
systemui:keyCode="0"
android:scaleType="center"
android:contentDescription="@string/accessibility_home"
android:paddingStart="@dimen/navigation_key_padding"
android:paddingEnd="@dimen/navigation_key_padding"
/>
drawable目录下添加ic_sysbar_power_button.xml和ic_sysbar_screenshot_button.xml
- frameworks/base/packages/SystemUI/res/drawable/ic_sysbar_power_button.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/singleToneColor"
android:pathData="M11,2h2v10h-2zM18.37,5.64l-1.41,1.41c2.73,2.73 2.72,7.16 -0.01,9.89 -2.73,2.73 -7.17,2.73 -9.89,0.01 -2.73,-2.73 -2.74,-7.18 -0.01,-9.91l-1.41,-1.4c-3.51,3.51 -3.51,9.21 0.01,12.73 3.51,3.51 9.21,3.51 12.72,-0.01 3.51,-3.51 3.51,-9.2 0,-12.72z"/>
</vector>
- frameworks/base/packages/SystemUI/res/drawable/ic_sysbar_screenshot_button.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/singleToneColor"
android:pathData="M17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,21L7,21v-1h10v1zM17,18L7,18L7,6h10v12zM17,4L7,4L7,3h10v1zM9.5,8.5L12,8.5L12,7L8,7v4h1.5zM12,17h4v-4h-1.5v2.5L12,15.5z"/>
</vector>
1.2 加载布局
- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
public static final String HOME = "home";
// add start
public static final String SCREENSHOT = "screenshot";
public static final String NAV_POWER = "nav_power";
// end
// 获取默认布局资源配置,关系到下一步修改图标显示位置顺序
protected String getDefaultLayout() {
final int defaultResource = QuickStepContract.isGesturalMode(mNavBarMode)
? R.string.config_navBarLayoutHandle
: mOverviewProxyService.shouldShowSwipeUpUI()
? R.string.config_navBarLayoutQuickstep
: R.string.config_navBarLayout;
return getContext().getString(defaultResource);
}
...
private View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater) {
View v = null;
...
if (HOME.equals(button)) {
v = inflater.inflate(R.layout.home, parent, false);
// add start
} else if (SCREENSHOT.equals(button)) {
v = inflater.inflate(R.layout.screenshot, parent, false);
} else if (NAV_POWER.equals(button)) {
v = inflater.inflate(R.layout.nav_power, parent, false);
}
// end
1.3 控制导航栏按键显示位置
- frameworks/base/packages/SystemUI/res/values-sw372dp/config.xml
<string name="config_navBarLayout" translatable="false">left[.25W],screenshot[.5WC],back[.5WC];home;recent[.5WC],nav_power[.5WC],right[.25W]</string>
这个根据设备的分辨率来修改,有可能需要修改其他目录下的config,搜索config_navBarLayout
1.4 添加的按键设置图标
- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
private KeyButtonDrawable mBackIcon;
private KeyButtonDrawable mHomeDefaultIcon;
// add start
private KeyButtonDrawable mScreenshotIcon;
private KeyButtonDrawable mNavPowerIcon;
// end
...
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
...
mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
// add start
mButtonDispatchers.put(R.id.screenshot, new ButtonDispatcher(R.id.screenshot));
mButtonDispatchers.put(R.id.nav_power, new ButtonDispatcher(R.id.nav_power));
// end
...
}
// add start
public ButtonDispatcher getScreenshotButton() {
return mButtonDispatchers.get(R.id.screenshot);
}
public ButtonDispatcher getNavPowerButton() {
return mButtonDispatchers.get(R.id.nav_power);
}
// end
...
private void updateIcons(Configuration oldConfig) {
...
if (orientationChange || densityChange || dirChange) {
mBackIcon = getBackDrawable();
}
// add start
mScreenshotIcon = getDrawable(R.drawable.ic_sysbar_screenshot_button);
mNavPowerIcon = getDrawable(R.drawable.ic_sysbar_power_button);
// end
}
...
public void updateNavButtonIcons() {
...
getHomeButton().setImageDrawable(homeIcon);
getBackButton().setImageDrawable(backIcon);
// add start
getScreenshotButton().setImageDrawable(mScreenshotIcon);
getNavPowerButton().setImageDrawable(mNavPowerIcon);
// end
...
}
1.5 设置监听事件
- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
import android.os.SystemClock; // add start
private static final long AUTODIM_TIMEOUT_MS = 2250;
// add start
private static final long SCREENSHOT_TIME_INTERVAL = 3000;
private long mLastClickScreenshotTime = 0;
// end
private void prepareNavigationBarView() {
mNavigationBarView.reorient();
...
// add start
ButtonDispatcher screenshotButton = mNavigationBarView.getScreenshotButton();
screenshotButton.setOnClickListener(this:: screenshotClick);
screenshotButton.setVisibility(View.VISIBLE);
ButtonDispatcher navPowerButton = mNavigationBarView.getNavPowerButton();
navPowerButton.setOnClickListener(this:: navPowerClick);
navPowerButton.setVisibility(View.VISIBLE);
// end
}
...
// add start
private void navPowerClick(View v) {
Intent intent=new Intent("android.intent.action.NAV_POWER");
getContext().sendBroadcast(intent);
}
private void screenshotClick(View v) {
long nowTime = SystemClock.elapsedRealtime();
if (nowTime - mLastClickScreenshotTime < SCREENSHOT_TIME_INTERVAL) {
return;
}
Intent intent=new Intent("android.intent.action.SCREENSHOT");
getContext().sendBroadcast(intent);
mLastClickScreenshotTime = nowTime;
}
// end
1.6 截屏和电源键功能实现
- frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
@Override
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
...
// add start
// register for nav_power click broadcasts
filter=new IntentFilter();
filter.addAction("android.intent.action.NAV_POWER");
context.registerReceiver(mNavPowerReceiver, filter);
// register for screenshot broadcasts
filter=new IntentFilter();
filter.addAction("android.intent.action.SCREENSHOT");
context.registerReceiver(mScreenshotReceiver, filter);
// end
...
}
// add start
BroadcastReceiver mScreenshotReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mHandler.post(mScreenshotRunnable);
}
};
BroadcastReceiver mNavPowerReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
showGlobalActionsInternal();
}
};
// end
底下的patch中有Settings中添加延时截屏和控制图标显示开关的修改
传送门