Update one-line layout for conversation notifs
Fixes: 152770837 Test: manual, visual Change-Id: I8433d5e26be4e6fe0c16acc87b29bac334011cbf
This commit is contained in:
@@ -35,10 +35,14 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
@@ -109,7 +113,7 @@ public class ConversationLayout extends FrameLayout
|
||||
private CharSequence mNameReplacement;
|
||||
private boolean mIsCollapsed;
|
||||
private ImageResolver mImageResolver;
|
||||
private CachingIconView mConversationIcon;
|
||||
private CachingIconView mConversationIconView;
|
||||
private View mConversationIconContainer;
|
||||
private int mConversationIconTopPadding;
|
||||
private int mConversationIconTopPaddingExpandedGroup;
|
||||
@@ -157,6 +161,7 @@ public class ConversationLayout extends FrameLayout
|
||||
private ViewGroup mAppOps;
|
||||
private Rect mAppOpsTouchRect = new Rect();
|
||||
private float mMinTouchSize;
|
||||
private Icon mConversationIcon;
|
||||
|
||||
public ConversationLayout(@NonNull Context context) {
|
||||
super(context);
|
||||
@@ -192,7 +197,7 @@ public class ConversationLayout extends FrameLayout
|
||||
mAvatarSize = getResources().getDimensionPixelSize(R.dimen.messaging_avatar_size);
|
||||
mTextPaint.setTextAlign(Paint.Align.CENTER);
|
||||
mTextPaint.setAntiAlias(true);
|
||||
mConversationIcon = findViewById(R.id.conversation_icon);
|
||||
mConversationIconView = findViewById(R.id.conversation_icon);
|
||||
mConversationIconContainer = findViewById(R.id.conversation_icon_container);
|
||||
mIcon = findViewById(R.id.icon);
|
||||
mAppOps = findViewById(com.android.internal.R.id.app_ops);
|
||||
@@ -232,7 +237,7 @@ public class ConversationLayout extends FrameLayout
|
||||
});
|
||||
|
||||
// When the conversation icon is gone, hide the whole badge
|
||||
mConversationIcon.setOnForceHiddenChangedListener((forceHidden) -> {
|
||||
mConversationIconView.setOnForceHiddenChangedListener((forceHidden) -> {
|
||||
animateViewForceHidden(mConversationIconBadgeBg, forceHidden);
|
||||
animateViewForceHidden(mImportanceRingView, forceHidden);
|
||||
animateViewForceHidden(mIcon, forceHidden);
|
||||
@@ -463,7 +468,7 @@ public class ConversationLayout extends FrameLayout
|
||||
CharSequence conversationText = mConversationTitle;
|
||||
if (mIsOneToOne) {
|
||||
// Let's resolve the icon / text from the last sender
|
||||
mConversationIcon.setVisibility(VISIBLE);
|
||||
mConversationIconView.setVisibility(VISIBLE);
|
||||
mConversationFacePile.setVisibility(GONE);
|
||||
CharSequence userKey = getKey(mUser);
|
||||
for (int i = mGroups.size() - 1; i >= 0; i--) {
|
||||
@@ -480,17 +485,20 @@ public class ConversationLayout extends FrameLayout
|
||||
if (avatarIcon == null) {
|
||||
avatarIcon = createAvatarSymbol(conversationText, "", mLayoutColor);
|
||||
}
|
||||
mConversationIcon.setImageIcon(avatarIcon);
|
||||
mConversationIcon = avatarIcon;
|
||||
mConversationIconView.setImageIcon(mConversationIcon);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mLargeIcon != null) {
|
||||
mConversationIcon.setVisibility(VISIBLE);
|
||||
mConversationIcon = mLargeIcon;
|
||||
mConversationIconView.setVisibility(VISIBLE);
|
||||
mConversationFacePile.setVisibility(GONE);
|
||||
mConversationIcon.setImageIcon(mLargeIcon);
|
||||
mConversationIconView.setImageIcon(mLargeIcon);
|
||||
} else {
|
||||
mConversationIcon.setVisibility(GONE);
|
||||
mConversationIcon = null;
|
||||
mConversationIconView.setVisibility(GONE);
|
||||
// This will also inflate it!
|
||||
mConversationFacePile.setVisibility(VISIBLE);
|
||||
// rebind the value to the inflated view instead of the stub
|
||||
@@ -561,15 +569,8 @@ public class ConversationLayout extends FrameLayout
|
||||
mImageMessageContainer.setVisibility(newMessage != null ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
private void bindFacePile() {
|
||||
// Let's bind the face pile
|
||||
ImageView bottomBackground = mConversationFacePile.findViewById(
|
||||
R.id.conversation_face_pile_bottom_background);
|
||||
public void bindFacePile(ImageView bottomBackground, ImageView bottomView, ImageView topView) {
|
||||
applyNotificationBackgroundColor(bottomBackground);
|
||||
ImageView bottomView = mConversationFacePile.findViewById(
|
||||
R.id.conversation_face_pile_bottom);
|
||||
ImageView topView = mConversationFacePile.findViewById(
|
||||
R.id.conversation_face_pile_top);
|
||||
// Let's find the two last conversations:
|
||||
Icon secondLastIcon = null;
|
||||
CharSequence lastKey = null;
|
||||
@@ -601,6 +602,17 @@ public class ConversationLayout extends FrameLayout
|
||||
secondLastIcon = createAvatarSymbol("", "", mLayoutColor);
|
||||
}
|
||||
topView.setImageIcon(secondLastIcon);
|
||||
}
|
||||
|
||||
private void bindFacePile() {
|
||||
ImageView bottomBackground = mConversationFacePile.findViewById(
|
||||
R.id.conversation_face_pile_bottom_background);
|
||||
ImageView bottomView = mConversationFacePile.findViewById(
|
||||
R.id.conversation_face_pile_bottom);
|
||||
ImageView topView = mConversationFacePile.findViewById(
|
||||
R.id.conversation_face_pile_top);
|
||||
|
||||
bindFacePile(bottomBackground, bottomView, topView);
|
||||
|
||||
int conversationAvatarSize;
|
||||
int facepileAvatarSize;
|
||||
@@ -614,7 +626,7 @@ public class ConversationLayout extends FrameLayout
|
||||
facepileAvatarSize = mFacePileAvatarSizeExpandedGroup;
|
||||
facePileBackgroundSize = facepileAvatarSize + 2 * mFacePileProtectionWidthExpanded;
|
||||
}
|
||||
LayoutParams layoutParams = (LayoutParams) mConversationIcon.getLayoutParams();
|
||||
LayoutParams layoutParams = (LayoutParams) mConversationIconView.getLayoutParams();
|
||||
layoutParams.width = conversationAvatarSize;
|
||||
layoutParams.height = conversationAvatarSize;
|
||||
mConversationFacePile.setLayoutParams(layoutParams);
|
||||
@@ -664,11 +676,11 @@ public class ConversationLayout extends FrameLayout
|
||||
layoutParams.setMarginStart(sidemargin);
|
||||
mConversationIconBadge.setLayoutParams(layoutParams);
|
||||
|
||||
if (mConversationIcon.getVisibility() == VISIBLE) {
|
||||
layoutParams = (LayoutParams) mConversationIcon.getLayoutParams();
|
||||
if (mConversationIconView.getVisibility() == VISIBLE) {
|
||||
layoutParams = (LayoutParams) mConversationIconView.getLayoutParams();
|
||||
layoutParams.width = conversationAvatarSize;
|
||||
layoutParams.height = conversationAvatarSize;
|
||||
mConversationIcon.setLayoutParams(layoutParams);
|
||||
mConversationIconView.setLayoutParams(layoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,6 +731,10 @@ public class ConversationLayout extends FrameLayout
|
||||
mConversationTitle = conversationTitle;
|
||||
}
|
||||
|
||||
public CharSequence getConversationTitle() {
|
||||
return mConversationText.getText();
|
||||
}
|
||||
|
||||
private void removeGroups(ArrayList<MessagingGroup> oldGroups) {
|
||||
int size = oldGroups.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
@@ -1218,4 +1234,43 @@ public class ConversationLayout extends FrameLayout
|
||||
public void setMessagingClippingDisabled(boolean clippingDisabled) {
|
||||
mMessagingLinearLayout.setClipBounds(clippingDisabled ? null : mMessagingClipRect);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CharSequence getConversationSenderName() {
|
||||
if (mGroups.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final CharSequence name = mGroups.get(mGroups.size() - 1).getSenderName();
|
||||
return getResources().getString(R.string.conversation_single_line_name_display, name);
|
||||
}
|
||||
|
||||
public boolean isOneToOne() {
|
||||
return mIsOneToOne;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CharSequence getConversationText() {
|
||||
if (mMessages.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final MessagingMessage messagingMessage = mMessages.get(mMessages.size() - 1);
|
||||
final CharSequence text = messagingMessage.getMessage().getText();
|
||||
if (text == null && messagingMessage instanceof MessagingImageMessage) {
|
||||
final String unformatted =
|
||||
getResources().getString(R.string.conversation_single_line_image_placeholder);
|
||||
SpannableString spannableString = new SpannableString(unformatted);
|
||||
spannableString.setSpan(
|
||||
new StyleSpan(Typeface.ITALIC),
|
||||
0,
|
||||
spannableString.length(),
|
||||
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
return spannableString;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Icon getConversationIcon() {
|
||||
return mConversationIcon;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
~ 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
|
||||
~ limitations underthe License
|
||||
-->
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
@@ -24,12 +24,20 @@
|
||||
android:layout_height="@dimen/notification_header_height"
|
||||
android:clipChildren="false"
|
||||
style="?attr/notificationHeaderStyle">
|
||||
<com.android.internal.widget.CachingIconView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="?attr/notificationHeaderIconSize"
|
||||
android:layout_height="?attr/notificationHeaderIconSize"
|
||||
android:layout_marginEnd="@dimen/notification_header_icon_margin_end"
|
||||
<!-- Wrapper used to expand the width of the "space" containing the icon programmatically -->
|
||||
<FrameLayout
|
||||
android:id="@+id/header_icon_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.android.internal.widget.CachingIconView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="?attr/notificationHeaderIconSize"
|
||||
android:layout_height="?attr/notificationHeaderIconSize"
|
||||
android:layout_marginEnd="@dimen/notification_header_icon_margin_end"
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
</FrameLayout>
|
||||
<TextView
|
||||
android:id="@+id/app_name_text"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -5449,6 +5449,9 @@
|
||||
<!-- The way a conversation name is displayed when single line. The text will be displayed to the end of this text with some spacing -->
|
||||
<string name="conversation_single_line_name_display"><xliff:g id="sender_name" example="Sara">%1$s</xliff:g>:</string>
|
||||
|
||||
<!-- Text used when a conversation is displayed in a single-line when the latest message is an image. [CHAR_LIMIT=NONE] -->
|
||||
<string name="conversation_single_line_image_placeholder">sent an image</string>
|
||||
|
||||
<!-- Conversation Title fallback if the there is no name provided in a 1:1 conversation [CHAR LIMIT=40]-->
|
||||
<string name="conversation_title_fallback_one_to_one">Conversation</string>
|
||||
|
||||
|
||||
@@ -296,6 +296,10 @@ easier.
|
||||
<style name="TextAppearance.DeviceDefault.Notification.Info" parent="TextAppearance.Material.Notification.Info">
|
||||
<item name="fontFamily">@string/config_bodyFontFamily</item>
|
||||
</style>
|
||||
<style name="TextAppearance.DeviceDefault.Notification.Conversation.AppName"
|
||||
parent="@*android:style/TextAppearance.DeviceDefault.Notification.Title">
|
||||
<item name="android:textSize">16sp</item>
|
||||
</style>
|
||||
<style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Material.Widget">
|
||||
<item name="fontFamily">@string/config_bodyFontFamily</item>
|
||||
</style>
|
||||
|
||||
@@ -1599,6 +1599,8 @@
|
||||
<java-symbol type="style" name="Theme.DeviceDefault.VoiceInteractionSession" />
|
||||
<java-symbol type="style" name="Pointer" />
|
||||
<java-symbol type="style" name="LargePointer" />
|
||||
<java-symbol type="style" name="TextAppearance.DeviceDefault.Notification.Title" />
|
||||
<java-symbol type="style" name="TextAppearance.DeviceDefault.Notification.Info" />
|
||||
|
||||
<java-symbol type="attr" name="mediaRouteButtonStyle" />
|
||||
<java-symbol type="attr" name="externalRouteEnabledDrawable" />
|
||||
@@ -3863,7 +3865,10 @@
|
||||
<java-symbol type="array" name="config_defaultImperceptibleKillingExemptionPkgs" />
|
||||
<java-symbol type="array" name="config_defaultImperceptibleKillingExemptionProcStates" />
|
||||
|
||||
<java-symbol type="id" name="header_icon_container" />
|
||||
<java-symbol type="attr" name="notificationHeaderTextAppearance" />
|
||||
<java-symbol type="string" name="conversation_single_line_name_display" />
|
||||
<java-symbol type="string" name="conversation_single_line_image_placeholder" />
|
||||
<java-symbol type="string" name="conversation_title_fallback_one_to_one" />
|
||||
<java-symbol type="string" name="conversation_title_fallback_group_chat" />
|
||||
<java-symbol type="id" name="conversation_icon" />
|
||||
@@ -3907,6 +3912,7 @@
|
||||
<java-symbol type="layout" name="conversation_face_pile_layout" />
|
||||
<java-symbol type="id" name="conversation_unread_count" />
|
||||
<java-symbol type="string" name="unread_convo_overflow" />
|
||||
<java-symbol type="style" name="TextAppearance.DeviceDefault.Notification.Conversation.AppName" />
|
||||
|
||||
<!-- Intent resolver and share sheet -->
|
||||
<java-symbol type="string" name="resolver_personal_tab" />
|
||||
|
||||
@@ -279,8 +279,12 @@ public class Utils {
|
||||
}
|
||||
|
||||
public static int getThemeAttr(Context context, int attr) {
|
||||
return getThemeAttr(context, attr, 0);
|
||||
}
|
||||
|
||||
public static int getThemeAttr(Context context, int attr, int defaultValue) {
|
||||
TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
|
||||
int theme = ta.getResourceId(0, 0);
|
||||
int theme = ta.getResourceId(0, defaultValue);
|
||||
ta.recycle();
|
||||
return theme;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2020 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.
|
||||
-->
|
||||
|
||||
<com.android.systemui.statusbar.notification.row.HybridConversationNotificationView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical|start"
|
||||
android:paddingEnd="12dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="@*android:dimen/conversation_content_start"
|
||||
android:layout_height="36dp"
|
||||
>
|
||||
<ImageView
|
||||
android:id="@*android:id/conversation_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
|
||||
<ViewStub
|
||||
android:id="@*android:id/conversation_face_pile"
|
||||
android:layout="@*android:layout/conversation_face_pile_layout"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
|
||||
android:paddingEnd="8dp"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conversation_notification_sender"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
style="?attr/hybridNotificationTextStyle"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
style="?attr/hybridNotificationTextStyle"
|
||||
/>
|
||||
</com.android.systemui.statusbar.notification.row.HybridConversationNotificationView>
|
||||
@@ -625,6 +625,15 @@
|
||||
<!-- The height of the gap between adjacent notification sections. -->
|
||||
<dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen>
|
||||
|
||||
<!-- Size of the face pile shown on one-line (children of a group) conversation notifications -->
|
||||
<dimen name="conversation_single_line_face_pile_size">36dp</dimen>
|
||||
|
||||
<!-- Size of an avatar shown on one-line (children of a group) conversation notifications -->
|
||||
<dimen name="conversation_single_line_avatar_size">24dp</dimen>
|
||||
|
||||
<!-- Border width for avatars in the face pile shown on one-line (children of a group) conversation notifications -->
|
||||
<dimen name="conversation_single_line_face_pile_protection_width">1dp</dimen>
|
||||
|
||||
<!-- The minimum amount of top overscroll to go to the quick settings. -->
|
||||
<dimen name="min_top_overscroll_to_qs">36dp</dimen>
|
||||
|
||||
|
||||
@@ -475,7 +475,6 @@
|
||||
<item name="android:textColor">?android:attr/textColorTertiary</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless">
|
||||
<item name="android:background">@drawable/btn_borderless_rect</item>
|
||||
</style>
|
||||
|
||||
@@ -536,6 +536,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
return isNonblockable;
|
||||
}
|
||||
|
||||
private boolean isConversation() {
|
||||
return mPeopleNotificationIdentifier
|
||||
.getPeopleNotificationType(mEntry.getSbn(), mEntry.getRanking())
|
||||
!= PeopleNotificationIdentifier.TYPE_NON_PERSON;
|
||||
}
|
||||
|
||||
public void onNotificationUpdated() {
|
||||
for (NotificationContentView l : mLayouts) {
|
||||
l.onNotificationUpdated(mEntry);
|
||||
@@ -548,7 +554,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
mMenuRow.setAppName(mAppName);
|
||||
}
|
||||
if (mIsSummaryWithChildren) {
|
||||
mChildrenContainer.recreateNotificationHeader(mExpandClickListener);
|
||||
mChildrenContainer.recreateNotificationHeader(mExpandClickListener, isConversation());
|
||||
mChildrenContainer.onNotificationUpdated();
|
||||
}
|
||||
if (mIconAnimationRunning) {
|
||||
@@ -2358,8 +2364,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
mIsSummaryWithChildren = mChildrenContainer != null
|
||||
&& mChildrenContainer.getNotificationChildCount() > 0;
|
||||
if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
|
||||
mChildrenContainer.recreateNotificationHeader(mExpandClickListener
|
||||
);
|
||||
mChildrenContainer.recreateNotificationHeader(mExpandClickListener, isConversation());
|
||||
}
|
||||
getShowingLayout().updateBackgroundColor(false /* animate */);
|
||||
mPrivateLayout.updateExpandButtons(isExpandable());
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.systemui.statusbar.notification.row;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.widget.ConversationLayout;
|
||||
import com.android.systemui.R;
|
||||
|
||||
/**
|
||||
* A hybrid view which may contain information about one ore more conversations.
|
||||
*/
|
||||
public class HybridConversationNotificationView extends HybridNotificationView {
|
||||
|
||||
private ImageView mConversationIconView;
|
||||
private TextView mConversationSenderName;
|
||||
private View mConversationFacePile;
|
||||
private int mConversationIconSize;
|
||||
private int mFacePileSize;
|
||||
private int mFacePileProtectionWidth;
|
||||
|
||||
public HybridConversationNotificationView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public HybridConversationNotificationView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public HybridConversationNotificationView(
|
||||
Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public HybridConversationNotificationView(
|
||||
Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mConversationIconView = requireViewById(com.android.internal.R.id.conversation_icon);
|
||||
mConversationFacePile = requireViewById(com.android.internal.R.id.conversation_face_pile);
|
||||
mConversationSenderName = requireViewById(R.id.conversation_notification_sender);
|
||||
mFacePileSize = getResources()
|
||||
.getDimensionPixelSize(R.dimen.conversation_single_line_face_pile_size);
|
||||
mConversationIconSize = getResources()
|
||||
.getDimensionPixelSize(R.dimen.conversation_single_line_avatar_size);
|
||||
mFacePileProtectionWidth = getResources().getDimensionPixelSize(
|
||||
R.dimen.conversation_single_line_face_pile_protection_width);
|
||||
mTransformationHelper.addViewTransformingToSimilar(mConversationIconView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(@Nullable CharSequence title, @Nullable CharSequence text,
|
||||
@Nullable View contentView) {
|
||||
if (!(contentView instanceof ConversationLayout)) {
|
||||
super.bind(title, text, contentView);
|
||||
return;
|
||||
}
|
||||
|
||||
ConversationLayout conversationLayout = (ConversationLayout) contentView;
|
||||
Icon conversationIcon = conversationLayout.getConversationIcon();
|
||||
if (conversationIcon != null) {
|
||||
mConversationFacePile.setVisibility(GONE);
|
||||
mConversationIconView.setVisibility(VISIBLE);
|
||||
mConversationIconView.setImageIcon(conversationIcon);
|
||||
} else {
|
||||
// If there isn't an icon, generate a "face pile" based on the sender avatars
|
||||
mConversationIconView.setVisibility(GONE);
|
||||
mConversationFacePile.setVisibility(VISIBLE);
|
||||
|
||||
mConversationFacePile =
|
||||
requireViewById(com.android.internal.R.id.conversation_face_pile);
|
||||
ImageView facePileBottomBg = mConversationFacePile.requireViewById(
|
||||
com.android.internal.R.id.conversation_face_pile_bottom_background);
|
||||
ImageView facePileBottom = mConversationFacePile.requireViewById(
|
||||
com.android.internal.R.id.conversation_face_pile_bottom);
|
||||
ImageView facePileTop = mConversationFacePile.requireViewById(
|
||||
com.android.internal.R.id.conversation_face_pile_top);
|
||||
conversationLayout.bindFacePile(facePileBottomBg, facePileBottom, facePileTop);
|
||||
setSize(mConversationFacePile, mFacePileSize);
|
||||
setSize(facePileBottom, mConversationIconSize);
|
||||
setSize(facePileTop, mConversationIconSize);
|
||||
setSize(facePileBottomBg, mConversationIconSize + 2 * mFacePileProtectionWidth);
|
||||
mTransformationHelper.addViewTransformingToSimilar(facePileTop);
|
||||
mTransformationHelper.addViewTransformingToSimilar(facePileBottom);
|
||||
mTransformationHelper.addViewTransformingToSimilar(facePileBottomBg);
|
||||
}
|
||||
CharSequence conversationTitle = conversationLayout.getConversationTitle();
|
||||
if (TextUtils.isEmpty(conversationTitle)) {
|
||||
conversationTitle = title;
|
||||
}
|
||||
if (conversationLayout.isOneToOne()) {
|
||||
mConversationSenderName.setVisibility(GONE);
|
||||
} else {
|
||||
mConversationSenderName.setVisibility(VISIBLE);
|
||||
mConversationSenderName.setText(conversationLayout.getConversationSenderName());
|
||||
}
|
||||
CharSequence conversationText = conversationLayout.getConversationText();
|
||||
if (TextUtils.isEmpty(conversationText)) {
|
||||
conversationText = text;
|
||||
}
|
||||
super.bind(conversationTitle, conversationText, conversationLayout);
|
||||
}
|
||||
|
||||
private static void setSize(View view, int size) {
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) view.getLayoutParams();
|
||||
lp.width = size;
|
||||
lp.height = size;
|
||||
view.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
@@ -16,18 +16,20 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification.row;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.widget.ConversationLayout;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.notification.NotificationDozeHelper;
|
||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
|
||||
/**
|
||||
* A class managing hybrid groups that include {@link HybridNotificationView} and the notification
|
||||
@@ -36,41 +38,41 @@ import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
public class HybridGroupManager {
|
||||
|
||||
private final Context mContext;
|
||||
private final ViewGroup mParent;
|
||||
|
||||
private float mOverflowNumberSize;
|
||||
private int mOverflowNumberPadding;
|
||||
|
||||
private int mOverflowNumberColor;
|
||||
|
||||
public HybridGroupManager(Context ctx, ViewGroup parent) {
|
||||
public HybridGroupManager(Context ctx) {
|
||||
mContext = ctx;
|
||||
mParent = parent;
|
||||
initDimens();
|
||||
}
|
||||
|
||||
public void initDimens() {
|
||||
Resources res = mContext.getResources();
|
||||
mOverflowNumberSize = res.getDimensionPixelSize(
|
||||
R.dimen.group_overflow_number_size);
|
||||
mOverflowNumberPadding = res.getDimensionPixelSize(
|
||||
R.dimen.group_overflow_number_padding);
|
||||
mOverflowNumberSize = res.getDimensionPixelSize(R.dimen.group_overflow_number_size);
|
||||
mOverflowNumberPadding = res.getDimensionPixelSize(R.dimen.group_overflow_number_padding);
|
||||
}
|
||||
|
||||
private HybridNotificationView inflateHybridViewWithStyle(int style) {
|
||||
private HybridNotificationView inflateHybridViewWithStyle(int style,
|
||||
View contentView, ViewGroup parent) {
|
||||
LayoutInflater inflater = new ContextThemeWrapper(mContext, style)
|
||||
.getSystemService(LayoutInflater.class);
|
||||
HybridNotificationView hybrid = (HybridNotificationView) inflater.inflate(
|
||||
R.layout.hybrid_notification, mParent, false);
|
||||
mParent.addView(hybrid);
|
||||
int layout = contentView instanceof ConversationLayout
|
||||
? R.layout.hybrid_conversation_notification
|
||||
: R.layout.hybrid_notification;
|
||||
HybridNotificationView hybrid = (HybridNotificationView)
|
||||
inflater.inflate(layout, parent, false);
|
||||
parent.addView(hybrid);
|
||||
return hybrid;
|
||||
}
|
||||
|
||||
private TextView inflateOverflowNumber() {
|
||||
private TextView inflateOverflowNumber(ViewGroup parent) {
|
||||
LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
|
||||
TextView numberView = (TextView) inflater.inflate(
|
||||
R.layout.hybrid_overflow_number, mParent, false);
|
||||
mParent.addView(numberView);
|
||||
R.layout.hybrid_overflow_number, parent, false);
|
||||
parent.addView(numberView);
|
||||
updateOverFlowNumberColor(numberView);
|
||||
return numberView;
|
||||
}
|
||||
@@ -87,22 +89,26 @@ public class HybridGroupManager {
|
||||
}
|
||||
|
||||
public HybridNotificationView bindFromNotification(HybridNotificationView reusableView,
|
||||
Notification notification) {
|
||||
return bindFromNotificationWithStyle(reusableView, notification,
|
||||
R.style.HybridNotification);
|
||||
View contentView, StatusBarNotification notification,
|
||||
ViewGroup parent) {
|
||||
return bindFromNotificationWithStyle(reusableView, contentView, notification,
|
||||
R.style.HybridNotification, parent);
|
||||
}
|
||||
|
||||
private HybridNotificationView bindFromNotificationWithStyle(
|
||||
HybridNotificationView reusableView, Notification notification, int style) {
|
||||
HybridNotificationView reusableView, View contentView,
|
||||
StatusBarNotification notification,
|
||||
int style, ViewGroup parent) {
|
||||
if (reusableView == null) {
|
||||
reusableView = inflateHybridViewWithStyle(style);
|
||||
reusableView = inflateHybridViewWithStyle(style, contentView, parent);
|
||||
}
|
||||
CharSequence titleText = resolveTitle(notification);
|
||||
CharSequence contentText = resolveText(notification);
|
||||
reusableView.bind(titleText, contentText);
|
||||
CharSequence titleText = resolveTitle(notification.getNotification());
|
||||
CharSequence contentText = resolveText(notification.getNotification());
|
||||
reusableView.bind(titleText, contentText, contentView);
|
||||
return reusableView;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CharSequence resolveText(Notification notification) {
|
||||
CharSequence contentText = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
|
||||
if (contentText == null) {
|
||||
@@ -111,6 +117,7 @@ public class HybridGroupManager {
|
||||
return contentText;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CharSequence resolveTitle(Notification notification) {
|
||||
CharSequence titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
|
||||
if (titleText == null) {
|
||||
@@ -119,9 +126,10 @@ public class HybridGroupManager {
|
||||
return titleText;
|
||||
}
|
||||
|
||||
public TextView bindOverflowNumber(TextView reusableView, int number) {
|
||||
public TextView bindOverflowNumber(TextView reusableView, int number,
|
||||
ViewGroup parent) {
|
||||
if (reusableView == null) {
|
||||
reusableView = inflateOverflowNumber();
|
||||
reusableView = inflateOverflowNumber(parent);
|
||||
}
|
||||
String text = mContext.getResources().getString(
|
||||
R.string.notification_group_overflow_indicator, number);
|
||||
|
||||
@@ -36,8 +36,7 @@ import com.android.systemui.statusbar.notification.TransformState;
|
||||
public class HybridNotificationView extends AlphaOptimizedLinearLayout
|
||||
implements TransformableView {
|
||||
|
||||
private ViewTransformationHelper mTransformationHelper;
|
||||
|
||||
protected final ViewTransformationHelper mTransformationHelper = new ViewTransformationHelper();
|
||||
protected TextView mTitleView;
|
||||
protected TextView mTextView;
|
||||
|
||||
@@ -69,9 +68,8 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mTitleView = (TextView) findViewById(R.id.notification_title);
|
||||
mTextView = (TextView) findViewById(R.id.notification_text);
|
||||
mTransformationHelper = new ViewTransformationHelper();
|
||||
mTitleView = findViewById(R.id.notification_title);
|
||||
mTextView = findViewById(R.id.notification_text);
|
||||
mTransformationHelper.setCustomTransformation(
|
||||
new ViewTransformationHelper.CustomTransformation() {
|
||||
@Override
|
||||
@@ -106,11 +104,8 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout
|
||||
mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TEXT, mTextView);
|
||||
}
|
||||
|
||||
public void bind(CharSequence title) {
|
||||
bind(title, null);
|
||||
}
|
||||
|
||||
public void bind(CharSequence title, CharSequence text) {
|
||||
public void bind(@Nullable CharSequence title, @Nullable CharSequence text,
|
||||
@Nullable View contentView) {
|
||||
mTitleView.setText(title);
|
||||
mTitleView.setVisibility(TextUtils.isEmpty(title) ? GONE : VISIBLE);
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
|
||||
@@ -177,7 +177,7 @@ public class NotificationContentView extends FrameLayout {
|
||||
|
||||
public NotificationContentView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mHybridGroupManager = new HybridGroupManager(getContext(), this);
|
||||
mHybridGroupManager = new HybridGroupManager(getContext());
|
||||
mMediaTransferManager = new MediaTransferManager(getContext());
|
||||
mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
|
||||
mSmartReplyController = Dependency.get(SmartReplyController.class);
|
||||
@@ -1163,7 +1163,7 @@ public class NotificationContentView extends FrameLayout {
|
||||
if (mIsChildInGroup) {
|
||||
boolean isNewView = mSingleLineView == null;
|
||||
mSingleLineView = mHybridGroupManager.bindFromNotification(
|
||||
mSingleLineView, mStatusBarNotification.getNotification());
|
||||
mSingleLineView, mContractedChild, mStatusBarNotification, this);
|
||||
if (isNewView) {
|
||||
updateViewVisibility(mVisibleType, VISIBLE_TYPE_SINGLELINE,
|
||||
mSingleLineView, mSingleLineView);
|
||||
|
||||
@@ -46,13 +46,13 @@ class NotificationConversationTemplateViewWrapper constructor(
|
||||
)
|
||||
private val conversationLayout: ConversationLayout = view as ConversationLayout
|
||||
|
||||
private lateinit var conversationIcon: CachingIconView
|
||||
private lateinit var conversationIconView: CachingIconView
|
||||
private lateinit var conversationBadgeBg: View
|
||||
private lateinit var expandButton: View
|
||||
private lateinit var expandButtonContainer: View
|
||||
private lateinit var imageMessageContainer: ViewGroup
|
||||
private lateinit var messagingLinearLayout: MessagingLinearLayout
|
||||
private lateinit var conversationTitle: View
|
||||
private lateinit var conversationTitleView: View
|
||||
private lateinit var importanceRing: View
|
||||
private lateinit var appName: View
|
||||
private var facePileBottomBg: View? = null
|
||||
@@ -63,7 +63,7 @@ class NotificationConversationTemplateViewWrapper constructor(
|
||||
messagingLinearLayout = conversationLayout.messagingLinearLayout
|
||||
imageMessageContainer = conversationLayout.imageMessageContainer
|
||||
with(conversationLayout) {
|
||||
conversationIcon = requireViewById(com.android.internal.R.id.conversation_icon)
|
||||
conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon)
|
||||
conversationBadgeBg =
|
||||
requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
|
||||
expandButton = requireViewById(com.android.internal.R.id.expand_button)
|
||||
@@ -71,7 +71,7 @@ class NotificationConversationTemplateViewWrapper constructor(
|
||||
requireViewById(com.android.internal.R.id.expand_button_container)
|
||||
importanceRing = requireViewById(com.android.internal.R.id.conversation_icon_badge_ring)
|
||||
appName = requireViewById(com.android.internal.R.id.app_name_text)
|
||||
conversationTitle = requireViewById(com.android.internal.R.id.conversation_text)
|
||||
conversationTitleView = requireViewById(com.android.internal.R.id.conversation_text)
|
||||
facePileTop = findViewById(com.android.internal.R.id.conversation_face_pile_top)
|
||||
facePileBottom = findViewById(com.android.internal.R.id.conversation_face_pile_bottom)
|
||||
facePileBottomBg =
|
||||
@@ -93,7 +93,7 @@ class NotificationConversationTemplateViewWrapper constructor(
|
||||
addTransformedViews(
|
||||
messagingLinearLayout,
|
||||
appName,
|
||||
conversationTitle)
|
||||
conversationTitleView)
|
||||
|
||||
// Let's ignore the image message container since that is transforming as part of the
|
||||
// messages already
|
||||
@@ -124,7 +124,7 @@ class NotificationConversationTemplateViewWrapper constructor(
|
||||
)
|
||||
|
||||
addViewsTransformingToSimilar(
|
||||
conversationIcon,
|
||||
conversationIconView,
|
||||
conversationBadgeBg,
|
||||
expandButton,
|
||||
importanceRing,
|
||||
@@ -136,29 +136,27 @@ class NotificationConversationTemplateViewWrapper constructor(
|
||||
|
||||
override fun setShelfIconVisible(visible: Boolean) {
|
||||
if (conversationLayout.isImportantConversation) {
|
||||
if (conversationIcon.visibility != GONE) {
|
||||
conversationIcon.setForceHidden(visible);
|
||||
if (conversationIconView.visibility != GONE) {
|
||||
conversationIconView.isForceHidden = visible
|
||||
// We don't want the small icon to be hidden by the extended wrapper, as force
|
||||
// hiding the conversationIcon will already do that via its listener.
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
super.setShelfIconVisible(visible)
|
||||
}
|
||||
|
||||
override fun getShelfTransformationTarget(): View? {
|
||||
if (conversationLayout.isImportantConversation) {
|
||||
if (conversationIcon.visibility != GONE) {
|
||||
return conversationIcon
|
||||
} else {
|
||||
// A notification with a fallback icon was set to important. Currently
|
||||
// the transformation doesn't work for these and needs to be fixed. In the meantime
|
||||
// those are using the icon.
|
||||
return super.getShelfTransformationTarget();
|
||||
}
|
||||
}
|
||||
return super.getShelfTransformationTarget()
|
||||
}
|
||||
override fun getShelfTransformationTarget(): View? =
|
||||
if (conversationLayout.isImportantConversation)
|
||||
if (conversationIconView.visibility != GONE)
|
||||
conversationIconView
|
||||
else
|
||||
// A notification with a fallback icon was set to important. Currently
|
||||
// the transformation doesn't work for these and needs to be fixed.
|
||||
// In the meantime those are using the icon.
|
||||
super.getShelfTransformationTarget()
|
||||
else
|
||||
super.getShelfTransformationTarget()
|
||||
|
||||
override fun setRemoteInputVisible(visible: Boolean) =
|
||||
conversationLayout.showHistoricMessages(visible)
|
||||
|
||||
@@ -27,11 +27,13 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.widget.CachingIconView;
|
||||
import com.android.internal.widget.NotificationExpandButton;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.TransformableView;
|
||||
@@ -60,12 +62,14 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
private NotificationExpandButton mExpandButton;
|
||||
protected NotificationHeaderView mNotificationHeader;
|
||||
private TextView mHeaderText;
|
||||
private TextView mAppNameText;
|
||||
private ImageView mWorkProfileImage;
|
||||
private View mCameraIcon;
|
||||
private View mMicIcon;
|
||||
private View mOverlayIcon;
|
||||
private View mAppOps;
|
||||
private View mAudiblyAlertedIcon;
|
||||
private FrameLayout mIconContainer;
|
||||
|
||||
private boolean mIsLowPriority;
|
||||
private boolean mTransformLowPriorityTitle;
|
||||
@@ -108,8 +112,10 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
}
|
||||
|
||||
protected void resolveHeaderViews() {
|
||||
mIconContainer = mView.findViewById(com.android.internal.R.id.header_icon_container);
|
||||
mIcon = mView.findViewById(com.android.internal.R.id.icon);
|
||||
mHeaderText = mView.findViewById(com.android.internal.R.id.header_text);
|
||||
mAppNameText = mView.findViewById(com.android.internal.R.id.app_name_text);
|
||||
mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
|
||||
mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
|
||||
mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
|
||||
@@ -182,6 +188,61 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
public void applyConversationSkin() {
|
||||
if (mAppNameText != null) {
|
||||
mAppNameText.setTextAppearance(
|
||||
com.android.internal.R.style
|
||||
.TextAppearance_DeviceDefault_Notification_Conversation_AppName);
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mAppNameText.getLayoutParams();
|
||||
layoutParams.setMarginStart(0);
|
||||
}
|
||||
if (mIconContainer != null) {
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mIconContainer.getLayoutParams();
|
||||
layoutParams.width =
|
||||
mIconContainer.getContext().getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.conversation_content_start);
|
||||
final int marginStart =
|
||||
mIconContainer.getContext().getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.notification_content_margin_start);
|
||||
layoutParams.setMarginStart(marginStart * -1);
|
||||
}
|
||||
if (mIcon != null) {
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mIcon.getLayoutParams();
|
||||
layoutParams.setMarginEnd(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearConversationSkin() {
|
||||
if (mAppNameText != null) {
|
||||
final int textAppearance = Utils.getThemeAttr(
|
||||
mAppNameText.getContext(),
|
||||
com.android.internal.R.attr.notificationHeaderTextAppearance,
|
||||
com.android.internal.R.style.TextAppearance_DeviceDefault_Notification_Info);
|
||||
mAppNameText.setTextAppearance(textAppearance);
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mAppNameText.getLayoutParams();
|
||||
final int marginStart = mAppNameText.getContext().getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.notification_header_app_name_margin_start);
|
||||
layoutParams.setMarginStart(marginStart);
|
||||
}
|
||||
if (mIconContainer != null) {
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mIconContainer.getLayoutParams();
|
||||
layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
layoutParams.setMarginStart(0);
|
||||
}
|
||||
if (mIcon != null) {
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mIcon.getLayoutParams();
|
||||
final int marginEnd = mIcon.getContext().getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.notification_header_icon_margin_end);
|
||||
layoutParams.setMarginEnd(marginEnd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the remaining TransformTypes to the TransformHelper. This is done to make sure that each
|
||||
* child is faded automatically and doesn't have to be manually added.
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.android.systemui.statusbar.notification.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.notification.row.HybridGroupManager;
|
||||
import com.android.systemui.statusbar.notification.row.HybridNotificationView;
|
||||
import com.android.systemui.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper;
|
||||
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -99,6 +100,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
private boolean mIsLowPriority;
|
||||
private OnClickListener mHeaderClickListener;
|
||||
private ViewGroup mCurrentHeader;
|
||||
private boolean mIsConversation;
|
||||
|
||||
private boolean mShowDividersWhenExpanded;
|
||||
private boolean mHideDividersDuringExpand;
|
||||
@@ -122,7 +124,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
public NotificationChildrenContainer(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
mHybridGroupManager = new HybridGroupManager(getContext(), this);
|
||||
mHybridGroupManager = new HybridGroupManager(getContext());
|
||||
initDimens();
|
||||
setClipChildren(false);
|
||||
}
|
||||
@@ -308,8 +310,9 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
return mAttachedChildren.size();
|
||||
}
|
||||
|
||||
public void recreateNotificationHeader(OnClickListener listener) {
|
||||
public void recreateNotificationHeader(OnClickListener listener, boolean isConversation) {
|
||||
mHeaderClickListener = listener;
|
||||
mIsConversation = isConversation;
|
||||
StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
|
||||
final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
|
||||
notification.getNotification());
|
||||
@@ -328,7 +331,16 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
header.reapply(getContext(), mNotificationHeader);
|
||||
}
|
||||
mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
|
||||
recreateLowPriorityHeader(builder);
|
||||
if (mNotificationHeaderWrapper instanceof NotificationHeaderViewWrapper) {
|
||||
NotificationHeaderViewWrapper headerWrapper =
|
||||
(NotificationHeaderViewWrapper) mNotificationHeaderWrapper;
|
||||
if (isConversation) {
|
||||
headerWrapper.applyConversationSkin();
|
||||
} else {
|
||||
headerWrapper.clearConversationSkin();
|
||||
}
|
||||
}
|
||||
recreateLowPriorityHeader(builder, isConversation);
|
||||
updateHeaderVisibility(false /* animate */);
|
||||
updateChildrenHeaderAppearance();
|
||||
}
|
||||
@@ -338,7 +350,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
*
|
||||
* @param builder a builder to reuse. Otherwise the builder will be recovered.
|
||||
*/
|
||||
private void recreateLowPriorityHeader(Notification.Builder builder) {
|
||||
private void recreateLowPriorityHeader(Notification.Builder builder, boolean isConversation) {
|
||||
RemoteViews header;
|
||||
StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
|
||||
if (mIsLowPriority) {
|
||||
@@ -362,6 +374,15 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
header.reapply(getContext(), mNotificationHeaderLowPriority);
|
||||
}
|
||||
mNotificationHeaderWrapperLowPriority.onContentUpdated(mContainingNotification);
|
||||
if (mNotificationHeaderWrapper instanceof NotificationHeaderViewWrapper) {
|
||||
NotificationHeaderViewWrapper headerWrapper =
|
||||
(NotificationHeaderViewWrapper) mNotificationHeaderWrapper;
|
||||
if (isConversation) {
|
||||
headerWrapper.applyConversationSkin();
|
||||
} else {
|
||||
headerWrapper.clearConversationSkin();
|
||||
}
|
||||
}
|
||||
resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, calculateDesiredHeader());
|
||||
} else {
|
||||
removeView(mNotificationHeaderLowPriority);
|
||||
@@ -378,7 +399,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
|
||||
if (mUntruncatedChildCount > maxAllowedVisibleChildren) {
|
||||
int number = mUntruncatedChildCount - maxAllowedVisibleChildren;
|
||||
mOverflowNumber = mHybridGroupManager.bindOverflowNumber(mOverflowNumber, number);
|
||||
mOverflowNumber = mHybridGroupManager.bindOverflowNumber(mOverflowNumber, number, this);
|
||||
if (mGroupOverFlowState == null) {
|
||||
mGroupOverFlowState = new ViewState();
|
||||
mNeverAppliedGroupState = true;
|
||||
@@ -1141,7 +1162,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
removeView(mNotificationHeaderLowPriority);
|
||||
mNotificationHeaderLowPriority = null;
|
||||
}
|
||||
recreateNotificationHeader(listener);
|
||||
recreateNotificationHeader(listener, mIsConversation);
|
||||
initDimens();
|
||||
for (int i = 0; i < mDividers.size(); i++) {
|
||||
View prevDivider = mDividers.get(i);
|
||||
@@ -1225,7 +1246,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
public void setIsLowPriority(boolean isLowPriority) {
|
||||
mIsLowPriority = isLowPriority;
|
||||
if (mContainingNotification != null) { /* we're not yet set up yet otherwise */
|
||||
recreateLowPriorityHeader(null /* existingBuilder */);
|
||||
recreateLowPriorityHeader(null /* existingBuilder */, mIsConversation);
|
||||
updateHeaderVisibility(false /* animate */);
|
||||
}
|
||||
if (mUserLocked) {
|
||||
|
||||
@@ -146,7 +146,7 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testRecreateNotificationHeader_hasHeader() {
|
||||
mChildrenContainer.recreateNotificationHeader(null);
|
||||
mChildrenContainer.recreateNotificationHeader(null, false);
|
||||
Assert.assertNotNull("Children container must have a header after recreation",
|
||||
mChildrenContainer.getCurrentHeaderView());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user