Separate notification area into own controller.

Extracts the notification area of the status bar into a layout file and
create a NotificationAreaController that controls what happens in this
area.

This is to allow this area to be configurable in Android Auto Embedded
cases where OEMs may want their own custom implementations here.

Change-Id: I8a52af676d16fd6f7d3878805970a5897d2db945
This commit is contained in:
Anthony Chen
2016-01-11 17:00:36 -08:00
parent 2a0a2e0129
commit 83092c6cbb
4 changed files with 207 additions and 103 deletions

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2016 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<com.android.keyguard.AlphaOptimizedLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/notification_icon_area_inner"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.android.systemui.statusbar.StatusBarIconView
android:id="@+id/moreIcon"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
android:src="@drawable/stat_notify_more"
android:visibility="gone" />
<com.android.systemui.statusbar.phone.IconMerger
android:id="@+id/notificationIcons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:gravity="center_vertical"
android:orientation="horizontal"/>
</com.android.keyguard.AlphaOptimizedLinearLayout>

View File

@@ -47,34 +47,14 @@
android:orientation="horizontal"
>
<!-- The alpha of this area is controlled from both PhoneStatusBarTransitions and
PhoneStatusBar (DISABLE_NOTIFICATION_ICONS). -->
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/notification_icon_area"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
>
<!-- The alpha of this area is both controlled from PhoneStatusBarTransitions and
PhoneStatusBar (DISABLE_NOTIFICATION_ICONS), so we need two views here. -->
<com.android.keyguard.AlphaOptimizedLinearLayout
android:id="@+id/notification_icon_area_inner"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.android.systemui.statusbar.StatusBarIconView android:id="@+id/moreIcon"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
android:src="@drawable/stat_notify_more"
android:visibility="gone"
/>
<com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:gravity="center_vertical"
android:orientation="horizontal"/>
</com.android.keyguard.AlphaOptimizedLinearLayout>
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
android:orientation="horizontal" />
<com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"
android:layout_width="wrap_content"

View File

@@ -0,0 +1,151 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import java.util.ArrayList;
/**
* A controller for the space in the status bar to the left of the system icons. This area is
* normally reserved for notifications.
*/
public class NotificationIconAreaController {
private final NotificationColorUtil mNotificationColorUtil;
private int mIconSize;
private int mIconHPadding;
private int mIconTint = Color.WHITE;
private PhoneStatusBar mPhoneStatusBar;
protected View mNotificationIconArea;
private IconMerger mNotificationIcons;
private ImageView mMoreIcon;
public NotificationIconAreaController(Context context, PhoneStatusBar phoneStatusBar) {
mPhoneStatusBar = phoneStatusBar;
mNotificationColorUtil = NotificationColorUtil.getInstance(context);
initializeNotificationAreaViews(context);
}
/**
* Initializes the views that will represent the notification area.
*/
protected void initializeNotificationAreaViews(Context context) {
Resources res = context.getResources();
mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
mIconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_padding);
LayoutInflater layoutInflater = LayoutInflater.from(context);
mNotificationIconArea = layoutInflater.inflate(R.layout.notification_icon_area, null);
mMoreIcon = (ImageView) mNotificationIconArea.findViewById(R.id.moreIcon);
mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
mNotificationIcons =
(IconMerger) mNotificationIconArea.findViewById(R.id.notificationIcons);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
}
/**
* Returns the view that represents the notification area.
*/
public View getNotificationInnerAreaView() {
return mNotificationIconArea;
}
/**
* Sets the color that should be used to tint any icons in the notification area. If this
* method is not called, the default tint is {@link Color#WHITE}.
*/
public void setIconTint(int iconTint) {
mIconTint = iconTint;
mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
applyNotificationIconsTint();
}
/**
* Updates the notifications with the given list of notifications to display.
*/
public void updateNotificationIcons(NotificationData notificationData) {
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
mIconSize + 2 * mIconHPadding, mPhoneStatusBar.getStatusBarHeight());
ArrayList<NotificationData.Entry> activeNotifications =
notificationData.getActiveNotifications();
final int size = activeNotifications.size();
ArrayList<StatusBarIconView> toShow = new ArrayList<>(size);
// Filter out ambient notifications and notification children.
for (int i = 0; i < size; i++) {
NotificationData.Entry ent = activeNotifications.get(i);
if (notificationData.isAmbient(ent.key)
&& !NotificationData.showNotificationEvenIfUnprovisioned(ent.notification)) {
continue;
}
if (!PhoneStatusBar.isTopLevelChild(ent)) {
continue;
}
toShow.add(ent.icon);
}
ArrayList<View> toRemove = new ArrayList<>();
for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
View child = mNotificationIcons.getChildAt(i);
if (!toShow.contains(child)) {
toRemove.add(child);
}
}
final int toRemoveCount = toRemove.size();
for (int i = 0; i < toRemoveCount; i++) {
mNotificationIcons.removeView(toRemove.get(i));
}
for (int i = 0; i < toShow.size(); i++) {
View v = toShow.get(i);
if (v.getParent() == null) {
mNotificationIcons.addView(v, i, params);
}
}
// Re-sort notification icons
final int childCount = mNotificationIcons.getChildCount();
for (int i = 0; i < childCount; i++) {
View actual = mNotificationIcons.getChildAt(i);
StatusBarIconView expected = toShow.get(i);
if (actual == expected) {
continue;
}
mNotificationIcons.removeView(expected);
mNotificationIcons.addView(expected, i);
}
applyNotificationIconsTint();
}
/**
* Applies {@link #mIconTint} to the notification icons.
*/
private void applyNotificationIconsTint() {
for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
StatusBarIconView v = (StatusBarIconView) mNotificationIcons.getChildAt(i);
boolean isPreL = Boolean.TRUE.equals(v.getTag(R.id.icon_is_pre_L));
boolean colorize = !isPreL || NotificationUtils.isGrayscale(v, mNotificationColorUtil);
if (colorize) {
v.setImageTintList(ColorStateList.valueOf(mIconTint));
}
}
}
}

