ExpandableNotificationRow.java revision d2319fbe6a53ac4c38ca02e4d8e32da86ed0994b
151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren/* 251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * Copyright (C) 2013 The Android Open Source Project 351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * 451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * Licensed under the Apache License, Version 2.0 (the "License"); 551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * you may not use this file except in compliance with the License. 651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * You may obtain a copy of the License at 751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * 851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * http://www.apache.org/licenses/LICENSE-2.0 951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * 1051c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * Unless required by applicable law or agreed to in writing, software 1151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * distributed under the License is distributed on an "AS IS" BASIS, 1251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * See the License for the specific language governing permissions and 1451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren * limitations under the License. 1551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren */ 1651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 1751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wrenpackage com.android.systemui.statusbar; 1851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 1951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wrenimport android.content.Context; 2051c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wrenimport android.util.AttributeSet; 21a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandlerimport android.view.View; 22fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggiimport android.view.accessibility.AccessibilityEvent; 2351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 24a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandlerimport com.android.systemui.R; 25a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler 264222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggipublic class ExpandableNotificationRow extends ActivatableNotificationView { 271685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private int mRowMinHeight; 281685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private int mRowMaxHeight; 2951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 301685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** Does this row contain layouts that can adapt to row expansion */ 3151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren private boolean mExpandable; 321685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** Has the user actively changed the expansion state of this row */ 331685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private boolean mHasUserChangedExpansion; 341685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */ 3551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren private boolean mUserExpanded; 361685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** Is the user touching this row */ 3751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren private boolean mUserLocked; 381685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** Are we showing the "public" version */ 39a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler private boolean mShowingPublic; 40ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi private boolean mSensitive; 41ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi private boolean mShowingPublicInitialized; 42ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi private boolean mShowingPublicForIntrinsicHeight; 4351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 441685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 451685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Is this notification expanded by the system. The expansion state can be overridden by the 461685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * user expansion. 471685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 481685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private boolean mIsSystemExpanded; 49dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi 50dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi /** 51dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi * Whether the notification expansion is disabled. This is the case on Keyguard. 52dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi */ 53dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi private boolean mExpansionDisabled; 54dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi 55be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi private NotificationContentView mPublicLayout; 56be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi private NotificationContentView mPrivateLayout; 571685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private int mMaxExpandHeight; 58863834bd96bdebcf21f4c4a7d8285d4858c061e4Selim Cinek private View mVetoButton; 590d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler private boolean mClearable; 6078403d79739605511ea88b653564d81d7bf4bbbaChris Wren private ExpansionLogger mLogger; 6178403d79739605511ea88b653564d81d7bf4bbbaChris Wren private String mLoggingKey; 62a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek private boolean mWasReset; 6378403d79739605511ea88b653564d81d7bf4bbbaChris Wren 6478403d79739605511ea88b653564d81d7bf4bbbaChris Wren public interface ExpansionLogger { 6578403d79739605511ea88b653564d81d7bf4bbbaChris Wren public void logNotificationExpansion(String key, boolean userAction, boolean expanded); 6678403d79739605511ea88b653564d81d7bf4bbbaChris Wren } 671685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 6851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public ExpandableNotificationRow(Context context, AttributeSet attrs) { 6951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren super(context, attrs); 7051c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 7151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 72a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer /** 73a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer * Resets this view so it can be re-used for an updated notification. 74a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer */ 7522f2ee567dd1b1a42432251229bcb2f05c1c4700Christoph Studer @Override 76a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer public void reset() { 7722f2ee567dd1b1a42432251229bcb2f05c1c4700Christoph Studer super.reset(); 78a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mRowMinHeight = 0; 7978403d79739605511ea88b653564d81d7bf4bbbaChris Wren final boolean wasExpanded = isExpanded(); 80a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mRowMaxHeight = 0; 81a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mExpandable = false; 82a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mHasUserChangedExpansion = false; 83a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mUserLocked = false; 84a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mShowingPublic = false; 85ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mSensitive = false; 86ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mShowingPublicInitialized = false; 87a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mIsSystemExpanded = false; 88a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mExpansionDisabled = false; 89a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mPublicLayout.reset(); 90a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mPrivateLayout.reset(); 9131094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek resetHeight(); 9231094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek logExpansionEvent(false, wasExpanded); 9331094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek } 9431094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek 9531094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek public void resetHeight() { 96a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer mMaxExpandHeight = 0; 97a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek mWasReset = true; 9831094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek onHeightReset(); 99a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer } 100a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer 101251957d76e57eb6e5f8068b37346144e10e586a4Jorim Jaggi @Override 102251957d76e57eb6e5f8068b37346144e10e586a4Jorim Jaggi protected void onFinishInflate() { 103251957d76e57eb6e5f8068b37346144e10e586a4Jorim Jaggi super.onFinishInflate(); 104be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic); 105be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded); 106863834bd96bdebcf21f4c4a7d8285d4858c061e4Selim Cinek mVetoButton = findViewById(R.id.veto); 107fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi } 108fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi 109fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi @Override 110fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { 111fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi if (super.onRequestSendAccessibilityEvent(child, event)) { 112fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi // Add a record for the entire layout since its content is somehow small. 113fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi // The event comes from a leaf view that is interacted with. 114fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi AccessibilityEvent record = AccessibilityEvent.obtain(); 115fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi onInitializeAccessibilityEvent(record); 116fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi dispatchPopulateAccessibilityEvent(record); 117fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi event.appendRecord(record); 118fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi return true; 119fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi } 120fe40f7d13bfc1faa35c9a131ce4be5104cb8f6b9Jorim Jaggi return false; 121c5dc0d0cce373fbf292e13633c114a431d747167Jorim Jaggi } 12251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 123e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock @Override 124e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock public void setDark(boolean dark, boolean fade) { 125e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock super.setDark(dark, fade); 126e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock final NotificationContentView showing = getShowingLayout(); 127e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock if (showing != null) { 128e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock showing.setDark(dark, fade); 129e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock } 130e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock } 131e15452bb49d2531eee3086acb4763dd125f8053aJohn Spurlock 1321685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public void setHeightRange(int rowMinHeight, int rowMaxHeight) { 1331685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mRowMinHeight = rowMinHeight; 1341685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mRowMaxHeight = rowMaxHeight; 13551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 13651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 13751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public boolean isExpandable() { 13851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren return mExpandable; 13951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 14051c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 14151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public void setExpandable(boolean expandable) { 14251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren mExpandable = expandable; 14351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 14451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 1451685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1461685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @return whether the user has changed the expansion state 1471685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 1481685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public boolean hasUserChangedExpansion() { 1491685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return mHasUserChangedExpansion; 1501685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1511685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 15251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public boolean isUserExpanded() { 15351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren return mUserExpanded; 15451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 15551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 1561685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1571685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Set this notification to be expanded by the user 1581685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * 1591685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @param userExpanded whether the user wants this notification to be expanded 1601685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 16151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public void setUserExpanded(boolean userExpanded) { 162a7fe63190cc3f95af1830886edd80acef0c334e3Christoph Studer if (userExpanded && !mExpandable) return; 16378403d79739605511ea88b653564d81d7bf4bbbaChris Wren final boolean wasExpanded = isExpanded(); 1641685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mHasUserChangedExpansion = true; 16551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren mUserExpanded = userExpanded; 16678403d79739605511ea88b653564d81d7bf4bbbaChris Wren logExpansionEvent(true, wasExpanded); 16751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 16851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 169ccd14fbcfe613eae71f0e00c39f38e5125749389Selim Cinek public void resetUserExpansion() { 170ccd14fbcfe613eae71f0e00c39f38e5125749389Selim Cinek mHasUserChangedExpansion = false; 171ccd14fbcfe613eae71f0e00c39f38e5125749389Selim Cinek mUserExpanded = false; 172ccd14fbcfe613eae71f0e00c39f38e5125749389Selim Cinek } 173ccd14fbcfe613eae71f0e00c39f38e5125749389Selim Cinek 17451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public boolean isUserLocked() { 17551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren return mUserLocked; 17651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 17751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 17851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public void setUserLocked(boolean userLocked) { 17951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren mUserLocked = userLocked; 18051c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 18151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 1821685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1831685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @return has the system set this notification to be expanded 1841685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 1851685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public boolean isSystemExpanded() { 1861685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return mIsSystemExpanded; 1871685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1881685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1891685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1901685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Set this notification to be expanded by the system. 1911685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * 1921685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @param expand whether the system wants this notification to be expanded. 1931685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 1941685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public void setSystemExpanded(boolean expand) { 19531094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek if (expand != mIsSystemExpanded) { 19631094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek final boolean wasExpanded = isExpanded(); 19731094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek mIsSystemExpanded = expand; 19831094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek notifyHeightChanged(); 19931094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek logExpansionEvent(false, wasExpanded); 20031094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek } 201dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi } 202dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi 203dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi /** 204dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi * @param expansionDisabled whether to prevent notification expansion 205dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi */ 206dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi public void setExpansionDisabled(boolean expansionDisabled) { 20731094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek if (expansionDisabled != mExpansionDisabled) { 20831094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek final boolean wasExpanded = isExpanded(); 20931094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek mExpansionDisabled = expansionDisabled; 21031094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek logExpansionEvent(false, wasExpanded); 21131094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek if (wasExpanded != isExpanded()) { 21231094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek notifyHeightChanged(); 21331094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek } 21431094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek } 2151685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 2161685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 2171685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 2180d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler * @return Can the underlying notification be cleared? 2190d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler */ 2200d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler public boolean isClearable() { 2210d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler return mClearable; 2220d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler } 2230d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler 2240d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler /** 2250d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler * Set whether the notification can be cleared. 2260d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler * 2270d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler * @param clearable 2280d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler */ 2290d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler public void setClearable(boolean clearable) { 2300d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler mClearable = clearable; 2310d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler updateVetoButton(); 2320d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler } 2330d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler 2340d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler /** 2351685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Apply an expansion state to the layout. 2361685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 237dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi public void applyExpansionToLayout() { 238dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi boolean expand = isExpanded(); 23951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren if (expand && mExpandable) { 240be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi setActualHeight(mMaxExpandHeight); 24151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } else { 242be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi setActualHeight(mRowMinHeight); 24351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 24451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 245a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler 2469cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi @Override 2479cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi public int getIntrinsicHeight() { 248be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi if (isUserLocked()) { 249be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi return getActualHeight(); 250be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 2511685e634fb0b14033bd436af8d7174436699ffecSelim Cinek boolean inExpansionState = isExpanded(); 2521685e634fb0b14033bd436af8d7174436699ffecSelim Cinek if (!inExpansionState) { 2531685e634fb0b14033bd436af8d7174436699ffecSelim Cinek // not expanded, so we return the collapsed size 2541685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return mRowMinHeight; 2551685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 2561685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 257ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi return mShowingPublicForIntrinsicHeight ? mRowMinHeight : getMaxExpandHeight(); 2581685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 2591685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 2601685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 2611685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Check whether the view state is currently expanded. This is given by the system in {@link 2621685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * #setSystemExpanded(boolean)} and can be overridden by user expansion or 2631685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this 2641685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * view can differ from this state, if layout params are modified from outside. 2651685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * 2661685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @return whether the view state is currently expanded. 2671685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 2681685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private boolean isExpanded() { 269dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi return !mExpansionDisabled 270dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi && (!hasUserChangedExpansion() && isSystemExpanded() || isUserExpanded()); 2711685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 2721685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 2731685e634fb0b14033bd436af8d7174436699ffecSelim Cinek @Override 2741685e634fb0b14033bd436af8d7174436699ffecSelim Cinek protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 2751685e634fb0b14033bd436af8d7174436699ffecSelim Cinek super.onLayout(changed, left, top, right, bottom); 276a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset; 277d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek updateMaxExpandHeight(); 278be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi if (updateExpandHeight) { 279dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2Jorim Jaggi applyExpansionToLayout(); 280be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 281a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek mWasReset = false; 2821685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 2831685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 284d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek private void updateMaxExpandHeight() { 285d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek int intrinsicBefore = getIntrinsicHeight(); 286d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek mMaxExpandHeight = mPrivateLayout.getMaxHeight(); 287d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek if (intrinsicBefore != getIntrinsicHeight()) { 288d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek notifyHeightChanged(); 289d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek } 290d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek } 291d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek 292ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi public void setSensitive(boolean sensitive) { 293ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mSensitive = sensitive; 294ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } 295ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi 296ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) { 297ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mShowingPublicForIntrinsicHeight = mSensitive && hideSensitive; 298ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } 299ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi 300ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi public void setHideSensitive(boolean hideSensitive, boolean animated, long delay, 301ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi long duration) { 302ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi boolean oldShowingPublic = mShowingPublic; 303ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mShowingPublic = mSensitive && hideSensitive; 304ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) { 305ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi return; 306ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } 307a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler 308a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler // bail out if no public version 3091685e634fb0b14033bd436af8d7174436699ffecSelim Cinek if (mPublicLayout.getChildCount() == 0) return; 310a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler 311ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi if (!animated) { 312ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mPublicLayout.animate().cancel(); 313ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mPrivateLayout.animate().cancel(); 314ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mPublicLayout.setAlpha(1f); 315ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mPrivateLayout.setAlpha(1f); 316ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE); 317ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mPrivateLayout.setVisibility(mShowingPublic ? View.INVISIBLE : View.VISIBLE); 318ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } else { 319ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi animateShowingPublic(delay, duration); 320ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } 3210d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler 3220d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler updateVetoButton(); 323ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi mShowingPublicInitialized = true; 324ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } 325ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi 326ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi private void animateShowingPublic(long delay, long duration) { 327ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi final View source = mShowingPublic ? mPrivateLayout : mPublicLayout; 328ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi View target = mShowingPublic ? mPublicLayout : mPrivateLayout; 329ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi source.setVisibility(View.VISIBLE); 330ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi target.setVisibility(View.VISIBLE); 331ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi target.setAlpha(0f); 332ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi source.animate().cancel(); 333ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi target.animate().cancel(); 334ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi source.animate() 335ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .alpha(0f) 336ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .withLayer() 337ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .setStartDelay(delay) 338ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .setDuration(duration) 339ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .withEndAction(new Runnable() { 340ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi @Override 341ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi public void run() { 342ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi source.setVisibility(View.INVISIBLE); 343ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } 344ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi }); 345ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi target.animate() 346ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .alpha(1f) 347ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .withLayer() 348ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .setStartDelay(delay) 349ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi .setDuration(duration); 3500d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler } 3510d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler 3520d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler private void updateVetoButton() { 3530d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler // public versions cannot be dismissed 3540d3e62f3e07a69f21c1b1dfa2c8c0fb8b6c95655Dan Sandler mVetoButton.setVisibility(isClearable() && !mShowingPublic ? View.VISIBLE : View.GONE); 355a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler } 356251957d76e57eb6e5f8068b37346144e10e586a4Jorim Jaggi 3571685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public int getMaxExpandHeight() { 358ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi return mShowingPublicForIntrinsicHeight ? mRowMinHeight : mMaxExpandHeight; 359a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler } 360584a7aa62c54bcbd654a6696d4fbb56e124874e7Jorim Jaggi 361be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi @Override 3624222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi public boolean isContentExpandable() { 3632f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek NotificationContentView showingLayout = getShowingLayout(); 3642f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek return showingLayout.isContentExpandable(); 3654222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi } 3664222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi 3674222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi @Override 368d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi public void setActualHeight(int height, boolean notifyListeners) { 369c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek mPrivateLayout.setActualHeight(height); 3702f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek mPublicLayout.setActualHeight(height); 371be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi invalidate(); 372d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi super.setActualHeight(height, notifyListeners); 373be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 374be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 375be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi @Override 376be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public int getMaxHeight() { 3772f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek NotificationContentView showingLayout = getShowingLayout(); 3782f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek return showingLayout.getMaxHeight(); 379be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 380be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 381be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi @Override 3824222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi public int getMinHeight() { 3832f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek NotificationContentView showingLayout = getShowingLayout(); 3842f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek return showingLayout.getMinHeight(); 3854222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi } 3864222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi 3874222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi @Override 388be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public void setClipTopAmount(int clipTopAmount) { 389be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi super.setClipTopAmount(clipTopAmount); 390be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mPrivateLayout.setClipTopAmount(clipTopAmount); 3912f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek mPublicLayout.setClipTopAmount(clipTopAmount); 392be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 393be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 394be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public void notifyContentUpdated() { 3952f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek mPublicLayout.notifyContentUpdated(); 396be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mPrivateLayout.notifyContentUpdated(); 397343e6e258ab6a9f647eabebaed05ce3acafd2ff1Selim Cinek } 3987d447726e2cb9fae80db417012039828daab8fe7Selim Cinek 39931094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek public boolean isMaxExpandHeightInitialized() { 40031094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek return mMaxExpandHeight != 0; 4017d447726e2cb9fae80db417012039828daab8fe7Selim Cinek } 4022f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek 4032f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek private NotificationContentView getShowingLayout() { 4042f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek return mShowingPublic ? mPublicLayout : mPrivateLayout; 4052f0df8ae038dbb873bf2e11e1e13c75cf95b0198Selim Cinek } 40678403d79739605511ea88b653564d81d7bf4bbbaChris Wren 40778403d79739605511ea88b653564d81d7bf4bbbaChris Wren public void setExpansionLogger(ExpansionLogger logger, String key) { 40878403d79739605511ea88b653564d81d7bf4bbbaChris Wren mLogger = logger; 40978403d79739605511ea88b653564d81d7bf4bbbaChris Wren mLoggingKey = key; 41078403d79739605511ea88b653564d81d7bf4bbbaChris Wren } 41178403d79739605511ea88b653564d81d7bf4bbbaChris Wren 41278403d79739605511ea88b653564d81d7bf4bbbaChris Wren 41378403d79739605511ea88b653564d81d7bf4bbbaChris Wren private void logExpansionEvent(boolean userAction, boolean wasExpanded) { 41478403d79739605511ea88b653564d81d7bf4bbbaChris Wren final boolean nowExpanded = isExpanded(); 41578403d79739605511ea88b653564d81d7bf4bbbaChris Wren if (wasExpanded != nowExpanded && mLogger != null) { 41678403d79739605511ea88b653564d81d7bf4bbbaChris Wren mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ; 41778403d79739605511ea88b653564d81d7bf4bbbaChris Wren } 41878403d79739605511ea88b653564d81d7bf4bbbaChris Wren } 41951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren} 420