1b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek/* 2b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * Copyright (C) 2015 The Android Open Source Project 3b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * 4b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * Licensed under the Apache License, Version 2.0 (the "License"); 5b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * you may not use this file except in compliance with the License. 6b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * You may obtain a copy of the License at 7b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * 8b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * http://www.apache.org/licenses/LICENSE-2.0 9b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * 10b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * Unless required by applicable law or agreed to in writing, software 11b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * distributed under the License is distributed on an "AS IS" BASIS, 12b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * See the License for the specific language governing permissions and 14b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * limitations under the License 15b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek */ 16b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 17b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekpackage com.android.systemui.statusbar.stack; 18b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 19b0a824687f56b6950338aad169d8d837f8ed657bMady Mellorimport android.app.Notification; 20b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport android.content.Context; 21a3d3b91a6eb1db65b52f12442973a1820754c8c0Selim Cinekimport android.content.res.Configuration; 22b0a824687f56b6950338aad169d8d837f8ed657bMady Mellorimport android.graphics.drawable.ColorDrawable; 23b0a824687f56b6950338aad169d8d837f8ed657bMady Mellorimport android.service.notification.StatusBarNotification; 24b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport android.util.AttributeSet; 25b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport android.view.LayoutInflater; 26b0a824687f56b6950338aad169d8d837f8ed657bMady Mellorimport android.view.NotificationHeaderView; 27b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport android.view.View; 28b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport android.view.ViewGroup; 29b0a824687f56b6950338aad169d8d837f8ed657bMady Mellorimport android.widget.RemoteViews; 30c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinekimport android.widget.TextView; 31b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 32b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport com.android.systemui.R; 339c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport com.android.systemui.ViewInvertHelper; 347b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinekimport com.android.systemui.statusbar.CrossFadeHelper; 35b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport com.android.systemui.statusbar.ExpandableNotificationRow; 36b0a824687f56b6950338aad169d8d837f8ed657bMady Mellorimport com.android.systemui.statusbar.NotificationHeaderUtil; 37c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinekimport com.android.systemui.statusbar.notification.HybridGroupManager; 3883bc78338437a460076a4b5778ded38440ac3501Selim Cinekimport com.android.systemui.statusbar.notification.HybridNotificationView; 3942357e030c095867b95e2e8a718649587c5ebf52Selim Cinekimport com.android.systemui.statusbar.notification.NotificationUtils; 40b0a824687f56b6950338aad169d8d837f8ed657bMady Mellorimport com.android.systemui.statusbar.notification.NotificationViewWrapper; 41add9526b1dd91360d0413296f2dbcb2053480162Selim Cinekimport com.android.systemui.statusbar.notification.VisualStabilityManager; 429c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport com.android.systemui.statusbar.phone.NotificationPanelView; 43b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 44b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport java.util.ArrayList; 45b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekimport java.util.List; 46b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 47b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek/** 48b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * A container containing child notifications 49b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek */ 50b5605e58cb8080c8c887b1885336b707596c8094Selim Cinekpublic class NotificationChildrenContainer extends ViewGroup { 51b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 5283bc78338437a460076a4b5778ded38440ac3501Selim Cinek private static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2; 5383bc78338437a460076a4b5778ded38440ac3501Selim Cinek private static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5; 5483bc78338437a460076a4b5778ded38440ac3501Selim Cinek private static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8; 5583bc78338437a460076a4b5778ded38440ac3501Selim Cinek 56b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek private final List<View> mDividers = new ArrayList<>(); 57b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek private final List<ExpandableNotificationRow> mChildren = new ArrayList<>(); 58c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek private final HybridGroupManager mHybridGroupManager; 5901af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek private int mChildPadding; 6001af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek private int mDividerHeight; 6101af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek private int mMaxNotificationHeight; 62b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor private int mNotificationHeaderMargin; 6301af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek private int mNotificatonTopPadding; 6401af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek private float mCollapsedBottompadding; 65c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek private ViewInvertHelper mOverflowInvertHelper; 6683bc78338437a460076a4b5778ded38440ac3501Selim Cinek private boolean mChildrenExpanded; 6783bc78338437a460076a4b5778ded38440ac3501Selim Cinek private ExpandableNotificationRow mNotificationParent; 68c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek private TextView mOverflowNumber; 69c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek private ViewState mGroupOverFlowState; 70a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek private int mRealHeight; 7142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek private boolean mUserLocked; 7242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek private int mActualHeight; 73c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek private boolean mNeverAppliedGroupState; 74b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor private int mHeaderHeight; 75b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 76b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor private NotificationHeaderView mNotificationHeader; 77b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor private NotificationViewWrapper mNotificationHeaderWrapper; 78b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor private NotificationHeaderUtil mHeaderUtil; 79b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor private ViewState mHeaderViewState; 80b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 81b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public NotificationChildrenContainer(Context context) { 82b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek this(context, null); 83b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 84b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 85b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public NotificationChildrenContainer(Context context, AttributeSet attrs) { 86b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek this(context, attrs, 0); 87b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 88b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 89b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public NotificationChildrenContainer(Context context, AttributeSet attrs, int defStyleAttr) { 90b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek this(context, attrs, defStyleAttr, 0); 91b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 92b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 93b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public NotificationChildrenContainer(Context context, AttributeSet attrs, int defStyleAttr, 94b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int defStyleRes) { 95b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek super(context, attrs, defStyleAttr, defStyleRes); 9601af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek initDimens(); 97c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mHybridGroupManager = new HybridGroupManager(getContext(), this); 9801af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek } 9901af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek 10001af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek private void initDimens() { 101b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek mChildPadding = getResources().getDimensionPixelSize( 102b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek R.dimen.notification_children_padding); 103cacc604115f1c05d700e5cd4fef7b0ac2bacb629Selim Cinek mDividerHeight = Math.max(1, getResources().getDimensionPixelSize( 104cacc604115f1c05d700e5cd4fef7b0ac2bacb629Selim Cinek R.dimen.notification_divider_height)); 105b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mHeaderHeight = getResources().getDimensionPixelSize(R.dimen.notification_header_height); 106b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek mMaxNotificationHeight = getResources().getDimensionPixelSize( 107b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek R.dimen.notification_max_height); 108b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeaderMargin = getResources().getDimensionPixelSize( 1097b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek com.android.internal.R.dimen.notification_content_margin_top); 1107b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek mNotificatonTopPadding = getResources().getDimensionPixelSize( 1117b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek R.dimen.notification_children_container_top_padding); 112c0fac72d3c84b6a1a1c82abfa9a74957b11fadc6Selim Cinek mCollapsedBottompadding = getResources().getDimensionPixelSize( 113c0fac72d3c84b6a1a1c82abfa9a74957b11fadc6Selim Cinek com.android.internal.R.dimen.notification_content_margin_bottom); 114b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 115b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 116b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek @Override 117b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek protected void onLayout(boolean changed, int l, int t, int r, int b) { 118471e31aa9bee64abc189fcc3518292a004960d2fSelim Cinek int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED); 119b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek for (int i = 0; i < childCount; i++) { 120b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek View child = mChildren.get(i); 121fa760d46369f1ee7baedd174cc8f973594c52970Selim Cinek // We need to layout all children even the GONE ones, such that the heights are 122fa760d46369f1ee7baedd174cc8f973594c52970Selim Cinek // calculated correctly as they are used to calculate how many we can fit on the screen 123c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); 1247b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek mDividers.get(i).layout(0, 0, getWidth(), mDividerHeight); 125b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 126c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mOverflowNumber != null) { 12709b7dea5b7613e3c96e46006a7b62e2ff84e77f2Selim Cinek boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; 12809b7dea5b7613e3c96e46006a7b62e2ff84e77f2Selim Cinek int left = (isRtl ? 0 : getWidth() - mOverflowNumber.getMeasuredWidth()); 12909b7dea5b7613e3c96e46006a7b62e2ff84e77f2Selim Cinek int right = left + mOverflowNumber.getMeasuredWidth(); 13009b7dea5b7613e3c96e46006a7b62e2ff84e77f2Selim Cinek mOverflowNumber.layout(left, 0, right, mOverflowNumber.getMeasuredHeight()); 131c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 132b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader != null) { 133b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(), 134b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader.getMeasuredHeight()); 135b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 136b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 137b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 138b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek @Override 139b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 140b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int ownMaxHeight = mMaxNotificationHeight; 141b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int heightMode = MeasureSpec.getMode(heightMeasureSpec); 142b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY; 143b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST; 144a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek int size = MeasureSpec.getSize(heightMeasureSpec); 145b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek if (hasFixedHeight || isHeightLimited) { 146b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek ownMaxHeight = Math.min(ownMaxHeight, size); 147b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 148b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST); 149c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek int width = MeasureSpec.getSize(widthMeasureSpec); 150c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mOverflowNumber != null) { 151c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mOverflowNumber.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), 152c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek newHeightSpec); 153c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 154b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY); 155b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int height = mNotificationHeaderMargin + mNotificatonTopPadding; 156471e31aa9bee64abc189fcc3518292a004960d2fSelim Cinek int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED); 157c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */); 158c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1; 159b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek for (int i = 0; i < childCount; i++) { 160c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 161fa760d46369f1ee7baedd174cc8f973594c52970Selim Cinek // We need to measure all children even the GONE ones, such that the heights are 162fa760d46369f1ee7baedd174cc8f973594c52970Selim Cinek // calculated correctly as they are used to calculate how many we can fit on the screen. 163c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek boolean isOverflow = i == overflowIndex; 164b41b2f6fc2bcce6da6d6ae855a2a36cfa6f7f99dSelim Cinek child.setSingleLineWidthIndention(isOverflow && mOverflowNumber != null 165b41b2f6fc2bcce6da6d6ae855a2a36cfa6f7f99dSelim Cinek ? mOverflowNumber.getMeasuredWidth() 166b41b2f6fc2bcce6da6d6ae855a2a36cfa6f7f99dSelim Cinek : 0); 167b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek child.measure(widthMeasureSpec, newHeightSpec); 1687b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek // layout the divider 1697b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek View divider = mDividers.get(i); 1707b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek divider.measure(widthMeasureSpec, dividerHeightSpec); 171fa760d46369f1ee7baedd174cc8f973594c52970Selim Cinek if (child.getVisibility() != GONE) { 172fa760d46369f1ee7baedd174cc8f973594c52970Selim Cinek height += child.getMeasuredHeight() + mDividerHeight; 173fa760d46369f1ee7baedd174cc8f973594c52970Selim Cinek } 174b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 175a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek mRealHeight = height; 176a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek if (heightMode != MeasureSpec.UNSPECIFIED) { 177a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek height = Math.min(height, size); 178a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek } 179b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 180b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader != null) { 181b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY); 182b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader.measure(widthMeasureSpec, headerHeightSpec); 183b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 184b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 185b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek setMeasuredDimension(width, height); 186b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 187b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 188a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek @Override 189a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek public boolean pointInView(float localX, float localY, float slop) { 190a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) && 191a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek localY < (mRealHeight + slop); 192a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek } 193a69f2a6449b4b5eceae9cd5a6b1aae6eeec379b8Selim Cinek 194b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek /** 195b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * Add a child notification to this view. 196b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * 197b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * @param row the row to add 198b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * @param childIndex the index to add it at, if -1 it will be added at the end 199b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek */ 200b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public void addNotification(ExpandableNotificationRow row, int childIndex) { 201b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int newIndex = childIndex < 0 ? mChildren.size() : childIndex; 202b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek mChildren.add(newIndex, row); 203b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek addView(row); 2048e0c4981656a7def112b10c1bec8e9a00142aa52Selim Cinek row.setUserLocked(mUserLocked); 2057b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek 2067b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek View divider = inflateDivider(); 2077b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek addView(divider); 2087b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek mDividers.add(newIndex, divider); 209c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek 210c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek updateGroupOverflow(); 211b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 212b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 213b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public void removeNotification(ExpandableNotificationRow row) { 214b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int childIndex = mChildren.indexOf(row); 215b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek mChildren.remove(row); 216b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek removeView(row); 2177b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek 2187b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinek final View divider = mDividers.remove(childIndex); 2197b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek removeView(divider); 2207b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinek getOverlay().add(divider); 2217b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinek CrossFadeHelper.fadeOut(divider, new Runnable() { 2227b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinek @Override 2237b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinek public void run() { 2247b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinek getOverlay().remove(divider); 2257b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinek } 2267b73a4c1d325fc1a2e54addbd220b3c7c6f3ff73Selim Cinek }); 2277b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek 228b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek row.setSystemChildExpanded(false); 2298e0c4981656a7def112b10c1bec8e9a00142aa52Selim Cinek row.setUserLocked(false); 230c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek updateGroupOverflow(); 231b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (!row.isRemoved()) { 232b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mHeaderUtil.restoreNotificationHeader(row); 233b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 234b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 235b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 236b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor /** 237b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * @return The number of notification children in the container. 238b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor */ 239b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public int getNotificationChildCount() { 240b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor return mChildren.size(); 241b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 242b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 243b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public void recreateNotificationHeader(OnClickListener listener, StatusBarNotification notification) { 244b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(), 245b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationParent.getStatusBarNotification().getNotification()); 246b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor final RemoteViews header = builder.makeNotificationHeader(); 247b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader == null) { 248b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this); 249b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor final View expandButton = mNotificationHeader.findViewById( 250b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor com.android.internal.R.id.expand_button); 251b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor expandButton.setVisibility(VISIBLE); 252b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader.setOnClickListener(listener); 253b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(), 254b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader, mNotificationParent); 255b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor addView(mNotificationHeader, 0); 256b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor invalidate(); 257b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } else { 258b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor header.reapply(getContext(), mNotificationHeader); 259b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeaderWrapper.notifyContentUpdated(notification); 260b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 261b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor updateChildrenHeaderAppearance(); 262b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 263b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 264b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public void updateChildrenHeaderAppearance() { 265b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mHeaderUtil.updateChildrenHeaderAppearance(); 266c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 267c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek 268c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek public void updateGroupOverflow() { 269c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek int childCount = mChildren.size(); 270c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */); 271c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (childCount > maxAllowedVisibleChildren) { 272c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mOverflowNumber = mHybridGroupManager.bindOverflowNumber( 273c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mOverflowNumber, childCount - maxAllowedVisibleChildren); 274c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mOverflowInvertHelper == null) { 275b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mOverflowInvertHelper = new ViewInvertHelper(mOverflowNumber, 276c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek NotificationPanelView.DOZE_ANIMATION_DURATION); 277c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 278c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mGroupOverFlowState == null) { 279c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mGroupOverFlowState = new ViewState(); 280c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mNeverAppliedGroupState = true; 281c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 282c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } else if (mOverflowNumber != null) { 283c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek removeView(mOverflowNumber); 284c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (isShown()) { 285c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek final View removedOverflowNumber = mOverflowNumber; 286c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek addTransientView(removedOverflowNumber, getTransientViewCount()); 287c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek CrossFadeHelper.fadeOut(removedOverflowNumber, new Runnable() { 288c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek @Override 289c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek public void run() { 290c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek removeTransientView(removedOverflowNumber); 291c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 292c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek }); 293c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 294c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mOverflowNumber = null; 295c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mOverflowInvertHelper = null; 296c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mGroupOverFlowState = null; 297c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 298b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 299b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 300a3d3b91a6eb1db65b52f12442973a1820754c8c0Selim Cinek @Override 301a3d3b91a6eb1db65b52f12442973a1820754c8c0Selim Cinek protected void onConfigurationChanged(Configuration newConfig) { 302a3d3b91a6eb1db65b52f12442973a1820754c8c0Selim Cinek super.onConfigurationChanged(newConfig); 303c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek updateGroupOverflow(); 304a3d3b91a6eb1db65b52f12442973a1820754c8c0Selim Cinek } 305a3d3b91a6eb1db65b52f12442973a1820754c8c0Selim Cinek 306b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek private View inflateDivider() { 307b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek return LayoutInflater.from(mContext).inflate( 308b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek R.layout.notification_children_divider, this, false); 309b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 310b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 311b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public List<ExpandableNotificationRow> getNotificationChildren() { 312b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek return mChildren; 313b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 314b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 315b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek /** 316b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * Apply the order given in the list to the children. 317b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * 318b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * @param childOrder the new list order 319add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek * @param visualStabilityManager 320add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek * @param callback 321b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * @return whether the list order has changed 322b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek */ 323add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder, 324add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek VisualStabilityManager visualStabilityManager, 325add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek VisualStabilityManager.Callback callback) { 326b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek if (childOrder == null) { 327b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek return false; 328b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 329b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek boolean result = false; 330b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek for (int i = 0; i < mChildren.size() && i < childOrder.size(); i++) { 331b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 332b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek ExpandableNotificationRow desiredChild = childOrder.get(i); 333b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek if (child != desiredChild) { 334add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek if (visualStabilityManager.canReorderNotification(desiredChild)) { 335add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek mChildren.remove(desiredChild); 336add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek mChildren.add(i, desiredChild); 337add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek result = true; 338add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek } else { 339add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek visualStabilityManager.addReorderingAllowedCallback(callback); 340add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek } 341b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 342b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 34383bc78338437a460076a4b5778ded38440ac3501Selim Cinek updateExpansionStates(); 34483bc78338437a460076a4b5778ded38440ac3501Selim Cinek return result; 34583bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 346b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 34783bc78338437a460076a4b5778ded38440ac3501Selim Cinek private void updateExpansionStates() { 348898d173b92fb78d56bce208da31808d0852c7762Selim Cinek if (mChildrenExpanded || mUserLocked) { 349898d173b92fb78d56bce208da31808d0852c7762Selim Cinek // we don't modify it the group is expanded or if we are expanding it 350898d173b92fb78d56bce208da31808d0852c7762Selim Cinek return; 351898d173b92fb78d56bce208da31808d0852c7762Selim Cinek } 352898d173b92fb78d56bce208da31808d0852c7762Selim Cinek int size = mChildren.size(); 353898d173b92fb78d56bce208da31808d0852c7762Selim Cinek for (int i = 0; i < size; i++) { 35483bc78338437a460076a4b5778ded38440ac3501Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 355898d173b92fb78d56bce208da31808d0852c7762Selim Cinek child.setSystemChildExpanded(i == 0 && size == 1); 356b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 357b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 358b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 35983bc78338437a460076a4b5778ded38440ac3501Selim Cinek /** 36083bc78338437a460076a4b5778ded38440ac3501Selim Cinek * 36183bc78338437a460076a4b5778ded38440ac3501Selim Cinek * @return the intrinsic size of this children container, i.e the natural fully expanded state 36283bc78338437a460076a4b5778ded38440ac3501Selim Cinek */ 363b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public int getIntrinsicHeight() { 36483bc78338437a460076a4b5778ded38440ac3501Selim Cinek int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(); 36583bc78338437a460076a4b5778ded38440ac3501Selim Cinek return getIntrinsicHeight(maxAllowedVisibleChildren); 36683bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 36783bc78338437a460076a4b5778ded38440ac3501Selim Cinek 36883bc78338437a460076a4b5778ded38440ac3501Selim Cinek /** 36983bc78338437a460076a4b5778ded38440ac3501Selim Cinek * @return the intrinsic height with a number of children given 37083bc78338437a460076a4b5778ded38440ac3501Selim Cinek * in @param maxAllowedVisibleChildren 37183bc78338437a460076a4b5778ded38440ac3501Selim Cinek */ 37283bc78338437a460076a4b5778ded38440ac3501Selim Cinek private int getIntrinsicHeight(float maxAllowedVisibleChildren) { 373b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int intrinsicHeight = mNotificationHeaderMargin; 374b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int visibleChildren = 0; 37583bc78338437a460076a4b5778ded38440ac3501Selim Cinek int childCount = mChildren.size(); 37642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek boolean firstChild = true; 37742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek float expandFactor = 0; 37842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked) { 379f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek expandFactor = getGroupExpandFraction(); 38042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 381b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek for (int i = 0; i < childCount; i++) { 38283bc78338437a460076a4b5778ded38440ac3501Selim Cinek if (visibleChildren >= maxAllowedVisibleChildren) { 38383bc78338437a460076a4b5778ded38440ac3501Selim Cinek break; 38483bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 38542357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (!firstChild) { 38642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked) { 38742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek intrinsicHeight += NotificationUtils.interpolate(mChildPadding, mDividerHeight, 38842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek expandFactor); 38942357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } else { 39042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek intrinsicHeight += mChildrenExpanded ? mDividerHeight : mChildPadding; 39142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 39242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } else { 39342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked) { 39442357e030c095867b95e2e8a718649587c5ebf52Selim Cinek intrinsicHeight += NotificationUtils.interpolate( 39542357e030c095867b95e2e8a718649587c5ebf52Selim Cinek 0, 39642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek mNotificatonTopPadding + mDividerHeight, 39742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek expandFactor); 39842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } else { 39942357e030c095867b95e2e8a718649587c5ebf52Selim Cinek intrinsicHeight += mChildrenExpanded 40042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek ? mNotificatonTopPadding + mDividerHeight 40142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek : 0; 40242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 40342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek firstChild = false; 40442357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 405b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 406b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek intrinsicHeight += child.getIntrinsicHeight(); 407b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek visibleChildren++; 408b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 40942357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked) { 41042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek intrinsicHeight += NotificationUtils.interpolate(mCollapsedBottompadding, 0.0f, 41142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek expandFactor); 41242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } else if (!mChildrenExpanded) { 41383bc78338437a460076a4b5778ded38440ac3501Selim Cinek intrinsicHeight += mCollapsedBottompadding; 41483bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 415b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek return intrinsicHeight; 416b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 417b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 418b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek /** 419b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * Update the state of all its children based on a linear layout algorithm. 420b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * 421b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * @param resultState the state to update 422b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * @param parentState the state of the parent 423b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek */ 424b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public void getState(StackScrollState resultState, StackViewState parentState) { 425b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int childCount = mChildren.size(); 426b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int yPosition = mNotificationHeaderMargin; 427b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek boolean firstChild = true; 42883bc78338437a460076a4b5778ded38440ac3501Selim Cinek int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(); 42991c2a15838403342302b230b1dbe66bb0eeceee0Selim Cinek int lastVisibleIndex = maxAllowedVisibleChildren - 1; 430f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek int firstOverflowIndex = lastVisibleIndex + 1; 43142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek float expandFactor = 0; 43242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked) { 433f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek expandFactor = getGroupExpandFraction(); 434f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */); 43542357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 436b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 437b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging() 438b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor && mChildrenExpanded; 439b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int parentHeight = parentState.height; 440b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek for (int i = 0; i < childCount; i++) { 441b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 442b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek if (!firstChild) { 44342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked) { 444b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight, 445b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor expandFactor); 44642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } else { 44742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding; 44842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 449b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } else { 45042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked) { 45142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek yPosition += NotificationUtils.interpolate( 45242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek 0, 45342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek mNotificatonTopPadding + mDividerHeight, 45442357e030c095867b95e2e8a718649587c5ebf52Selim Cinek expandFactor); 45542357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } else { 45642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek yPosition += mChildrenExpanded ? mNotificatonTopPadding + mDividerHeight : 0; 45742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 458b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek firstChild = false; 459b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 460b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 461b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek StackViewState childState = resultState.getViewStateForView(child); 462b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int intrinsicHeight = child.getIntrinsicHeight(); 463b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (childrenExpanded) { 464b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor // When a group is expanded and moving into bottom stack, the bottom visible child 465b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor // adjusts its height to move into it. Children after it are hidden. 466b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (updateChildStateForExpandedGroup(child, parentHeight, childState, yPosition)) { 467b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor // Clipping might be deactivated if the view is transforming, however, clipping 468b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor // the child into the bottom stack should take precedent over this. 469b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor childState.isBottomClipped = true; 470b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 471b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } else { 472b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor childState.hidden = false; 473b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor childState.height = intrinsicHeight; 474b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor childState.isBottomClipped = false; 475b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 476b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek childState.yTranslation = yPosition; 477b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor // When the group is expanded, the children cast the shadows rather than the parent 478b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor // so use the parent's elevation here. 479b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor childState.zTranslation = childrenExpanded 480b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor ? mNotificationParent.getTranslationZ() 481b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor : 0; 482b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek childState.dimmed = parentState.dimmed; 483b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek childState.dark = parentState.dark; 484b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek childState.hideSensitive = parentState.hideSensitive; 485b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek childState.belowSpeedBump = parentState.belowSpeedBump; 486b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek childState.clipTopAmount = 0; 487f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek childState.alpha = 0; 488f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek if (i < firstOverflowIndex) { 489f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek childState.alpha = 1; 490f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek } else if (expandFactor == 1.0f && i <= lastVisibleIndex) { 491f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek childState.alpha = (mActualHeight - childState.yTranslation) / childState.height; 492f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek childState.alpha = Math.max(0.0f, Math.min(1.0f, childState.alpha)); 493f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek } 494b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek childState.location = parentState.location; 495b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek yPosition += intrinsicHeight; 496add9526b1dd91360d0413296f2dbcb2053480162Selim Cinek 497b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 498c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mOverflowNumber != null) { 499c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek ExpandableNotificationRow overflowView = mChildren.get(Math.min( 500c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek getMaxAllowedVisibleChildren(true /* likeCollpased */), childCount) - 1); 501c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mGroupOverFlowState.copyFrom(resultState.getViewStateForView(overflowView)); 502c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (!mChildrenExpanded) { 503c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mUserLocked) { 504c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek HybridNotificationView singleLineView = overflowView.getSingleLineView(); 505c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek View mirrorView = singleLineView.getTextView(); 506c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mirrorView.getVisibility() == GONE) { 507c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mirrorView = singleLineView.getTitleView(); 508c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 509c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mirrorView.getVisibility() == GONE) { 510c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mirrorView = singleLineView; 511c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 512c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mGroupOverFlowState.yTranslation += NotificationUtils.getRelativeYOffset( 513c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mirrorView, overflowView); 514c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mGroupOverFlowState.alpha = mirrorView.getAlpha(); 515c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 516c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } else { 517b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mGroupOverFlowState.yTranslation += mNotificationHeaderMargin; 518c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mGroupOverFlowState.alpha = 0.0f; 519c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 520c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 521b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader != null) { 522b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mHeaderViewState == null) { 523b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mHeaderViewState = new ViewState(); 524b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 525b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mHeaderViewState.initFrom(mNotificationHeader); 526b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mHeaderViewState.zTranslation = childrenExpanded 527b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor ? mNotificationParent.getTranslationZ() 528b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor : 0; 529b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 530b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 531b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 532b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor /** 533b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * When moving into the bottom stack, the bottom visible child in an expanded group adjusts its 534b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * height, children in the group after this are gone. 535b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * 536b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * @param child the child who's height to adjust. 537b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * @param parentHeight the height of the parent. 538b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * @param childState the state to update. 539b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * @param yPosition the yPosition of the view. 540b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * @return true if children after this one should be hidden. 541b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor */ 542b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor private boolean updateChildStateForExpandedGroup(ExpandableNotificationRow child, 543b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int parentHeight, StackViewState childState, int yPosition) { 544b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor final int top = yPosition + child.getClipTopAmount(); 545b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor final int intrinsicHeight = child.getIntrinsicHeight(); 546b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor final int bottom = top + intrinsicHeight; 547b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int newHeight = intrinsicHeight; 548b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (bottom >= parentHeight) { 549b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor // Child is either clipped or gone 550b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor newHeight = Math.max((parentHeight - top), 0); 551b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 552b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor childState.hidden = newHeight == 0; 553b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor childState.height = newHeight; 554b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor return childState.height != intrinsicHeight && !childState.hidden; 55583bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 55683bc78338437a460076a4b5778ded38440ac3501Selim Cinek 55783bc78338437a460076a4b5778ded38440ac3501Selim Cinek private int getMaxAllowedVisibleChildren() { 55883bc78338437a460076a4b5778ded38440ac3501Selim Cinek return getMaxAllowedVisibleChildren(false /* likeCollapsed */); 55983bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 56083bc78338437a460076a4b5778ded38440ac3501Selim Cinek 56183bc78338437a460076a4b5778ded38440ac3501Selim Cinek private int getMaxAllowedVisibleChildren(boolean likeCollapsed) { 56283bc78338437a460076a4b5778ded38440ac3501Selim Cinek if (!likeCollapsed && (mChildrenExpanded || mNotificationParent.isUserLocked())) { 56383bc78338437a460076a4b5778ded38440ac3501Selim Cinek return NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED; 56483bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 565f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek if (!mNotificationParent.isOnKeyguard() 566f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek && (mNotificationParent.isExpanded() || mNotificationParent.isHeadsUp())) { 56783bc78338437a460076a4b5778ded38440ac3501Selim Cinek return NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED; 56883bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 56983bc78338437a460076a4b5778ded38440ac3501Selim Cinek return NUMBER_OF_CHILDREN_WHEN_COLLAPSED; 570b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 571b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 572b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public void applyState(StackScrollState state) { 573b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int childCount = mChildren.size(); 57483bc78338437a460076a4b5778ded38440ac3501Selim Cinek ViewState tmpState = new ViewState(); 575c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek float expandFraction = 0.0f; 576c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mUserLocked) { 577f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek expandFraction = getGroupExpandFraction(); 578c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 579b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor final boolean dividersVisible = mUserLocked 580b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor || mNotificationParent.isGroupExpansionChanging(); 581b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek for (int i = 0; i < childCount; i++) { 582b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 583b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek StackViewState viewState = state.getViewStateForView(child); 584b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek state.applyState(child, viewState); 5857b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek 5867b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek // layout the divider 5877b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek View divider = mDividers.get(i); 5887b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek tmpState.initFrom(divider); 5897b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek tmpState.yTranslation = viewState.yTranslation - mDividerHeight; 59042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0; 59142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked && viewState.alpha != 0) { 592f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek alpha = NotificationUtils.interpolate(0, 0.5f, 593f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek Math.min(viewState.alpha, expandFraction)); 59442357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 595b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor tmpState.hidden = !dividersVisible; 59642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek tmpState.alpha = alpha; 5977b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek state.applyViewState(divider, tmpState); 598d9a3f8f0f13defda29875de414372ecea9d4c9e0Selim Cinek // There is no fake shadow to be drawn on the children 599d9a3f8f0f13defda29875de414372ecea9d4c9e0Selim Cinek child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0); 600b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 601c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mOverflowNumber != null) { 602c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek state.applyViewState(mOverflowNumber, mGroupOverFlowState); 603c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mNeverAppliedGroupState = false; 604c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 605b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader != null) { 606b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor state.applyViewState(mNotificationHeader, mHeaderViewState); 607b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 608b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 609b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 610b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek /** 611b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * This is called when the children expansion has changed and positions the children properly 612b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * for an appear animation. 613b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * 614b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek * @param state the new state we animate to 615b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek */ 616b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public void prepareExpansionChanged(StackScrollState state) { 617277a8aa409def1a35eb662c974b91c0f133926aaSelim Cinek // TODO: do something that makes sense, like placing the invisible views correctly 618277a8aa409def1a35eb662c974b91c0f133926aaSelim Cinek return; 619b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 620b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 621b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public void startAnimationToState(StackScrollState state, StackStateAnimator stateAnimator, 6229969559da02f54fcbd7832de9810507a581d98d8Selim Cinek long baseDelay, long duration) { 623b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek int childCount = mChildren.size(); 62483bc78338437a460076a4b5778ded38440ac3501Selim Cinek ViewState tmpState = new ViewState(); 625f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek float expandFraction = getGroupExpandFraction(); 626b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor final boolean dividersVisible = mUserLocked 627b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor || mNotificationParent.isGroupExpansionChanging(); 628e812652fba04abc32fd6eeefee3463270f3b9d8eSelim Cinek for (int i = childCount - 1; i >= 0; i--) { 629b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 630b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek StackViewState viewState = state.getViewStateForView(child); 6319969559da02f54fcbd7832de9810507a581d98d8Selim Cinek stateAnimator.startStackAnimations(child, viewState, state, -1, baseDelay); 6327b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek 6337b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek // layout the divider 6347b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek View divider = mDividers.get(i); 6357b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek tmpState.initFrom(divider); 6367b83639c34cb8b52f915099973e0892c5fbfd674Selim Cinek tmpState.yTranslation = viewState.yTranslation - mDividerHeight; 63742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0; 63842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (mUserLocked && viewState.alpha != 0) { 639f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek alpha = NotificationUtils.interpolate(0, 0.5f, 640f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek Math.min(viewState.alpha, expandFraction)); 64142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 642b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor tmpState.hidden = !dividersVisible; 64342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek tmpState.alpha = alpha; 6449969559da02f54fcbd7832de9810507a581d98d8Selim Cinek stateAnimator.startViewAnimations(divider, tmpState, baseDelay, duration); 645d9a3f8f0f13defda29875de414372ecea9d4c9e0Selim Cinek // There is no fake shadow to be drawn on the children 646d9a3f8f0f13defda29875de414372ecea9d4c9e0Selim Cinek child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0); 647b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 648c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mOverflowNumber != null) { 649c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mNeverAppliedGroupState) { 650c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek float alpha = mGroupOverFlowState.alpha; 651c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mGroupOverFlowState.alpha = 0; 652c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek state.applyViewState(mOverflowNumber, mGroupOverFlowState); 653c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mGroupOverFlowState.alpha = alpha; 654c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mNeverAppliedGroupState = false; 655c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 656c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek stateAnimator.startViewAnimations(mOverflowNumber, mGroupOverFlowState, 657c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek baseDelay, duration); 658c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 659b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader != null) { 660b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor state.applyViewState(mNotificationHeader, mHeaderViewState); 661b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 662b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 663b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 664b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek public ExpandableNotificationRow getViewAtPosition(float y) { 665b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek // find the view under the pointer, accounting for GONE views 666b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek final int count = mChildren.size(); 667b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek for (int childIdx = 0; childIdx < count; childIdx++) { 668b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek ExpandableNotificationRow slidingChild = mChildren.get(childIdx); 669b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek float childTop = slidingChild.getTranslationY(); 670b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek float top = childTop + slidingChild.getClipTopAmount(); 671b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek float bottom = childTop + slidingChild.getActualHeight(); 672b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek if (y >= top && y <= bottom) { 673b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek return slidingChild; 674b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 675b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 676b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek return null; 677b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 678b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek 67983bc78338437a460076a4b5778ded38440ac3501Selim Cinek public void setChildrenExpanded(boolean childrenExpanded) { 68083bc78338437a460076a4b5778ded38440ac3501Selim Cinek mChildrenExpanded = childrenExpanded; 681898d173b92fb78d56bce208da31808d0852c7762Selim Cinek updateExpansionStates(); 682b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader != null) { 683b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader.setExpanded(childrenExpanded); 684b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 685ddf1b399d85ca417301625a55b2a3c7acab2633cSelim Cinek final int count = mChildren.size(); 686ddf1b399d85ca417301625a55b2a3c7acab2633cSelim Cinek for (int childIdx = 0; childIdx < count; childIdx++) { 687ddf1b399d85ca417301625a55b2a3c7acab2633cSelim Cinek ExpandableNotificationRow child = mChildren.get(childIdx); 688ddf1b399d85ca417301625a55b2a3c7acab2633cSelim Cinek child.setChildrenExpanded(childrenExpanded, false); 689ddf1b399d85ca417301625a55b2a3c7acab2633cSelim Cinek } 69083bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 69183bc78338437a460076a4b5778ded38440ac3501Selim Cinek 692388df6dd3d07376ecd7446cae36e1486cd313171Selim Cinek public void setNotificationParent(ExpandableNotificationRow parent) { 693388df6dd3d07376ecd7446cae36e1486cd313171Selim Cinek mNotificationParent = parent; 694b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mHeaderUtil = new NotificationHeaderUtil(mNotificationParent); 695b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 696b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 6974a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos public ExpandableNotificationRow getNotificationParent() { 6984a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos return mNotificationParent; 6994a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos } 7004a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos 701b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public NotificationHeaderView getHeaderView() { 702b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor return mNotificationHeader; 703b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 704b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 705b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public void updateHeaderVisibility(int visiblity) { 706b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader != null) { 707b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader.setVisibility(visiblity); 708b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 709b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 710b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 711b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor /** 712b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * Called when a groups expansion changes to adjust the background of the header view. 713b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * 714b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor * @param expanded whether the group is expanded. 715b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor */ 716b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public void updateHeaderForExpansion(boolean expanded) { 717b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mNotificationHeader != null) { 718b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (expanded) { 719b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor ColorDrawable cd = new ColorDrawable(); 720b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor cd.setColor(mNotificationParent.calculateBgColor()); 721b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader.setHeaderBackgroundDrawable(cd); 722b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } else { 723b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader.setHeaderBackgroundDrawable(null); 724b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 725b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 726388df6dd3d07376ecd7446cae36e1486cd313171Selim Cinek } 727388df6dd3d07376ecd7446cae36e1486cd313171Selim Cinek 72883bc78338437a460076a4b5778ded38440ac3501Selim Cinek public int getMaxContentHeight() { 729b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int maxContentHeight = mNotificationHeaderMargin + mNotificatonTopPadding; 73042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek int visibleChildren = 0; 73142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek int childCount = mChildren.size(); 73242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek for (int i = 0; i < childCount; i++) { 73342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) { 73442357e030c095867b95e2e8a718649587c5ebf52Selim Cinek break; 73542357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 73642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 737e81b82ba252582753cb87ba424c82028b6e490ecSelim Cinek float childHeight = child.isExpanded(true /* allowOnKeyguard */) 73842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek ? child.getMaxExpandHeight() 73942357e030c095867b95e2e8a718649587c5ebf52Selim Cinek : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */); 74042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek maxContentHeight += childHeight; 74142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek visibleChildren++; 74242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 74342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (visibleChildren > 0) { 74442357e030c095867b95e2e8a718649587c5ebf52Selim Cinek maxContentHeight += visibleChildren * mDividerHeight; 74542357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 74642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek return maxContentHeight; 74742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 74842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek 74942357e030c095867b95e2e8a718649587c5ebf52Selim Cinek public void setActualHeight(int actualHeight) { 75042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek if (!mUserLocked) { 75142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek return; 75242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 75342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek mActualHeight = actualHeight; 754f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek float fraction = getGroupExpandFraction(); 755f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */); 75642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek int childCount = mChildren.size(); 75742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek for (int i = 0; i < childCount; i++) { 75842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 759e81b82ba252582753cb87ba424c82028b6e490ecSelim Cinek float childHeight = child.isExpanded(true /* allowOnKeyguard */) 76042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek ? child.getMaxExpandHeight() 76142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */); 762f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek if (i < maxAllowedVisibleChildren) { 763f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek float singleLineHeight = child.getShowingLayout().getMinHeight( 764f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek false /* likeGroupExpanded */); 765f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek child.setActualHeight((int) NotificationUtils.interpolate(singleLineHeight, 766f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek childHeight, fraction), false); 767f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek } else { 768f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek child.setActualHeight((int) childHeight, false); 769f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek } 77042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 77142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 77242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek 773f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek public float getGroupExpandFraction() { 774f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek int visibleChildrenExpandedHeight = getVisibleChildrenExpandHeight(); 775567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek int minExpandHeight = getCollapsedHeight(); 776f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek float factor = (mActualHeight - minExpandHeight) 777f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek / (float) (visibleChildrenExpandedHeight - minExpandHeight); 77842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek return Math.max(0.0f, Math.min(1.0f, factor)); 77942357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 78042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek 781f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek private int getVisibleChildrenExpandHeight() { 782b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int intrinsicHeight = mNotificationHeaderMargin + mNotificatonTopPadding + mDividerHeight; 78342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek int visibleChildren = 0; 78442357e030c095867b95e2e8a718649587c5ebf52Selim Cinek int childCount = mChildren.size(); 785f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */); 78642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek for (int i = 0; i < childCount; i++) { 787f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek if (visibleChildren >= maxAllowedVisibleChildren) { 78842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek break; 78942357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 79042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 791f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek float childHeight = child.isExpanded(true /* allowOnKeyguard */) 792f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek ? child.getMaxExpandHeight() 793f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */); 794f07d06212b08939809aa4128f153bd5179f81fc7Selim Cinek intrinsicHeight += childHeight; 79542357e030c095867b95e2e8a718649587c5ebf52Selim Cinek visibleChildren++; 79642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 79742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek return intrinsicHeight; 79883bc78338437a460076a4b5778ded38440ac3501Selim Cinek } 79983bc78338437a460076a4b5778ded38440ac3501Selim Cinek 80083bc78338437a460076a4b5778ded38440ac3501Selim Cinek public int getMinHeight() { 801567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED); 802b55386d64aeb80f74ed21035d1e389d86be89db6Selim Cinek } 803b55386d64aeb80f74ed21035d1e389d86be89db6Selim Cinek 804567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek public int getCollapsedHeight() { 805567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */)); 806567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek } 807567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek 808567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek private int getMinHeight(int maxAllowedVisibleChildren) { 809b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int minExpandHeight = mNotificationHeaderMargin; 8102c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek int visibleChildren = 0; 8112c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek boolean firstChild = true; 8122c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek int childCount = mChildren.size(); 8132c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek for (int i = 0; i < childCount; i++) { 8142c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek if (visibleChildren >= maxAllowedVisibleChildren) { 8152c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek break; 8162c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek } 8172c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek if (!firstChild) { 8182c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek minExpandHeight += mChildPadding; 8192c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek } else { 8202c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek firstChild = false; 8212c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek } 8222c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 823f1f270a09469343abd864f1b02a630a8a15762ffSelim Cinek minExpandHeight += child.getSingleLineView().getHeight(); 8242c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek visibleChildren++; 8252c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek } 8262c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek minExpandHeight += mCollapsedBottompadding; 8272c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek return minExpandHeight; 828b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek } 8299c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 830c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek public void setDark(boolean dark, boolean fade, long delay) { 831c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek if (mOverflowNumber != null) { 832c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mOverflowInvertHelper.setInverted(dark, fade, delay); 833c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 834b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeaderWrapper.setDark(dark, fade, delay); 835c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 836c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek 837b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public void reInflateViews(OnClickListener listener, StatusBarNotification notification) { 838b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor removeView(mNotificationHeader); 839b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mNotificationHeader = null; 840b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor recreateNotificationHeader(listener, notification); 84101af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek initDimens(); 84201af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek for (int i = 0; i < mDividers.size(); i++) { 84301af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek View prevDivider = mDividers.get(i); 84401af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek int index = indexOfChild(prevDivider); 84501af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek removeView(prevDivider); 84601af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek View divider = inflateDivider(); 84701af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek addView(divider, index); 84801af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek mDividers.set(i, divider); 84901af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek } 8504bb593492ccf560382fac9ae533a7429cec53c94Selim Cinek removeView(mOverflowNumber); 8514bb593492ccf560382fac9ae533a7429cec53c94Selim Cinek mOverflowNumber = null; 8524bb593492ccf560382fac9ae533a7429cec53c94Selim Cinek mOverflowInvertHelper = null; 8534bb593492ccf560382fac9ae533a7429cec53c94Selim Cinek mGroupOverFlowState = null; 8544bb593492ccf560382fac9ae533a7429cec53c94Selim Cinek updateGroupOverflow(); 85501af334b70c8ad47c8ce1f465e458863ebe9eae2Selim Cinek } 85642357e030c095867b95e2e8a718649587c5ebf52Selim Cinek 85742357e030c095867b95e2e8a718649587c5ebf52Selim Cinek public void setUserLocked(boolean userLocked) { 85842357e030c095867b95e2e8a718649587c5ebf52Selim Cinek mUserLocked = userLocked; 85942357e030c095867b95e2e8a718649587c5ebf52Selim Cinek int childCount = mChildren.size(); 86042357e030c095867b95e2e8a718649587c5ebf52Selim Cinek for (int i = 0; i < childCount; i++) { 86142357e030c095867b95e2e8a718649587c5ebf52Selim Cinek ExpandableNotificationRow child = mChildren.get(i); 86242357e030c095867b95e2e8a718649587c5ebf52Selim Cinek child.setUserLocked(userLocked); 86342357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 86442357e030c095867b95e2e8a718649587c5ebf52Selim Cinek } 865c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek 866c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek public void onNotificationUpdated() { 867c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mHybridGroupManager.setOverflowNumberColor(mOverflowNumber, 868c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek mNotificationParent.getNotificationColor()); 869c897bd3e91ed442b0f32c3a5b9918e9e580b62b1Selim Cinek } 870d009ab1e2a57648cac9de93912964e2a36ae1762Adrian Roos 8714a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos public int getPositionInLinearLayout(View childInGroup) { 8724a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos int position = mNotificationHeaderMargin + mNotificatonTopPadding; 8734a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos 8744a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos for (int i = 0; i < mChildren.size(); i++) { 8754a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos ExpandableNotificationRow child = mChildren.get(i); 8764a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos boolean notGone = child.getVisibility() != View.GONE; 8774a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos if (notGone) { 8784a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos position += mDividerHeight; 8794a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos } 8804a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos if (child == childInGroup) { 8814a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos return position; 8824a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos } 8834a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos if (notGone) { 8844a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos position += child.getIntrinsicHeight(); 8854a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos } 8864a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos } 8874a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos return 0; 8884a5796765041dcb45ce782fc7ec5866b89fe0df0Adrian Roos } 889b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek} 890