View File

@@ -36,14 +36,12 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -66,15 +64,15 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
private Interpolator mLinearOutSlowIn;
private Interpolator mFastOutSlowIn;
private DemoStatusIcons mDemoStatusIcons;
private NotificationColorUtil mNotificationColorUtil;
private LinearLayout mSystemIconArea;
private LinearLayout mStatusIcons;
private SignalClusterView mSignalCluster;
private LinearLayout mStatusIconsKeyguard;
private IconMerger mNotificationIcons;
private View mNotificationIconArea;
private ImageView mMoreIcon;
private NotificationIconAreaController mNotificationIconAreaController;
private View mNotificationIconAreaInner;
private BatteryMeterView mBatteryMeterView;
private TextView mClock;
@@ -110,14 +108,19 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
PhoneStatusBar phoneStatusBar) {
mContext = context;
mPhoneStatusBar = phoneStatusBar;
mNotificationColorUtil = NotificationColorUtil.getInstance(context);
mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area);
mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons);
mSignalCluster = (SignalClusterView) statusBar.findViewById(R.id.signal_cluster);
mNotificationIconArea = statusBar.findViewById(R.id.notification_icon_area_inner);
mNotificationIcons = (IconMerger) statusBar.findViewById(R.id.notificationIcons);
mMoreIcon = (ImageView) statusBar.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
mNotificationIconAreaController =
new NotificationIconAreaController(context, phoneStatusBar);
mNotificationIconAreaInner =
mNotificationIconAreaController.getNotificationInnerAreaView();
ViewGroup notificationIconArea =
(ViewGroup) statusBar.findViewById(R.id.notification_icon_area);
notificationIconArea.addView(mNotificationIconAreaInner);
mStatusIconsKeyguard = (LinearLayout) keyguardStatusBar.findViewById(R.id.statusIcons);
mBatteryMeterView = (BatteryMeterView) statusBar.findViewById(R.id.battery);
mClock = (TextView) statusBar.findViewById(R.id.clock);
@@ -259,60 +262,7 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
}
public void updateNotificationIcons(NotificationData notificationData) {
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
mIconSize + 2*mIconHPadding, mPhoneStatusBar.getStatusBarHeight());
ArrayList<NotificationData.Entry> activeNotifications =
notificationData.getActiveNotifications();
final int N = activeNotifications.size();
ArrayList<StatusBarIconView> toShow = new ArrayList<>(N);
// Filter out ambient notifications and notification children.
for (int i = 0; i < N; i++) {
NotificationData.Entry ent = activeNotifications.get(i);
if (notificationData.isAmbient(ent.key)
&& !NotificationData.showNotificationEvenIfUnprovisioned(ent.notification)) {
continue;
}
if (!PhoneStatusBar.isTopLevelChild(ent)) {
continue;
}
toShow.add(ent.icon);
}
ArrayList<View> toRemove = new ArrayList<>();
for (int i=0; i<mNotificationIcons.getChildCount(); i++) {
View child = mNotificationIcons.getChildAt(i);
if (!toShow.contains(child)) {
toRemove.add(child);
}
}
final int toRemoveCount = toRemove.size();
for (int i = 0; i < toRemoveCount; i++) {
mNotificationIcons.removeView(toRemove.get(i));
}
for (int i=0; i<toShow.size(); i++) {
View v = toShow.get(i);
if (v.getParent() == null) {
mNotificationIcons.addView(v, i, params);
}
}
// Resort notification icons
final int childCount = mNotificationIcons.getChildCount();
for (int i = 0; i < childCount; i++) {
View actual = mNotificationIcons.getChildAt(i);
StatusBarIconView expected = toShow.get(i);
if (actual == expected) {
continue;
}
mNotificationIcons.removeView(expected);
mNotificationIcons.addView(expected, i);
}
applyNotificationIconsTint();
mNotificationIconAreaController.updateNotificationIcons(notificationData);
}
public void hideSystemIconArea(boolean animate) {
@@ -324,11 +274,11 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
}
public void hideNotificationIconArea(boolean animate) {
animateHide(mNotificationIconArea, animate);
animateHide(mNotificationIconAreaInner, animate);
}
public void showNotificationIconArea(boolean animate) {
animateShow(mNotificationIconArea, animate);
animateShow(mNotificationIconAreaInner, animate);
}
public void setClockVisibility(boolean visible) {
@@ -444,6 +394,7 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
mDarkIntensity = darkIntensity;
mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
mNotificationIconAreaController.setIconTint(mIconTint);
applyIconTint();
}
@@ -461,21 +412,8 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
v.setImageTintList(ColorStateList.valueOf(mIconTint));
}
mSignalCluster.setIconTint(mIconTint, mDarkIntensity);
mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
mBatteryMeterView.setDarkIntensity(mDarkIntensity);
mClock.setTextColor(mIconTint);
applyNotificationIconsTint();
}
private void applyNotificationIconsTint() {
for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
StatusBarIconView v = (StatusBarIconView) mNotificationIcons.getChildAt(i);
boolean isPreL = Boolean.TRUE.equals(v.getTag(R.id.icon_is_pre_L));
boolean colorize = !isPreL || NotificationUtils.isGrayscale(v, mNotificationColorUtil);
if (colorize) {
v.setImageTintList(ColorStateList.valueOf(mIconTint));
}
}
}
public void appTransitionPending() {