Update notification visuals (part 2)

- Background is now white, and color beneath and divider color
  updated accordingly (not from color extraction)
- Removed overflow text ("+6") and added it to a header
  ("6 Notifications"). Use "..." instead if there is an overflow.
- Even spaced out icons in notification footer between the
  far right icon and the ellipsis
- Remove code to change arrow tint, since it is always white
  now. This also fixes the issue where it was drawn as a rect.

Bug: 35766387
Change-Id: I03bfda4ff029f23dd8b3dd1b72f534ea0e2c0816
This commit is contained in:
Tony Wickham
2017-02-24 15:08:13 -08:00
parent f2db25398a
commit 9407d4ab57
15 changed files with 282 additions and 186 deletions
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="@dimen/horizontal_ellipsis_size"
android:height="@dimen/horizontal_ellipsis_size"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/textColorSecondary" >
<path
android:pathData="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"
android:fillColor="@android:color/white" />
</vector>
+37 -3
View File
@@ -20,7 +20,8 @@
android:layout_width="@dimen/bg_popup_item_width"
android:layout_height="wrap_content"
android:elevation="@dimen/deep_shortcuts_elevation"
android:background="@drawable/bg_white_round_rect">
android:background="@drawable/bg_white_round_rect"
android:backgroundTint="@color/notification_color_beneath">
<RelativeLayout
android:layout_width="match_parent"
@@ -28,16 +29,49 @@
android:orientation="vertical"
android:clipChildren="false">
<com.android.launcher3.notification.NotificationHeaderView
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="@dimen/notification_header_height"
android:orientation="horizontal"
android:paddingStart="@dimen/notification_padding"
android:background="@color/notification_header_background_color"
android:elevation="@dimen/notification_elevation">
<TextView
android:id="@+id/notification_count"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="start|center_vertical"
android:paddingEnd="@dimen/notification_header_padding_after_count"
android:textSize="@dimen/notification_main_text_size"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/notification_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="start|center_vertical"
android:textSize="@dimen/notification_main_text_size"
android:textColor="?android:attr/textColorSecondary" />
</com.android.launcher3.notification.NotificationHeaderView>
<include layout="@layout/notification_main"
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="@dimen/notification_main_height" />
android:layout_height="@dimen/notification_main_height"
android:layout_below="@id/header" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="@dimen/popup_item_divider_height"
android:background="@color/divider_color"
android:layout_below="@id/main_view"/>
<include layout="@layout/notification_footer"
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="@dimen/notification_footer_height"
android:layout_below="@id/main_view" />
android:layout_below="@id/divider" />
</RelativeLayout>
+12 -8
View File
@@ -18,25 +18,29 @@
<com.android.launcher3.notification.NotificationFooterLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
android:elevation="@dimen/notification_elevation"
android:clipChildren="false" >
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="@dimen/popup_item_divider_height"/>
android:clipChildren="false"
android:layout_gravity="center_vertical"
android:background="@color/notification_background_color">
<LinearLayout
android:id="@+id/icon_row"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="end"
android:gravity="end|center_vertical"
android:padding="@dimen/notification_footer_icon_row_padding"
android:clipToPadding="false"
android:clipChildren="false"/>
<View
android:id="@+id/overflow"
android:layout_width="@dimen/horizontal_ellipsis_size"
android:layout_height="@dimen/horizontal_ellipsis_size"
android:background="@drawable/horizontal_ellipsis"
android:layout_marginStart="@dimen/horizontal_ellipsis_offset"
android:layout_gravity="start|center_vertical" />
</com.android.launcher3.notification.NotificationFooterLayout>
+19 -16
View File
@@ -19,43 +19,46 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:focusable="true"
android:padding="@dimen/notification_padding"
android:elevation="@dimen/notification_elevation" >
<LinearLayout
android:id="@+id/text_and_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="1"
android:gravity="center_vertical">
android:gravity="center_vertical"
android:background="@color/notification_background_color"
android:paddingStart="@dimen/notification_padding"
android:paddingEnd="@dimen/notification_main_text_padding_end">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="viewStart"
android:fontFamily="sans-serif"
android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:textSize="@dimen/notification_main_text_size"
android:textColor="?android:attr/textColorPrimary"
android:lines="1"
android:ellipsize="end" />
<TextView
android:id="@+id/text"
android:paddingEnd="4dp"
android:textSize="12sp"
android:textAlignment="viewStart"
android:fontFamily="sans-serif"
android:textColor="?android:attr/textColorTertiary"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:textSize="@dimen/notification_main_text_size"
android:textColor="?android:attr/textColorSecondary"
android:lines="1"
android:ellipsize="end" />
</LinearLayout>
<View
android:id="@+id/popup_item_icon"
android:layout_width="@dimen/notification_icon_size"
android:layout_height="@dimen/notification_icon_size"
android:layout_weight="0"
android:layout_gravity="center_vertical" />
android:layout_marginEnd="@dimen/notification_padding"
android:layout_gravity="center_vertical|end" />
</com.android.launcher3.notification.NotificationMainView>
+4
View File
@@ -36,4 +36,8 @@
<color name="spring_loaded_highlighted_panel_border_color">#FFF</color>
<color name="notification_icon_default_color">#757575</color> <!-- Gray 600 -->
<color name="notification_header_background_color">#F5F5F5</color> <!-- Gray 100 -->
<color name="notification_background_color">#FFF</color>
<color name="notification_color_beneath">#E0E0E0</color> <!-- Gray 300 -->
<color name="divider_color">@color/notification_color_beneath</color>
</resources>
+13 -4
View File
@@ -178,17 +178,26 @@
<dimen name="badge_text_size">12dp</dimen>
<dimen name="badge_small_padding">0dp</dimen>
<dimen name="badge_large_padding">3dp</dimen>
<dimen name="notification_icon_size">28dp</dimen>
<dimen name="notification_footer_icon_size">24dp</dimen>
<dimen name="notification_icon_size">24dp</dimen>
<dimen name="notification_footer_icon_size">18dp</dimen>
<!-- Notifications -->
<dimen name="bg_round_rect_radius">12dp</dimen>
<dimen name="notification_padding">12dp</dimen>
<!-- (icon_size - footer_icon_size) / 2 -->
<dimen name="notification_footer_icon_row_padding">2dp</dimen>
<!-- notification_padding + (icon_size - footer_icon_size) / 2 -->
<dimen name="notification_footer_icon_row_padding">15dp</dimen>
<dimen name="notification_header_padding_after_count">8dp</dimen>
<dimen name="notification_header_height">32dp</dimen>
<dimen name="notification_main_height">60dp</dimen>
<dimen name="notification_footer_height">@dimen/bg_popup_item_height</dimen>
<dimen name="notification_header_text_size">12dp</dimen>
<dimen name="notification_main_text_size">14dp</dimen>
<!-- notification_icon_size + notification+padding + padding we want between icon and text -->
<dimen name="notification_main_text_padding_end">40dp</dimen>
<dimen name="notification_elevation">2dp</dimen>
<dimen name="horizontal_ellipsis_size">18dp</dimen>
<!-- arrow_horizontal_offset - (ellipsis_size - arrow_width) / 2 -->
<dimen name="horizontal_ellipsis_offset">15dp</dimen>
<dimen name="popup_item_divider_height">0.5dp</dimen>
<dimen name="swipe_helper_falsing_threshold">70dp</dimen>
+4 -1
View File
@@ -72,7 +72,10 @@
The text must fit in the size of a small icon [CHAR_LIMIT=3] -->
<string name="deep_notifications_overflow" translatable="false">+%1$d</string>
<!-- Text to display as the header above notifications. [CHAR_LIMIT=30] -->
<string name="notifications_header" translatable="false">Notifications</string>
<plurals name="notifications_header" translatable="false">
<item quantity="one">Notification</item>
<item quantity="other">Notifications</item>
</plurals>
<!-- Drag and drop -->
<skip />
@@ -42,9 +42,9 @@ import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.graphics.HolographicOutlineHelper;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.popup.PopupContainerWithArrow;
import java.text.NumberFormat;
@@ -502,15 +502,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
if (mIcon instanceof FastBitmapDrawable) {
BadgeInfo badgeInfo = mLauncher.getPopupDataProvider().getBadgeInfoForItem(itemInfo);
BadgeRenderer badgeRenderer = mLauncher.getDeviceProfile().mBadgeRenderer;
PopupContainerWithArrow popup = PopupContainerWithArrow.getOpen(mLauncher);
if (popup != null) {
popup.updateNotificationHeader(badgeInfo, itemInfo);
}
((FastBitmapDrawable) mIcon).applyIconBadge(badgeInfo, badgeRenderer, animate);
}
}
public IconPalette getIconPalette() {
return mIcon instanceof FastBitmapDrawable ? ((FastBitmapDrawable) mIcon).getIconPalette()
: null;
}
/**
* Sets the icon for this view based on the layout direction.
*/
@@ -167,7 +167,7 @@ public class FastBitmapDrawable extends Drawable {
}
}
public IconPalette getIconPalette() {
protected IconPalette getIconPalette() {
if (mIconPalette == null) {
mIconPalette = IconPalette.fromDominantColor(Utilities
.findDominantColorByHue(mBitmap, 20));
@@ -21,14 +21,15 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
@@ -36,7 +37,6 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.anim.PropertyResetListener;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.popup.PopupContainerWithArrow;
import java.util.ArrayList;
@@ -44,16 +44,16 @@ import java.util.Iterator;
import java.util.List;
/**
* A {@link LinearLayout} that contains only icons of notifications.
* If there are more than {@link #MAX_FOOTER_NOTIFICATIONS} icons, we add a "+x" overflow.
* A {@link FrameLayout} that contains only icons of notifications.
* If there are more than {@link #MAX_FOOTER_NOTIFICATIONS} icons, we add a "..." overflow.
*/
public class NotificationFooterLayout extends LinearLayout {
public class NotificationFooterLayout extends FrameLayout {
public interface IconAnimationEndListener {
void onIconAnimationEnd(NotificationInfo animatedNotification);
}
private static final int MAX_FOOTER_NOTIFICATIONS = 4;
private static final int MAX_FOOTER_NOTIFICATIONS = 5;
private static final Rect sTempRect = new Rect();
@@ -61,11 +61,10 @@ public class NotificationFooterLayout extends LinearLayout {
private final List<NotificationInfo> mOverflowNotifications = new ArrayList<>();
private final boolean mRtl;
LinearLayout.LayoutParams mIconLayoutParams;
FrameLayout.LayoutParams mIconLayoutParams;
private View mOverflowEllipsis;
private LinearLayout mIconRow;
private final ColorDrawable mBackgroundColor;
private int mTextColor;
private TextView mOverflowView;
private int mBackgroundColor;
public NotificationFooterLayout(Context context) {
this(context, null, 0);
@@ -78,33 +77,29 @@ public class NotificationFooterLayout extends LinearLayout {
public NotificationFooterLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mRtl = Utilities.isRtl(getResources());
Resources res = getResources();
mRtl = Utilities.isRtl(res);
int size = getResources().getDimensionPixelSize(
R.dimen.notification_footer_icon_size);
int padding = getResources().getDimensionPixelSize(R.dimen.notification_padding);
mIconLayoutParams = new LayoutParams(size, size);
mIconLayoutParams.setMarginEnd(padding);
int iconSize = res.getDimensionPixelSize(R.dimen.notification_footer_icon_size);
mIconLayoutParams = new LayoutParams(iconSize, iconSize);
mIconLayoutParams.gravity = Gravity.CENTER_VERTICAL;
mBackgroundColor = new ColorDrawable();
setBackground(mBackgroundColor);
// Compute margin start for each icon such that the icons between the first one
// and the ellipsis are evenly spaced out.
int paddingEnd = res.getDimensionPixelSize(R.dimen.notification_footer_icon_row_padding);
int ellipsisSpace = res.getDimensionPixelSize(R.dimen.horizontal_ellipsis_offset)
+ res.getDimensionPixelSize(R.dimen.horizontal_ellipsis_size);
int footerWidth = res.getDimensionPixelSize(R.dimen.bg_popup_item_width);
int availableIconRowSpace = footerWidth - paddingEnd - ellipsisSpace
- iconSize * MAX_FOOTER_NOTIFICATIONS;
mIconLayoutParams.setMarginStart(availableIconRowSpace / MAX_FOOTER_NOTIFICATIONS);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mOverflowEllipsis = findViewById(R.id.overflow);
mIconRow = (LinearLayout) findViewById(R.id.icon_row);
}
public void applyColors(IconPalette iconPalette) {
mBackgroundColor.setColor(iconPalette.backgroundColor);
findViewById(R.id.divider).setBackgroundColor(iconPalette.secondaryColor);
mTextColor = iconPalette.textColor;
}
public int getBackgroundColor() {
return mBackgroundColor.getColor();
mBackgroundColor = ((ColorDrawable) getBackground()).getColor();
}
/**
@@ -128,35 +123,26 @@ public class NotificationFooterLayout extends LinearLayout {
for (int i = 0; i < mNotifications.size(); i++) {
NotificationInfo info = mNotifications.get(i);
addNotificationIconForInfo(info, false /* fromOverflow */);
}
if (!mOverflowNotifications.isEmpty()) {
mOverflowView = new TextView(getContext());
mOverflowView.setTextColor(mTextColor);
updateOverflowText();
mIconRow.addView(mOverflowView, 0, mIconLayoutParams);
addNotificationIconForInfo(info);
}
updateOverflowEllipsisVisibility();
}
private void addNotificationIconForInfo(NotificationInfo info, boolean fromOverflow) {
private void updateOverflowEllipsisVisibility() {
mOverflowEllipsis.setVisibility(mOverflowNotifications.isEmpty() ? GONE : VISIBLE);
}
/**
* Creates an icon for the given NotificationInfo, and adds it to the icon row.
* @return the icon view that was added
*/
private View addNotificationIconForInfo(NotificationInfo info) {
View icon = new View(getContext());
icon.setBackground(info.getIconForBackground(getContext(), getBackgroundColor()));
icon.setBackground(info.getIconForBackground(getContext(), mBackgroundColor));
icon.setOnClickListener(info);
int addIndex = 0;
if (fromOverflow) {
// Add the notification before the overflow view.
addIndex = 1;
icon.setAlpha(0);
icon.animate().alpha(1);
}
icon.setTag(info);
mIconRow.addView(icon, addIndex, mIconLayoutParams);
}
private void updateOverflowText() {
mOverflowView.setText(getResources().getString(R.string.deep_notifications_overflow,
mOverflowNotifications.size()));
mIconRow.addView(icon, 0, mIconLayoutParams);
return icon;
}
public void animateFirstNotificationTo(Rect toBounds,
@@ -180,16 +166,22 @@ public class NotificationFooterLayout extends LinearLayout {
animation.play(moveAndScaleIcon);
// Shift all notifications (not the overflow) over to fill the gap.
int gapWidth = mIconLayoutParams.width + mIconLayoutParams.getMarginEnd();
int gapWidth = mIconLayoutParams.width + mIconLayoutParams.getMarginStart();
if (mRtl) {
gapWidth = -gapWidth;
}
int numIcons = mIconRow.getChildCount() - 1;
// We have to set the translation X to 0 when the new main notification
if (!mOverflowNotifications.isEmpty()) {
NotificationInfo notification = mOverflowNotifications.remove(0);
mNotifications.add(notification);
View iconFromOverflow = addNotificationIconForInfo(notification);
animation.play(ObjectAnimator.ofFloat(iconFromOverflow, ALPHA, 0, 1));
}
int numIcons = mIconRow.getChildCount() - 1; // All children besides the one leaving.
// We have to reset the translation X to 0 when the new main notification
// is removed from the footer.
PropertyResetListener<View, Float> propertyResetListener
= new PropertyResetListener<>(TRANSLATION_X, 0f);
for (int i = mOverflowNotifications.isEmpty() ? 0 : 1; i < numIcons; i++) {
for (int i = 0; i < numIcons; i++) {
final View child = mIconRow.getChildAt(i);
Animator shiftChild = ObjectAnimator.ofFloat(child, TRANSLATION_X, gapWidth);
shiftChild.addListener(propertyResetListener);
@@ -201,19 +193,7 @@ public class NotificationFooterLayout extends LinearLayout {
private void removeViewFromIconRow(View child) {
mIconRow.removeView(child);
mNotifications.remove((NotificationInfo) child.getTag());
if (!mOverflowNotifications.isEmpty()) {
NotificationInfo notification = mOverflowNotifications.remove(0);
mNotifications.add(notification);
addNotificationIconForInfo(notification, true /* fromOverflow */);
}
if (mOverflowView != null) {
if (mOverflowNotifications.isEmpty()) {
mIconRow.removeView(mOverflowView);
mOverflowView = null;
} else {
updateOverflowText();
}
}
updateOverflowEllipsisVisibility();
if (mIconRow.getChildCount() == 0) {
// There are no more icons in the footer, so hide it.
PopupContainerWithArrow popup = PopupContainerWithArrow.getOpen(
@@ -240,16 +220,11 @@ public class NotificationFooterLayout extends LinearLayout {
overflowIterator.remove();
}
}
TextView overflowView = null;
for (int i = mIconRow.getChildCount() - 1; i >= 0; i--) {
View child = mIconRow.getChildAt(i);
if (child instanceof TextView) {
overflowView = (TextView) child;
} else {
NotificationInfo childInfo = (NotificationInfo) child.getTag();
if (!notifications.contains(childInfo.notificationKey)) {
removeViewFromIconRow(child);
}
NotificationInfo childInfo = (NotificationInfo) child.getTag();
if (!notifications.contains(childInfo.notificationKey)) {
removeViewFromIconRow(child);
}
}
}
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2017 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.
*/
package com.android.launcher3.notification;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.launcher3.R;
/**
* A {@link LinearLayout} that contains two text views: one for the notification count
* and one just to say "Notification" or "Notifications"
*/
public class NotificationHeaderView extends LinearLayout {
private TextView mNotificationCount;
private TextView mNotificationText;
public NotificationHeaderView(Context context) {
this(context, null, 0);
}
public NotificationHeaderView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NotificationHeaderView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mNotificationCount = (TextView) findViewById(R.id.notification_count);
mNotificationText = (TextView) findViewById(R.id.notification_text);
}
public void update(int notificationCount) {
mNotificationCount.setText(String.valueOf(notificationCount));
mNotificationText.setText(getResources().getQuantityString(
R.plurals.notifications_header, notificationCount));
}
}
@@ -19,7 +19,6 @@ package com.android.launcher3.notification;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -30,7 +29,6 @@ import android.widget.FrameLayout;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.anim.PillHeightRevealOutlineProvider;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.logging.UserEventDispatcher.LogContainerProvider;
import com.android.launcher3.popup.PopupItemView;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -47,7 +45,7 @@ public class NotificationItemView extends PopupItemView implements LogContainerP
private static final Rect sTempRect = new Rect();
private View mDivider;
private NotificationHeaderView mHeader;
private NotificationMainView mMainView;
private NotificationFooterLayout mFooter;
private SwipeHelper mSwipeHelper;
@@ -68,7 +66,7 @@ public class NotificationItemView extends PopupItemView implements LogContainerP
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mDivider = findViewById(R.id.divider);
mHeader = (NotificationHeaderView) findViewById(R.id.header);
mMainView = (NotificationMainView) findViewById(R.id.main_view);
mFooter = (NotificationFooterLayout) findViewById(R.id.footer);
mSwipeHelper = new SwipeHelper(SwipeHelper.X, mMainView, getContext());
@@ -95,6 +93,10 @@ public class NotificationItemView extends PopupItemView implements LogContainerP
return heightAnimator;
}
public void updateHeader(int notificationCount) {
mHeader.update(notificationCount);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mMainView.getNotificationInfo() == null) {
@@ -114,13 +116,6 @@ public class NotificationItemView extends PopupItemView implements LogContainerP
return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev);
}
@Override
protected ColorStateList getAttachedArrowColor() {
// This NotificationView itself has a different color that is only
// revealed when dismissing notifications.
return ColorStateList.valueOf(mFooter.getBackgroundColor());
}
public void applyNotificationInfos(final List<NotificationInfo> notificationInfos) {
if (notificationInfos.isEmpty()) {
return;
@@ -135,13 +130,6 @@ public class NotificationItemView extends PopupItemView implements LogContainerP
mFooter.commitNotificationInfos();
}
public void applyColors(IconPalette iconPalette) {
setBackgroundTintList(ColorStateList.valueOf(iconPalette.secondaryColor));
mDivider.setBackgroundColor(iconPalette.secondaryColor);
mMainView.applyColors(iconPalette);
mFooter.applyColors(iconPalette);
}
public void trimNotifications(final List<String> notificationKeys) {
boolean dismissedMainNotification = !notificationKeys.contains(
mMainView.getNotificationInfo().notificationKey);
@@ -16,11 +16,7 @@
package com.android.launcher3.notification;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.ColorDrawable;
@@ -28,28 +24,27 @@ import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.Themes;
/**
* A {@link LinearLayout} that contains a single notification, e.g. icon + title + text.
* A {@link android.widget.FrameLayout} that contains a single notification,
* e.g. icon + title + text.
*/
public class NotificationMainView extends LinearLayout implements SwipeHelper.Callback {
private final ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();
public class NotificationMainView extends FrameLayout implements SwipeHelper.Callback {
private NotificationInfo mNotificationInfo;
private ViewGroup mTextAndBackground;
private int mBackgroundColor;
private TextView mTitleView;
private TextView mTextView;
private IconPalette mIconPalette;
private ColorDrawable mColorBackground;
public NotificationMainView(Context context) {
this(context, null, 0);
@@ -67,16 +62,15 @@ public class NotificationMainView extends LinearLayout implements SwipeHelper.Ca
protected void onFinishInflate() {
super.onFinishInflate();
mTitleView = (TextView) findViewById(R.id.title);
mTextView = (TextView) findViewById(R.id.text);
}
public void applyColors(IconPalette iconPalette) {
mColorBackground = new ColorDrawable(iconPalette.backgroundColor);
RippleDrawable rippleDrawable = new RippleDrawable(ColorStateList.valueOf(
iconPalette.secondaryColor), mColorBackground, null);
setBackground(rippleDrawable);
mIconPalette = iconPalette;
mTextAndBackground = (ViewGroup) findViewById(R.id.text_and_background);
ColorDrawable colorBackground = (ColorDrawable) mTextAndBackground.getBackground();
mBackgroundColor = colorBackground.getColor();
RippleDrawable rippleBackground = new RippleDrawable(ColorStateList.valueOf(
Themes.getAttrColor(getContext(), android.R.attr.colorControlHighlight)),
colorBackground, null);
mTextAndBackground.setBackground(rippleBackground);
mTitleView = (TextView) mTextAndBackground.findViewById(R.id.title);
mTextView = (TextView) mTextAndBackground.findViewById(R.id.text);
}
public void applyNotificationInfo(NotificationInfo mainNotification, View iconView) {
@@ -88,30 +82,18 @@ public class NotificationMainView extends LinearLayout implements SwipeHelper.Ca
*/
public void applyNotificationInfo(NotificationInfo mainNotification, View iconView,
boolean animate) {
if (animate) {
mTitleView.setAlpha(0);
mTextView.setAlpha(0);
mColorBackground.setColor(mIconPalette.secondaryColor);
}
mNotificationInfo = mainNotification;
mTitleView.setText(mNotificationInfo.title);
mTextView.setText(mNotificationInfo.text);
iconView.setBackground(mNotificationInfo.getIconForBackground(
getContext(), mIconPalette.backgroundColor));
iconView.setBackground(mNotificationInfo.getIconForBackground(getContext(),
mBackgroundColor));
setOnClickListener(mNotificationInfo);
setTranslationX(0);
// Add a dummy ItemInfo so that logging populates the correct container and item types
// instead of DEFAULT_CONTAINERTYPE and DEFAULT_ITEMTYPE, respectively.
setTag(new ItemInfo());
if (animate) {
AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
Animator textFade = ObjectAnimator.ofFloat(mTextView, View.ALPHA, 1);
Animator titleFade = ObjectAnimator.ofFloat(mTitleView, View.ALPHA, 1);
ValueAnimator colorChange = ObjectAnimator.ofObject(mColorBackground, "color",
mArgbEvaluator, mIconPalette.secondaryColor, mIconPalette.backgroundColor);
animation.playTogether(textFade, titleFade, colorChange);
animation.setDuration(150);
animation.start();
ObjectAnimator.ofFloat(mTextAndBackground, ALPHA, 0, 1).setDuration(150).start();
}
}
@@ -63,14 +63,12 @@ import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.graphics.TriangleShape;
import com.android.launcher3.notification.NotificationItemView;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutsItemView;
import com.android.launcher3.util.PackageUserKey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -184,20 +182,20 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra
orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
}
ItemInfo originalItemInfo = (ItemInfo) originalIcon.getTag();
List<DeepShortcutView> shortcutViews = mShortcutsItemView == null
? Collections.EMPTY_LIST
: mShortcutsItemView.getDeepShortcutViews(reverseOrder);
if (mNotificationItemView != null) {
IconPalette iconPalette = originalIcon.getIconPalette();
mNotificationItemView.applyColors(iconPalette);
BadgeInfo badgeInfo = mLauncher.getPopupDataProvider()
.getBadgeInfoForItem(originalItemInfo);
updateNotificationHeader(badgeInfo);
}
// Add the arrow.
mArrow = addArrowView(arrowHorizontalOffset, arrowVerticalOffset, arrowWidth, arrowHeight);
mArrow.setPivotX(arrowWidth / 2);
mArrow.setPivotY(mIsAboveIcon ? 0 : arrowHeight);
PopupItemView firstItem = getItemViewAt(mIsAboveIcon ? getItemCount() - 1 : 0);
mArrow.setBackgroundTintList(firstItem.getAttachedArrowColor());
animateOpen();
@@ -208,7 +206,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra
// Load the shortcuts on a background thread and update the container as it animates.
final Looper workerLooper = LauncherModel.getWorkerLooper();
new Handler(workerLooper).postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
mLauncher, (ItemInfo) originalIcon.getTag(), new Handler(Looper.getMainLooper()),
mLauncher, originalItemInfo, new Handler(Looper.getMainLooper()),
this, shortcutIds, shortcutViews, notificationKeys, mNotificationItemView));
}
@@ -540,6 +538,24 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra
return true;
}
/**
* Updates the notification header to reflect the badge info. Since this can be called
* for any badge info (not necessarily the one associated with this app), we first
* check that the ItemInfo matches the one of this popup.
*/
public void updateNotificationHeader(BadgeInfo badgeInfo, ItemInfo originalItemInfo) {
if (originalItemInfo != mOriginalIcon.getTag()) {
return;
}
updateNotificationHeader(badgeInfo);
}
private void updateNotificationHeader(BadgeInfo badgeInfo) {
if (mNotificationItemView != null && badgeInfo != null) {
mNotificationItemView.updateHeader(badgeInfo.getNotificationCount());
}
}
public void trimNotifications(Map<PackageUserKey, BadgeInfo> updatedBadges) {
if (mNotificationItemView == null) {
return;
@@ -576,8 +592,6 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra
close(false);
return;
}
View firstItem = getItemViewAt(mIsAboveIcon ? getItemCount() - 1 : 0);
mArrow.setBackgroundTintList(firstItem.getBackgroundTintList());
}
});
removeNotification.play(fade);
@@ -20,7 +20,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
@@ -109,10 +108,6 @@ public abstract class PopupItemView extends FrameLayout
canvas.restoreToCount(saveCount);
}
protected ColorStateList getAttachedArrowColor() {
return getBackgroundTintList();
}
/**
* Creates an animator to play when the shortcut container is being opened.
*/