ExpandableNotificationRow.java revision 1685e634fb0b14033bd436af8d7174436699ffec
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; 2251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wrenimport android.view.ViewGroup; 2351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wrenimport android.widget.FrameLayout; 2451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 251685e634fb0b14033bd436af8d7174436699ffecSelim Cinekimport com.android.internal.widget.SizeAdaptiveLayout; 26a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandlerimport com.android.systemui.R; 27a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler 2851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wrenpublic class ExpandableNotificationRow extends FrameLayout { 291685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private int mRowMinHeight; 301685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private int mRowMaxHeight; 3151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 321685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** Does this row contain layouts that can adapt to row expansion */ 3351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren private boolean mExpandable; 341685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** Has the user actively changed the expansion state of this row */ 351685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private boolean mHasUserChangedExpansion; 361685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */ 3751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren private boolean mUserExpanded; 381685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** Is the user touching this row */ 3951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren private boolean mUserLocked; 401685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** Are we showing the "public" version */ 41a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler private boolean mShowingPublic; 4251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 431685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 441685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Is this notification expanded by the system. The expansion state can be overridden by the 451685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * user expansion. 461685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 471685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private boolean mIsSystemExpanded; 481685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private SizeAdaptiveLayout mPublicLayout; 491685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private SizeAdaptiveLayout mPrivateLayout; 501685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private int mMaxExpandHeight; 511685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private boolean mMaxHeightNeedsUpdate; 521685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 5351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public ExpandableNotificationRow(Context context, AttributeSet attrs) { 5451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren super(context, attrs); 5551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 5651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 571685e634fb0b14033bd436af8d7174436699ffecSelim Cinek @Override 581685e634fb0b14033bd436af8d7174436699ffecSelim Cinek protected void onFinishInflate() { 591685e634fb0b14033bd436af8d7174436699ffecSelim Cinek super.onFinishInflate(); 601685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mPublicLayout = (SizeAdaptiveLayout) findViewById(R.id.expandedPublic); 611685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mPrivateLayout = (SizeAdaptiveLayout) findViewById(R.id.expanded); 6251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 6351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 641685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public void setHeightRange(int rowMinHeight, int rowMaxHeight) { 651685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mRowMinHeight = rowMinHeight; 661685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mRowMaxHeight = rowMaxHeight; 671685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mMaxHeightNeedsUpdate = true; 6851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 6951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 7051c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public boolean isExpandable() { 7151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren return mExpandable; 7251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 7351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 7451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public void setExpandable(boolean expandable) { 7551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren mExpandable = expandable; 7651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 7751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 781685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 791685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @return whether the user has changed the expansion state 801685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 811685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public boolean hasUserChangedExpansion() { 821685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return mHasUserChangedExpansion; 831685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 841685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 8551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public boolean isUserExpanded() { 8651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren return mUserExpanded; 8751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 8851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 891685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 901685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Set this notification to be expanded by the user 911685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * 921685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @param userExpanded whether the user wants this notification to be expanded 931685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 9451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public void setUserExpanded(boolean userExpanded) { 951685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mHasUserChangedExpansion = true; 9651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren mUserExpanded = userExpanded; 9751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 9851c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 9951c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public boolean isUserLocked() { 10051c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren return mUserLocked; 10151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 10251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 10351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren public void setUserLocked(boolean userLocked) { 10451c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren mUserLocked = userLocked; 10551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 10651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren 1071685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1081685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @return has the system set this notification to be expanded 1091685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 1101685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public boolean isSystemExpanded() { 1111685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return mIsSystemExpanded; 1121685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1131685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1141685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1151685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Set this notification to be expanded by the system. 1161685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * 1171685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @param expand whether the system wants this notification to be expanded. 1181685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 1191685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public void setSystemExpanded(boolean expand) { 1201685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mIsSystemExpanded = expand; 1211685e634fb0b14033bd436af8d7174436699ffecSelim Cinek applyExpansionToLayout(expand); 1221685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1231685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1241685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1251685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Apply an expansion state to the layout. 1261685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * 1271685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @param expand should the layout be in the expanded state 1281685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 1291685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public void applyExpansionToLayout(boolean expand) { 13051c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren ViewGroup.LayoutParams lp = getLayoutParams(); 13151c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren if (expand && mExpandable) { 13251c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; 13351c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } else { 1341685e634fb0b14033bd436af8d7174436699ffecSelim Cinek lp.height = mRowMinHeight; 13551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 13651c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren setLayoutParams(lp); 13751c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren } 138a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler 1391685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1401685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * If {@link #isExpanded()} then this is the greatest possible height this view can 1411685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * get and otherwise it is {@link #mRowMinHeight}. 1421685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * 1431685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @return the maximum allowed expansion height of this view. 1441685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 1451685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public int getMaximumAllowedExpandHeight() { 1461685e634fb0b14033bd436af8d7174436699ffecSelim Cinek boolean inExpansionState = isExpanded(); 1471685e634fb0b14033bd436af8d7174436699ffecSelim Cinek if (!inExpansionState) { 1481685e634fb0b14033bd436af8d7174436699ffecSelim Cinek // not expanded, so we return the collapsed size 1491685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return mRowMinHeight; 1501685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1511685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1521685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return mShowingPublic ? mRowMinHeight : getMaxExpandHeight(); 1531685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1541685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1551685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1561685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1571685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private void updateMaxExpandHeight() { 1581685e634fb0b14033bd436af8d7174436699ffecSelim Cinek ViewGroup.LayoutParams lp = getLayoutParams(); 1591685e634fb0b14033bd436af8d7174436699ffecSelim Cinek int oldHeight = lp.height; 1601685e634fb0b14033bd436af8d7174436699ffecSelim Cinek lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; 1611685e634fb0b14033bd436af8d7174436699ffecSelim Cinek setLayoutParams(lp); 1621685e634fb0b14033bd436af8d7174436699ffecSelim Cinek measure(View.MeasureSpec.makeMeasureSpec(getMeasuredWidth(), View.MeasureSpec.EXACTLY), 1631685e634fb0b14033bd436af8d7174436699ffecSelim Cinek View.MeasureSpec.makeMeasureSpec(mRowMaxHeight, View.MeasureSpec.AT_MOST)); 1641685e634fb0b14033bd436af8d7174436699ffecSelim Cinek lp.height = oldHeight; 1651685e634fb0b14033bd436af8d7174436699ffecSelim Cinek setLayoutParams(lp); 1661685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mMaxExpandHeight = getMeasuredHeight(); 1671685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1681685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1691685e634fb0b14033bd436af8d7174436699ffecSelim Cinek /** 1701685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * Check whether the view state is currently expanded. This is given by the system in {@link 1711685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * #setSystemExpanded(boolean)} and can be overridden by user expansion or 1721685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this 1731685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * view can differ from this state, if layout params are modified from outside. 1741685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * 1751685e634fb0b14033bd436af8d7174436699ffecSelim Cinek * @return whether the view state is currently expanded. 1761685e634fb0b14033bd436af8d7174436699ffecSelim Cinek */ 1771685e634fb0b14033bd436af8d7174436699ffecSelim Cinek private boolean isExpanded() { 1781685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return !hasUserChangedExpansion() && isSystemExpanded() || isUserExpanded(); 1791685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1801685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1811685e634fb0b14033bd436af8d7174436699ffecSelim Cinek @Override 1821685e634fb0b14033bd436af8d7174436699ffecSelim Cinek protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 1831685e634fb0b14033bd436af8d7174436699ffecSelim Cinek super.onLayout(changed, left, top, right, bottom); 1841685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mMaxHeightNeedsUpdate = true; 1851685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1861685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 187a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler public void setShowingPublic(boolean show) { 188a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler mShowingPublic = show; 189a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler 190a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler // bail out if no public version 1911685e634fb0b14033bd436af8d7174436699ffecSelim Cinek if (mPublicLayout.getChildCount() == 0) return; 192a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler 193a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler // TODO: animation? 1941685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mPublicLayout.setVisibility(show ? View.VISIBLE : View.GONE); 1951685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE); 1961685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1971685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1981685e634fb0b14033bd436af8d7174436699ffecSelim Cinek public int getMaxExpandHeight() { 1991685e634fb0b14033bd436af8d7174436699ffecSelim Cinek if (mMaxHeightNeedsUpdate) { 2001685e634fb0b14033bd436af8d7174436699ffecSelim Cinek updateMaxExpandHeight(); 2011685e634fb0b14033bd436af8d7174436699ffecSelim Cinek mMaxHeightNeedsUpdate = false; 2021685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 2031685e634fb0b14033bd436af8d7174436699ffecSelim Cinek return mMaxExpandHeight; 204a5e0f415d351ad1a9c0ffde8d93df91a2384591fDan Sandler } 20551c7510e493680b4aca1ed7695b35c52d2cd63ffChris Wren} 206