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