1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.systemui.statusbar.notification;
18 
19 import android.app.Notification;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.util.TypedValue;
23 import android.view.ContextThemeWrapper;
24 import android.view.LayoutInflater;
25 import android.view.ViewGroup;
26 import android.widget.TextView;
27 
28 import com.android.systemui.R;
29 
30 /**
31  * A class managing hybrid groups that include {@link HybridNotificationView} and the notification
32  * group overflow.
33  */
34 public class HybridGroupManager {
35 
36     private final Context mContext;
37     private final NotificationDozeHelper mDozer;
38     private final ViewGroup mParent;
39 
40     private float mOverflowNumberSizeDark;
41     private int mOverflowNumberPaddingDark;
42     private float mOverflowNumberSize;
43     private int mOverflowNumberPadding;
44 
45     private int mOverflowNumberColor;
46     private int mOverflowNumberColorDark;
47     private float mDarkAmount = 0f;
48 
HybridGroupManager(Context ctx, ViewGroup parent)49     public HybridGroupManager(Context ctx, ViewGroup parent) {
50         mContext = ctx;
51         mParent = parent;
52         mDozer = new NotificationDozeHelper();
53         initDimens();
54     }
55 
initDimens()56     public void initDimens() {
57         Resources res = mContext.getResources();
58         mOverflowNumberSize = res.getDimensionPixelSize(
59                 R.dimen.group_overflow_number_size);
60         mOverflowNumberSizeDark = res.getDimensionPixelSize(
61                 R.dimen.group_overflow_number_size_dark);
62         mOverflowNumberPadding = res.getDimensionPixelSize(
63                 R.dimen.group_overflow_number_padding);
64         mOverflowNumberPaddingDark = mOverflowNumberPadding + res.getDimensionPixelSize(
65                 R.dimen.group_overflow_number_extra_padding_dark);
66     }
67 
inflateHybridViewWithStyle(int style)68     private HybridNotificationView inflateHybridViewWithStyle(int style) {
69         LayoutInflater inflater = new ContextThemeWrapper(mContext, style)
70                 .getSystemService(LayoutInflater.class);
71         HybridNotificationView hybrid = (HybridNotificationView) inflater.inflate(
72                 R.layout.hybrid_notification, mParent, false);
73         mParent.addView(hybrid);
74         return hybrid;
75     }
76 
inflateOverflowNumber()77     private TextView inflateOverflowNumber() {
78         LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
79         TextView numberView = (TextView) inflater.inflate(
80                 R.layout.hybrid_overflow_number, mParent, false);
81         mParent.addView(numberView);
82         updateOverFlowNumberColor(numberView);
83         return numberView;
84     }
85 
updateOverFlowNumberColor(TextView numberView)86     private void updateOverFlowNumberColor(TextView numberView) {
87         numberView.setTextColor(NotificationUtils.interpolateColors(
88                 mOverflowNumberColor, mOverflowNumberColorDark, mDarkAmount));
89     }
90 
setOverflowNumberColor(TextView numberView, int colorRegular, int colorDark)91     public void setOverflowNumberColor(TextView numberView, int colorRegular, int colorDark) {
92         mOverflowNumberColor = colorRegular;
93         mOverflowNumberColorDark = colorDark;
94         if (numberView != null) {
95             updateOverFlowNumberColor(numberView);
96         }
97     }
98 
bindFromNotification(HybridNotificationView reusableView, Notification notification)99     public HybridNotificationView bindFromNotification(HybridNotificationView reusableView,
100             Notification notification) {
101         return bindFromNotificationWithStyle(reusableView, notification,
102                 R.style.HybridNotification);
103     }
104 
bindAmbientFromNotification(HybridNotificationView reusableView, Notification notification)105     public HybridNotificationView bindAmbientFromNotification(HybridNotificationView reusableView,
106             Notification notification) {
107         return bindFromNotificationWithStyle(reusableView, notification,
108                 R.style.HybridNotification_Ambient);
109     }
110 
bindFromNotificationWithStyle( HybridNotificationView reusableView, Notification notification, int style)111     private HybridNotificationView bindFromNotificationWithStyle(
112             HybridNotificationView reusableView, Notification notification, int style) {
113         if (reusableView == null) {
114             reusableView = inflateHybridViewWithStyle(style);
115         }
116         CharSequence titleText = resolveTitle(notification);
117         CharSequence contentText = resolveText(notification);
118         reusableView.bind(titleText, contentText);
119         return reusableView;
120     }
121 
resolveText(Notification notification)122     private CharSequence resolveText(Notification notification) {
123         CharSequence contentText = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
124         if (contentText == null) {
125             contentText = notification.extras.getCharSequence(Notification.EXTRA_BIG_TEXT);
126         }
127         return contentText;
128     }
129 
resolveTitle(Notification notification)130     private CharSequence resolveTitle(Notification notification) {
131         CharSequence titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
132         if (titleText == null) {
133             titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE_BIG);
134         }
135         return titleText;
136     }
137 
bindOverflowNumber(TextView reusableView, int number)138     public TextView bindOverflowNumber(TextView reusableView, int number) {
139         if (reusableView == null) {
140             reusableView = inflateOverflowNumber();
141         }
142         String text = mContext.getResources().getString(
143                 R.string.notification_group_overflow_indicator, number);
144         if (!text.equals(reusableView.getText())) {
145             reusableView.setText(text);
146         }
147         String contentDescription = String.format(mContext.getResources().getQuantityString(
148                 R.plurals.notification_group_overflow_description, number), number);
149 
150         reusableView.setContentDescription(contentDescription);
151         return reusableView;
152     }
153 
bindOverflowNumberAmbient(TextView titleView, Notification notification, int number)154     public TextView bindOverflowNumberAmbient(TextView titleView, Notification notification,
155             int number) {
156         String text = mContext.getResources().getString(
157                 R.string.notification_group_overflow_indicator_ambient,
158                 resolveTitle(notification), number);
159         if (!text.equals(titleView.getText())) {
160             titleView.setText(text);
161         }
162         return titleView;
163     }
164 
setOverflowNumberDark(TextView view, boolean dark, boolean fade, long delay)165     public void setOverflowNumberDark(TextView view, boolean dark, boolean fade, long delay) {
166         mDozer.setIntensityDark((f)->{
167             mDarkAmount = f;
168             updateOverFlowNumberColor(view);
169         }, dark, fade, delay, view);
170         view.setTextSize(TypedValue.COMPLEX_UNIT_PX,
171                 dark ? mOverflowNumberSizeDark : mOverflowNumberSize);
172         int paddingEnd = dark ? mOverflowNumberPaddingDark : mOverflowNumberPadding;
173         view.setPaddingRelative(view.getPaddingStart(), view.getPaddingTop(), paddingEnd,
174                 view.getPaddingBottom());
175     }
176 }
177