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 applyTextColor(mConversationSenderName, mSecondaryTextColor); 71 mFacePileSize = getResources() 72 .getDimensionPixelSize(R.dimen.conversation_single_line_face_pile_size); 73 mFacePileAvatarSize = getResources() 74 .getDimensionPixelSize(R.dimen.conversation_single_line_face_pile_avatar_size); 75 mSingleAvatarSize = getResources() 76 .getDimensionPixelSize(R.dimen.conversation_single_line_avatar_size); 77 mFacePileProtectionWidth = getResources().getDimensionPixelSize( 78 R.dimen.conversation_single_line_face_pile_protection_width); 79 mTransformationHelper.setCustomTransformation( 80 new FadeOutAndDownWithTitleTransformation(mConversationSenderName), 81 mConversationSenderName.getId()); 82 mTransformationHelper.addViewTransformingToSimilar(mConversationIconView); 83 mTransformationHelper.addTransformedView(mConversationSenderName); 84 } 85 86 @Override bind(@ullable CharSequence title, @Nullable CharSequence text, @Nullable View contentView)87 public void bind(@Nullable CharSequence title, @Nullable CharSequence text, 88 @Nullable View contentView) { 89 if (!(contentView instanceof ConversationLayout)) { 90 super.bind(title, text, contentView); 91 return; 92 } 93 94 ConversationLayout conversationLayout = (ConversationLayout) contentView; 95 Icon conversationIcon = conversationLayout.getConversationIcon(); 96 if (conversationIcon != null) { 97 mConversationFacePile.setVisibility(GONE); 98 mConversationIconView.setVisibility(VISIBLE); 99 mConversationIconView.setImageIcon(conversationIcon); 100 setSize(mConversationIconView, mSingleAvatarSize); 101 } else { 102 // If there isn't an icon, generate a "face pile" based on the sender avatars 103 mConversationIconView.setVisibility(GONE); 104 mConversationFacePile.setVisibility(VISIBLE); 105 106 mConversationFacePile = 107 requireViewById(com.android.internal.R.id.conversation_face_pile); 108 ImageView facePileBottomBg = mConversationFacePile.requireViewById( 109 com.android.internal.R.id.conversation_face_pile_bottom_background); 110 ImageView facePileBottom = mConversationFacePile.requireViewById( 111 com.android.internal.R.id.conversation_face_pile_bottom); 112 ImageView facePileTop = mConversationFacePile.requireViewById( 113 com.android.internal.R.id.conversation_face_pile_top); 114 conversationLayout.bindFacePile(facePileBottomBg, facePileBottom, facePileTop); 115 setSize(mConversationFacePile, mFacePileSize); 116 setSize(facePileBottom, mFacePileAvatarSize); 117 setSize(facePileTop, mFacePileAvatarSize); 118 setSize(facePileBottomBg, mFacePileAvatarSize + 2 * mFacePileProtectionWidth); 119 mTransformationHelper.addViewTransformingToSimilar(facePileTop); 120 mTransformationHelper.addViewTransformingToSimilar(facePileBottom); 121 mTransformationHelper.addViewTransformingToSimilar(facePileBottomBg); 122 } 123 CharSequence conversationTitle = conversationLayout.getConversationTitle(); 124 if (TextUtils.isEmpty(conversationTitle)) { 125 conversationTitle = title; 126 } 127 if (conversationLayout.isOneToOne()) { 128 mConversationSenderName.setVisibility(GONE); 129 } else { 130 mConversationSenderName.setVisibility(VISIBLE); 131 mConversationSenderName.setText(conversationLayout.getConversationSenderName()); 132 } 133 CharSequence conversationText = conversationLayout.getConversationText(); 134 if (TextUtils.isEmpty(conversationText)) { 135 conversationText = text; 136 } 137 super.bind(conversationTitle, conversationText, conversationLayout); 138 } 139 setSize(View view, int size)140 private static void setSize(View view, int size) { 141 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) view.getLayoutParams(); 142 lp.width = size; 143 lp.height = size; 144 view.setLayoutParams(lp); 145 } 146 147 /** 148 * Apply the faded state as a layer type change to the face pile view which needs to have 149 * overlapping contents render precisely. 150 */ 151 @Override setNotificationFaded(boolean faded)152 public void setNotificationFaded(boolean faded) { 153 super.setNotificationFaded(faded); 154 NotificationFadeAware.setLayerTypeForFaded(mConversationFacePile, faded); 155 } 156 } 157