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 final float mOverflowNumberSizeDark;
41     private final int mOverflowNumberPaddingDark;
42     private final float mOverflowNumberSize;
43     private final 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 
54         Resources res = mContext.getResources();
55         mOverflowNumberSize = res.getDimensionPixelSize(
56                 R.dimen.group_overflow_number_size);
57         mOverflowNumberSizeDark = res.getDimensionPixelSize(
58                 R.dimen.group_overflow_number_size_dark);
59         mOverflowNumberPadding = res.getDimensionPixelSize(
60                 R.dimen.group_overflow_number_padding);
61         mOverflowNumberPaddingDark = mOverflowNumberPadding + res.getDimensionPixelSize(
62                 R.dimen.group_overflow_number_extra_padding_dark);
63     }
64 
inflateHybridViewWithStyle(int style)65     private HybridNotificationView inflateHybridViewWithStyle(int style) {
66         LayoutInflater inflater = new ContextThemeWrapper(mContext, style)
67                 .getSystemService(LayoutInflater.class);
68         HybridNotificationView hybrid = (HybridNotificationView) inflater.inflate(
69                 R.layout.hybrid_notification, mParent, false);
70         mParent.addView(hybrid);
71         return hybrid;
72     }
73 
inflateOverflowNumber()74     private TextView inflateOverflowNumber() {
75         LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
76         TextView numberView = (TextView) inflater.inflate(
77                 R.layout.hybrid_overflow_number, mParent, false);
78         mParent.addView(numberView);
79         updateOverFlowNumberColor(numberView);
80         return numberView;
81     }
82 
updateOverFlowNumberColor(TextView numberView)83     private void updateOverFlowNumberColor(TextView numberView) {
84         numberView.setTextColor(NotificationUtils.interpolateColors(
85                 mOverflowNumberColor, mOverflowNumberColorDark, mDarkAmount));
86     }
87 
setOverflowNumberColor(TextView numberView, int colorRegular, int colorDark)88     public void setOverflowNumberColor(TextView numberView, int colorRegular, int colorDark) {
89         mOverflowNumberColor = colorRegular;
90         mOverflowNumberColorDark = colorDark;
91         if (numberView != null) {
92             updateOverFlowNumberColor(numberView);
93         }
94     }
95 
bindFromNotification(HybridNotificationView reusableView, Notification notification)96     public HybridNotificationView bindFromNotification(HybridNotificationView reusableView,
97             Notification notification) {
98         return bindFromNotificationWithStyle(reusableView, notification,
99                 R.style.HybridNotification);
100     }
101 
bindAmbientFromNotification(HybridNotificationView reusableView, Notification notification)102     public HybridNotificationView bindAmbientFromNotification(HybridNotificationView reusableView,
103             Notification notification) {
104         return bindFromNotificationWithStyle(reusableView, notification,
105                 R.style.HybridNotification_Ambient);
106     }
107 
bindFromNotificationWithStyle( HybridNotificationView reusableView, Notification notification, int style)108     private HybridNotificationView bindFromNotificationWithStyle(
109             HybridNotificationView reusableView, Notification notification, int style) {
110         if (reusableView == null) {
111             reusableView = inflateHybridViewWithStyle(style);
112         }
113         CharSequence titleText = resolveTitle(notification);
114         CharSequence contentText = resolveText(notification);
115         reusableView.bind(titleText, contentText);
116         return reusableView;
117     }
118 
resolveText(Notification notification)119     private CharSequence resolveText(Notification notification) {
120         CharSequence contentText = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
121         if (contentText == null) {
122             contentText = notification.extras.getCharSequence(Notification.EXTRA_BIG_TEXT);
123         }
124         return contentText;
125     }
126 
resolveTitle(Notification notification)127     private CharSequence resolveTitle(Notification notification) {
128         CharSequence titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
129         if (titleText == null) {
130             titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE_BIG);
131         }
132         return titleText;
133     }
134 
bindOverflowNumber(TextView reusableView, int number)135     public TextView bindOverflowNumber(TextView reusableView, int number) {
136         if (reusableView == null) {
137             reusableView = inflateOverflowNumber();
138         }
139         String text = mContext.getResources().getString(
140                 R.string.notification_group_overflow_indicator, number);
141         if (!text.equals(reusableView.getText())) {
142             reusableView.setText(text);
143         }
144         String contentDescription = String.format(mContext.getResources().getQuantityString(
145                 R.plurals.notification_group_overflow_description, number), number);
146 
147         reusableView.setContentDescription(contentDescription);
148         return reusableView;
149     }
150 
setOverflowNumberDark(TextView view, boolean dark, boolean fade, long delay)151     public void setOverflowNumberDark(TextView view, boolean dark, boolean fade, long delay) {
152         mDozer.setIntensityDark((f)->{
153             mDarkAmount = f;
154             updateOverFlowNumberColor(view);
155         }, dark, fade, delay);
156         view.setTextSize(TypedValue.COMPLEX_UNIT_PX,
157                 dark ? mOverflowNumberSizeDark : mOverflowNumberSize);
158         int paddingEnd = dark ? mOverflowNumberPaddingDark : mOverflowNumberPadding;
159         view.setPaddingRelative(view.getPaddingStart(), view.getPaddingTop(), paddingEnd,
160                 view.getPaddingBottom());
161     }
162 }
163