1 /*
2  * Copyright (C) 2020 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.row;
18 
19 import android.annotation.Nullable;
20 import android.content.Context;
21 import android.graphics.drawable.Icon;
22 import android.text.TextUtils;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.widget.FrameLayout;
26 import android.widget.ImageView;
27 import android.widget.TextView;
28 
29 import com.android.internal.widget.ConversationLayout;
30 import com.android.systemui.R;
31 import com.android.systemui.statusbar.notification.NotificationFadeAware;
32 
33 /**
34  * A hybrid view which may contain information about one ore more conversations.
35  */
36 public class HybridConversationNotificationView extends HybridNotificationView {
37 
38     private ImageView mConversationIconView;
39     private TextView mConversationSenderName;
40     private View mConversationFacePile;
41     private int mSingleAvatarSize;
42     private int mFacePileSize;
43     private int mFacePileAvatarSize;
44     private int mFacePileProtectionWidth;
45 
HybridConversationNotificationView(Context context)46     public HybridConversationNotificationView(Context context) {
47         this(context, null);
48     }
49 
HybridConversationNotificationView(Context context, @Nullable AttributeSet attrs)50     public HybridConversationNotificationView(Context context, @Nullable AttributeSet attrs) {
51         this(context, attrs, 0);
52     }
53 
HybridConversationNotificationView( Context context, @Nullable AttributeSet attrs, int defStyleAttr)54     public HybridConversationNotificationView(
55             Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
56         this(context, attrs, defStyleAttr, 0);
57     }
58 
HybridConversationNotificationView( Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)59     public HybridConversationNotificationView(
60             Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
61         super(context, attrs, defStyleAttr, defStyleRes);
62     }
63 
64     @Override
onFinishInflate()65     protected void onFinishInflate() {
66         super.onFinishInflate();
67         mConversationIconView = requireViewById(com.android.internal.R.id.conversation_icon);
68         mConversationFacePile = requireViewById(com.android.internal.R.id.conversation_face_pile);
69         mConversationSenderName = requireViewById(R.id.conversation_notification_sender);
70         mFacePileSize = getResources()
71                 .getDimensionPixelSize(R.dimen.conversation_single_line_face_pile_size);
72         mFacePileAvatarSize = getResources()
73                 .getDimensionPixelSize(R.dimen.conversation_single_line_face_pile_avatar_size);
74         mSingleAvatarSize = getResources()
75                 .getDimensionPixelSize(R.dimen.conversation_single_line_avatar_size);
76         mFacePileProtectionWidth = getResources().getDimensionPixelSize(
77                 R.dimen.conversation_single_line_face_pile_protection_width);
78         mTransformationHelper.addViewTransformingToSimilar(mConversationIconView);
79         mTransformationHelper.addTransformedView(mConversationSenderName);
80     }
81 
82     @Override
bind(@ullable CharSequence title, @Nullable CharSequence text, @Nullable View contentView)83     public void bind(@Nullable CharSequence title, @Nullable CharSequence text,
84             @Nullable View contentView) {
85         if (!(contentView instanceof ConversationLayout)) {
86             super.bind(title, text, contentView);
87             return;
88         }
89 
90         ConversationLayout conversationLayout = (ConversationLayout) contentView;
91         Icon conversationIcon = conversationLayout.getConversationIcon();
92         if (conversationIcon != null) {
93             mConversationFacePile.setVisibility(GONE);
94             mConversationIconView.setVisibility(VISIBLE);
95             mConversationIconView.setImageIcon(conversationIcon);
96             setSize(mConversationIconView, mSingleAvatarSize);
97         } else {
98             // If there isn't an icon, generate a "face pile" based on the sender avatars
99             mConversationIconView.setVisibility(GONE);
100             mConversationFacePile.setVisibility(VISIBLE);
101 
102             mConversationFacePile =
103                     requireViewById(com.android.internal.R.id.conversation_face_pile);
104             ImageView facePileBottomBg = mConversationFacePile.requireViewById(
105                     com.android.internal.R.id.conversation_face_pile_bottom_background);
106             ImageView facePileBottom = mConversationFacePile.requireViewById(
107                     com.android.internal.R.id.conversation_face_pile_bottom);
108             ImageView facePileTop = mConversationFacePile.requireViewById(
109                     com.android.internal.R.id.conversation_face_pile_top);
110             conversationLayout.bindFacePile(facePileBottomBg, facePileBottom, facePileTop);
111             setSize(mConversationFacePile, mFacePileSize);
112             setSize(facePileBottom, mFacePileAvatarSize);
113             setSize(facePileTop, mFacePileAvatarSize);
114             setSize(facePileBottomBg, mFacePileAvatarSize + 2 * mFacePileProtectionWidth);
115             mTransformationHelper.addViewTransformingToSimilar(facePileTop);
116             mTransformationHelper.addViewTransformingToSimilar(facePileBottom);
117             mTransformationHelper.addViewTransformingToSimilar(facePileBottomBg);
118         }
119         CharSequence conversationTitle = conversationLayout.getConversationTitle();
120         if (TextUtils.isEmpty(conversationTitle)) {
121             conversationTitle = title;
122         }
123         if (conversationLayout.isOneToOne()) {
124             mConversationSenderName.setVisibility(GONE);
125         } else {
126             mConversationSenderName.setVisibility(VISIBLE);
127             mConversationSenderName.setText(conversationLayout.getConversationSenderName());
128         }
129         CharSequence conversationText = conversationLayout.getConversationText();
130         if (TextUtils.isEmpty(conversationText)) {
131             conversationText = text;
132         }
133         super.bind(conversationTitle, conversationText, conversationLayout);
134     }
135 
setSize(View view, int size)136     private static void setSize(View view, int size) {
137         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) view.getLayoutParams();
138         lp.width = size;
139         lp.height = size;
140         view.setLayoutParams(lp);
141     }
142 
143     /**
144      * Apply the faded state as a layer type change to the face pile view which needs to have
145      * overlapping contents render precisely.
146      */
147     @Override
setNotificationFaded(boolean faded)148     public void setNotificationFaded(boolean faded) {
149         super.setNotificationFaded(faded);
150         NotificationFadeAware.setLayerTypeForFaded(mConversationFacePile, faded);
151     }
152 }
153