Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2010 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.systemui.statusbar.tablet; |
| 18 | |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 19 | import android.animation.Animator; |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 20 | import android.animation.AnimatorListenerAdapter; |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 21 | import android.animation.AnimatorSet; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 22 | import android.animation.ObjectAnimator; |
Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 23 | import android.content.Context; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 24 | import android.graphics.Rect; |
Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 25 | import android.util.AttributeSet; |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 26 | import android.util.Slog; |
Chris Wren | 9b2cd15 | 2012-06-11 10:39:36 -0400 | [diff] [blame] | 27 | import android.view.Gravity; |
Svetoslav Ganov | 73b9c29 | 2012-07-30 16:13:46 -0700 | [diff] [blame] | 28 | import android.view.KeyEvent; |
Joe Onorato | cf2b199 | 2010-11-16 21:36:42 -0800 | [diff] [blame] | 29 | import android.view.LayoutInflater; |
Daniel Sandler | 8f491b5 | 2011-03-03 00:00:22 -0500 | [diff] [blame] | 30 | import android.view.MotionEvent; |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 31 | import android.view.View; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 32 | import android.view.ViewGroup; |
Chet Haase | 41bff38 | 2011-08-29 16:00:23 -0700 | [diff] [blame] | 33 | import android.view.ViewTreeObserver; |
| 34 | import android.view.animation.AccelerateInterpolator; |
| 35 | import android.view.animation.DecelerateInterpolator; |
| 36 | import android.view.animation.Interpolator; |
Fabrice Di Meglio | 8afcd14 | 2012-07-27 18:27:11 -0700 | [diff] [blame] | 37 | import android.widget.ImageView; |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 38 | import android.widget.RelativeLayout; |
Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 39 | |
Chris Wren | 1e8f65d | 2012-06-06 18:08:56 -0400 | [diff] [blame] | 40 | import com.android.systemui.ExpandHelper; |
Joe Onorato | fd52b18 | 2010-11-10 18:00:52 -0800 | [diff] [blame] | 41 | import com.android.systemui.R; |
Chris Wren | 1e8f65d | 2012-06-06 18:08:56 -0400 | [diff] [blame] | 42 | import com.android.systemui.statusbar.policy.NotificationRowLayout; |
Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 43 | |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 44 | public class NotificationPanel extends RelativeLayout implements StatusBarPanel, |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 45 | View.OnClickListener { |
Chris Wren | 1e8f65d | 2012-06-06 18:08:56 -0400 | [diff] [blame] | 46 | private ExpandHelper mExpandHelper; |
| 47 | private NotificationRowLayout latestItems; |
| 48 | |
Daniel Sandler | ef6e936 | 2010-12-17 14:50:03 -0500 | [diff] [blame] | 49 | static final String TAG = "Tablet/NotificationPanel"; |
| 50 | static final boolean DEBUG = false; |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 51 | |
Daniel Sandler | 40c1545 | 2011-01-22 01:26:22 -0500 | [diff] [blame] | 52 | final static int PANEL_FADE_DURATION = 150; |
| 53 | |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 54 | boolean mShowing; |
Daniel Sandler | 06a0d4b | 2011-08-05 00:19:21 -0400 | [diff] [blame] | 55 | boolean mHasClearableNotifications = false; |
Daniel Sandler | 40c1545 | 2011-01-22 01:26:22 -0500 | [diff] [blame] | 56 | int mNotificationCount = 0; |
Svetoslav Ganov | 6179ea3 | 2011-06-28 01:12:41 -0700 | [diff] [blame] | 57 | NotificationPanelTitle mTitleArea; |
Fabrice Di Meglio | 8afcd14 | 2012-07-27 18:27:11 -0700 | [diff] [blame] | 58 | ImageView mSettingsButton; |
| 59 | ImageView mNotificationButton; |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 60 | View mNotificationScroller; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 61 | ViewGroup mContentFrame; |
Joe Onorato | 6223fba | 2011-01-18 18:00:30 -0800 | [diff] [blame] | 62 | Rect mContentArea = new Rect(); |
Joe Onorato | 755cc74 | 2010-11-27 15:45:35 -0800 | [diff] [blame] | 63 | View mSettingsView; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 64 | ViewGroup mContentParent; |
Daniel Sandler | 1347c30 | 2011-08-01 16:47:53 -0400 | [diff] [blame] | 65 | TabletStatusBar mBar; |
Daniel Sandler | 06a0d4b | 2011-08-05 00:19:21 -0400 | [diff] [blame] | 66 | View mClearButton; |
Chet Haase | 41bff38 | 2011-08-29 16:00:23 -0700 | [diff] [blame] | 67 | static Interpolator sAccelerateInterpolator = new AccelerateInterpolator(); |
| 68 | static Interpolator sDecelerateInterpolator = new DecelerateInterpolator(); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 69 | |
Daniel Sandler | 641a499 | 2011-01-26 21:19:10 -0500 | [diff] [blame] | 70 | // amount to slide mContentParent down by when mContentFrame is missing |
| 71 | float mContentFrameMissingTranslation; |
| 72 | |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 73 | Choreographer mChoreo = new Choreographer(); |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 74 | |
Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 75 | public NotificationPanel(Context context, AttributeSet attrs) { |
| 76 | this(context, attrs, 0); |
| 77 | } |
| 78 | |
| 79 | public NotificationPanel(Context context, AttributeSet attrs, int defStyle) { |
| 80 | super(context, attrs, defStyle); |
| 81 | } |
| 82 | |
Daniel Sandler | 1347c30 | 2011-08-01 16:47:53 -0400 | [diff] [blame] | 83 | public void setBar(TabletStatusBar b) { |
| 84 | mBar = b; |
| 85 | } |
| 86 | |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 87 | @Override |
| 88 | public void onFinishInflate() { |
| 89 | super.onFinishInflate(); |
| 90 | |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 91 | setWillNotDraw(false); |
| 92 | |
| 93 | mContentParent = (ViewGroup)findViewById(R.id.content_parent); |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 94 | mContentParent.bringToFront(); |
Svetoslav Ganov | 6179ea3 | 2011-06-28 01:12:41 -0700 | [diff] [blame] | 95 | mTitleArea = (NotificationPanelTitle) findViewById(R.id.title_area); |
| 96 | mTitleArea.setPanel(this); |
Joe Onorato | cf2b199 | 2010-11-16 21:36:42 -0800 | [diff] [blame] | 97 | |
Fabrice Di Meglio | 8afcd14 | 2012-07-27 18:27:11 -0700 | [diff] [blame] | 98 | mSettingsButton = (ImageView) findViewById(R.id.settings_button); |
| 99 | mNotificationButton = (ImageView) findViewById(R.id.notification_button); |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 100 | |
Joe Onorato | 244e415 | 2010-12-16 13:22:34 -0800 | [diff] [blame] | 101 | mNotificationScroller = findViewById(R.id.notification_scroller); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 102 | mContentFrame = (ViewGroup)findViewById(R.id.content_frame); |
Daniel Sandler | 06a0d4b | 2011-08-05 00:19:21 -0400 | [diff] [blame] | 103 | mContentFrameMissingTranslation = 0; // not needed with current assets |
| 104 | |
| 105 | // the "X" that appears in place of the clock when the panel is showing notifications |
| 106 | mClearButton = findViewById(R.id.clear_all_button); |
| 107 | mClearButton.setOnClickListener(mClearButtonListener); |
Daniel Sandler | 641a499 | 2011-01-26 21:19:10 -0500 | [diff] [blame] | 108 | |
| 109 | mShowing = false; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 110 | } |
| 111 | |
Chris Wren | 1e8f65d | 2012-06-06 18:08:56 -0400 | [diff] [blame] | 112 | @Override |
| 113 | protected void onAttachedToWindow () { |
| 114 | super.onAttachedToWindow(); |
| 115 | latestItems = (NotificationRowLayout) findViewById(R.id.content); |
| 116 | int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height); |
| 117 | int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height); |
| 118 | mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight); |
| 119 | mExpandHelper.setEventSource(this); |
Chris Wren | 9b2cd15 | 2012-06-11 10:39:36 -0400 | [diff] [blame] | 120 | mExpandHelper.setGravity(Gravity.BOTTOM); |
Chris Wren | 1e8f65d | 2012-06-06 18:08:56 -0400 | [diff] [blame] | 121 | } |
| 122 | |
Daniel Sandler | 06a0d4b | 2011-08-05 00:19:21 -0400 | [diff] [blame] | 123 | private View.OnClickListener mClearButtonListener = new View.OnClickListener() { |
| 124 | public void onClick(View v) { |
| 125 | mBar.clearAll(); |
| 126 | } |
| 127 | }; |
| 128 | |
| 129 | public View getClearButton() { |
| 130 | return mClearButton; |
| 131 | } |
| 132 | |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 133 | public void show(boolean show, boolean animate) { |
| 134 | if (animate) { |
| 135 | if (mShowing != show) { |
| 136 | mShowing = show; |
| 137 | if (show) { |
| 138 | setVisibility(View.VISIBLE); |
Chet Haase | 41bff38 | 2011-08-29 16:00:23 -0700 | [diff] [blame] | 139 | // Don't start the animation until we've created the layer, which is done |
| 140 | // right before we are drawn |
| 141 | mContentParent.setLayerType(View.LAYER_TYPE_HARDWARE, null); |
| 142 | getViewTreeObserver().addOnPreDrawListener(mPreDrawListener); |
| 143 | } else { |
| 144 | mChoreo.startAnimation(show); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 145 | } |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 146 | } |
| 147 | } else { |
| 148 | mShowing = show; |
| 149 | setVisibility(show ? View.VISIBLE : View.GONE); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 150 | } |
| 151 | } |
| 152 | |
| 153 | /** |
Chet Haase | 41bff38 | 2011-08-29 16:00:23 -0700 | [diff] [blame] | 154 | * This is used only when we've created a hardware layer and are waiting until it's |
| 155 | * been created in order to start the appearing animation. |
| 156 | */ |
| 157 | private ViewTreeObserver.OnPreDrawListener mPreDrawListener = |
| 158 | new ViewTreeObserver.OnPreDrawListener() { |
| 159 | @Override |
| 160 | public boolean onPreDraw() { |
| 161 | getViewTreeObserver().removeOnPreDrawListener(this); |
| 162 | mChoreo.startAnimation(true); |
Chet Haase | 3c4ce72 | 2011-09-02 15:37:25 -0700 | [diff] [blame] | 163 | return false; |
Chet Haase | 41bff38 | 2011-08-29 16:00:23 -0700 | [diff] [blame] | 164 | } |
| 165 | }; |
| 166 | |
| 167 | /** |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 168 | * Whether the panel is showing, or, if it's animating, whether it will be |
| 169 | * when the animation is done. |
| 170 | */ |
| 171 | public boolean isShowing() { |
| 172 | return mShowing; |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | @Override |
| 176 | public void onVisibilityChanged(View v, int vis) { |
| 177 | super.onVisibilityChanged(v, vis); |
| 178 | // when we hide, put back the notifications |
Daniel Sandler | 641a499 | 2011-01-26 21:19:10 -0500 | [diff] [blame] | 179 | if (vis != View.VISIBLE) { |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 180 | if (mSettingsView != null) removeSettingsView(); |
| 181 | mNotificationScroller.setVisibility(View.VISIBLE); |
| 182 | mNotificationScroller.setAlpha(1f); |
Joe Onorato | 4386191 | 2010-11-27 16:08:58 -0800 | [diff] [blame] | 183 | mNotificationScroller.scrollTo(0, 0); |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 184 | updatePanelModeButtons(); |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 185 | } |
| 186 | } |
| 187 | |
Svetoslav Ganov | 6179ea3 | 2011-06-28 01:12:41 -0700 | [diff] [blame] | 188 | @Override |
| 189 | public boolean dispatchHoverEvent(MotionEvent event) { |
| 190 | // Ignore hover events outside of this panel bounds since such events |
| 191 | // generate spurious accessibility events with the panel content when |
| 192 | // tapping outside of it, thus confusing the user. |
| 193 | final int x = (int) event.getX(); |
| 194 | final int y = (int) event.getY(); |
| 195 | if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { |
| 196 | return super.dispatchHoverEvent(event); |
| 197 | } |
| 198 | return true; |
| 199 | } |
| 200 | |
Svetoslav Ganov | 73b9c29 | 2012-07-30 16:13:46 -0700 | [diff] [blame] | 201 | @Override |
| 202 | public boolean dispatchKeyEvent(KeyEvent event) { |
| 203 | final int keyCode = event.getKeyCode(); |
| 204 | switch (keyCode) { |
| 205 | // We exclusively handle the back key by hiding this panel. |
| 206 | case KeyEvent.KEYCODE_BACK: { |
| 207 | if (event.getAction() == KeyEvent.ACTION_UP) { |
Daniel Sandler | 11cf178 | 2012-09-27 14:03:08 -0400 | [diff] [blame] | 208 | mBar.animateCollapsePanels(); |
Svetoslav Ganov | 73b9c29 | 2012-07-30 16:13:46 -0700 | [diff] [blame] | 209 | } |
| 210 | return true; |
| 211 | } |
| 212 | // We react to the home key but let the system handle it. |
| 213 | case KeyEvent.KEYCODE_HOME: { |
| 214 | if (event.getAction() == KeyEvent.ACTION_UP) { |
Daniel Sandler | 11cf178 | 2012-09-27 14:03:08 -0400 | [diff] [blame] | 215 | mBar.animateCollapsePanels(); |
Svetoslav Ganov | 73b9c29 | 2012-07-30 16:13:46 -0700 | [diff] [blame] | 216 | } |
| 217 | } break; |
| 218 | } |
| 219 | return super.dispatchKeyEvent(event); |
| 220 | } |
| 221 | |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 222 | /* |
Joe Onorato | 4cddc98 | 2010-11-21 11:48:15 -0800 | [diff] [blame] | 223 | @Override |
| 224 | protected void onLayout(boolean changed, int l, int t, int r, int b) { |
| 225 | super.onLayout(changed, l, t, r, b); |
Daniel Sandler | 2f447aa | 2011-01-14 16:39:19 -0500 | [diff] [blame] | 226 | |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 227 | if (DEBUG) Slog.d(TAG, String.format("PANEL: onLayout: (%d, %d, %d, %d)", l, t, r, b)); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 228 | } |
| 229 | |
| 230 | @Override |
| 231 | public void onSizeChanged(int w, int h, int oldw, int oldh) { |
| 232 | super.onSizeChanged(w, h, oldw, oldh); |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 233 | |
| 234 | if (DEBUG) { |
| 235 | Slog.d(TAG, String.format("PANEL: onSizeChanged: (%d -> %d, %d -> %d)", |
| 236 | oldw, w, oldh, h)); |
| 237 | } |
Joe Onorato | 4cddc98 | 2010-11-21 11:48:15 -0800 | [diff] [blame] | 238 | } |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 239 | */ |
Joe Onorato | 4cddc98 | 2010-11-21 11:48:15 -0800 | [diff] [blame] | 240 | |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 241 | public void onClick(View v) { |
John Spurlock | 3623128 | 2012-06-23 17:11:27 -0400 | [diff] [blame] | 242 | if (mSettingsButton.isEnabled() && v == mTitleArea) { |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 243 | swapPanels(); |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 244 | } |
| 245 | } |
| 246 | |
Daniel Sandler | 40c1545 | 2011-01-22 01:26:22 -0500 | [diff] [blame] | 247 | public void setNotificationCount(int n) { |
Daniel Sandler | 40c1545 | 2011-01-22 01:26:22 -0500 | [diff] [blame] | 248 | mNotificationCount = n; |
| 249 | } |
| 250 | |
| 251 | public void setContentFrameVisible(final boolean showing, boolean animate) { |
Daniel Sandler | 40c1545 | 2011-01-22 01:26:22 -0500 | [diff] [blame] | 252 | } |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 253 | |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 254 | public void swapPanels() { |
| 255 | final View toShow, toHide; |
| 256 | if (mSettingsView == null) { |
| 257 | addSettingsView(); |
| 258 | toShow = mSettingsView; |
| 259 | toHide = mNotificationScroller; |
| 260 | } else { |
| 261 | toShow = mNotificationScroller; |
| 262 | toHide = mSettingsView; |
| 263 | } |
| 264 | Animator a = ObjectAnimator.ofFloat(toHide, "alpha", 1f, 0f) |
| 265 | .setDuration(PANEL_FADE_DURATION); |
| 266 | a.addListener(new AnimatorListenerAdapter() { |
| 267 | @Override |
| 268 | public void onAnimationEnd(Animator _a) { |
| 269 | toHide.setVisibility(View.GONE); |
Daniel Sandler | 40c1545 | 2011-01-22 01:26:22 -0500 | [diff] [blame] | 270 | if (toShow != null) { |
Daniel Sandler | 40c1545 | 2011-01-22 01:26:22 -0500 | [diff] [blame] | 271 | toShow.setVisibility(View.VISIBLE); |
| 272 | if (toShow == mSettingsView || mNotificationCount > 0) { |
| 273 | ObjectAnimator.ofFloat(toShow, "alpha", 0f, 1f) |
| 274 | .setDuration(PANEL_FADE_DURATION) |
| 275 | .start(); |
| 276 | } |
| 277 | |
| 278 | if (toHide == mSettingsView) { |
| 279 | removeSettingsView(); |
| 280 | } |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 281 | } |
Daniel Sandler | 1347c30 | 2011-08-01 16:47:53 -0400 | [diff] [blame] | 282 | updateClearButton(); |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 283 | updatePanelModeButtons(); |
| 284 | } |
| 285 | }); |
| 286 | a.start(); |
| 287 | } |
| 288 | |
Daniel Sandler | 1347c30 | 2011-08-01 16:47:53 -0400 | [diff] [blame] | 289 | public void updateClearButton() { |
| 290 | if (mBar != null) { |
| 291 | final boolean showX |
| 292 | = (isShowing() |
Daniel Sandler | 06a0d4b | 2011-08-05 00:19:21 -0400 | [diff] [blame] | 293 | && mHasClearableNotifications |
| 294 | && mNotificationScroller.getVisibility() == View.VISIBLE); |
| 295 | getClearButton().setVisibility(showX ? View.VISIBLE : View.INVISIBLE); |
Daniel Sandler | 1347c30 | 2011-08-01 16:47:53 -0400 | [diff] [blame] | 296 | } |
| 297 | } |
| 298 | |
Daniel Sandler | 06a0d4b | 2011-08-05 00:19:21 -0400 | [diff] [blame] | 299 | public void setClearable(boolean clearable) { |
| 300 | mHasClearableNotifications = clearable; |
| 301 | } |
| 302 | |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 303 | public void updatePanelModeButtons() { |
| 304 | final boolean settingsVisible = (mSettingsView != null); |
John Spurlock | 3623128 | 2012-06-23 17:11:27 -0400 | [diff] [blame] | 305 | mSettingsButton.setVisibility(!settingsVisible && mSettingsButton.isEnabled() ? View.VISIBLE : View.GONE); |
Daniel Sandler | 5962fd5 | 2012-01-11 14:57:04 -0500 | [diff] [blame] | 306 | mNotificationButton.setVisibility(settingsVisible ? View.VISIBLE : View.GONE); |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 307 | } |
| 308 | |
Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 309 | public boolean isInContentArea(int x, int y) { |
Chris Wren | 1e8f65d | 2012-06-06 18:08:56 -0400 | [diff] [blame] | 310 | mContentArea.left = mContentFrame.getLeft() + mContentFrame.getPaddingLeft(); |
| 311 | mContentArea.top = mContentFrame.getTop() + mContentFrame.getPaddingTop() |
Daniel Sandler | 641a499 | 2011-01-26 21:19:10 -0500 | [diff] [blame] | 312 | + (int)mContentParent.getTranslationY(); // account for any adjustment |
Chris Wren | 1e8f65d | 2012-06-06 18:08:56 -0400 | [diff] [blame] | 313 | mContentArea.right = mContentFrame.getRight() - mContentFrame.getPaddingRight(); |
| 314 | mContentArea.bottom = mContentFrame.getBottom() - mContentFrame.getPaddingBottom(); |
Daniel Sandler | 641a499 | 2011-01-26 21:19:10 -0500 | [diff] [blame] | 315 | |
Joe Onorato | 6223fba | 2011-01-18 18:00:30 -0800 | [diff] [blame] | 316 | offsetDescendantRectToMyCoords(mContentParent, mContentArea); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 317 | return mContentArea.contains(x, y); |
Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 318 | } |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 319 | |
Joe Onorato | 755cc74 | 2010-11-27 15:45:35 -0800 | [diff] [blame] | 320 | void removeSettingsView() { |
| 321 | if (mSettingsView != null) { |
| 322 | mContentFrame.removeView(mSettingsView); |
| 323 | mSettingsView = null; |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 324 | } |
| 325 | } |
| 326 | |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 327 | // NB: it will be invisible until you show it |
Joe Onorato | 755cc74 | 2010-11-27 15:45:35 -0800 | [diff] [blame] | 328 | void addSettingsView() { |
Joe Onorato | cf2b199 | 2010-11-16 21:36:42 -0800 | [diff] [blame] | 329 | LayoutInflater infl = LayoutInflater.from(getContext()); |
Daniel Sandler | 4a066c5 | 2012-04-20 14:49:13 -0400 | [diff] [blame] | 330 | mSettingsView = infl.inflate(R.layout.system_bar_settings_view, mContentFrame, false); |
Daniel Sandler | 14db0bc | 2011-01-20 12:11:23 -0500 | [diff] [blame] | 331 | mSettingsView.setVisibility(View.GONE); |
Daniel Sandler | 2f447aa | 2011-01-14 16:39:19 -0500 | [diff] [blame] | 332 | mContentFrame.addView(mSettingsView); |
Joe Onorato | 8a57671 | 2010-11-15 16:50:34 -0800 | [diff] [blame] | 333 | } |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 334 | |
| 335 | private class Choreographer implements Animator.AnimatorListener { |
Joe Onorato | 244e415 | 2010-12-16 13:22:34 -0800 | [diff] [blame] | 336 | boolean mVisible; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 337 | int mPanelHeight; |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 338 | AnimatorSet mContentAnim; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 339 | |
| 340 | // should group this into a multi-property animation |
Chet Haase | 41bff38 | 2011-08-29 16:00:23 -0700 | [diff] [blame] | 341 | final static int OPEN_DURATION = 250; |
| 342 | final static int CLOSE_DURATION = 250; |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 343 | |
| 344 | // the panel will start to appear this many px from the end |
Daniel Sandler | 1347c30 | 2011-08-01 16:47:53 -0400 | [diff] [blame] | 345 | final int HYPERSPACE_OFFRAMP = 200; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 346 | |
| 347 | Choreographer() { |
| 348 | } |
| 349 | |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 350 | void createAnimation(boolean appearing) { |
Daniel Sandler | add2620 | 2011-01-20 02:53:43 -0500 | [diff] [blame] | 351 | // mVisible: previous state; appearing: new state |
| 352 | |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 353 | float start, end; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 354 | |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 355 | // 0: on-screen |
| 356 | // height: off-screen |
| 357 | float y = mContentParent.getTranslationY(); |
| 358 | if (appearing) { |
| 359 | // we want to go from near-the-top to the top, unless we're half-open in the right |
| 360 | // general vicinity |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 361 | end = 0; |
Daniel Sandler | 641a499 | 2011-01-26 21:19:10 -0500 | [diff] [blame] | 362 | if (mNotificationCount == 0) { |
| 363 | end += mContentFrameMissingTranslation; |
| 364 | } |
Daniel Sandler | 8c98918 | 2011-01-30 01:24:09 -0500 | [diff] [blame] | 365 | start = HYPERSPACE_OFFRAMP+end; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 366 | } else { |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 367 | start = y; |
| 368 | end = y + HYPERSPACE_OFFRAMP; |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 369 | } |
Daniel Sandler | 641a499 | 2011-01-26 21:19:10 -0500 | [diff] [blame] | 370 | |
Daniel Sandler | add2620 | 2011-01-20 02:53:43 -0500 | [diff] [blame] | 371 | Animator posAnim = ObjectAnimator.ofFloat(mContentParent, "translationY", |
| 372 | start, end); |
Chet Haase | 41bff38 | 2011-08-29 16:00:23 -0700 | [diff] [blame] | 373 | posAnim.setInterpolator(appearing ? sDecelerateInterpolator : sAccelerateInterpolator); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 374 | |
Daniel Sandler | f844dc4 | 2011-01-24 23:44:47 -0500 | [diff] [blame] | 375 | if (mContentAnim != null && mContentAnim.isRunning()) { |
| 376 | mContentAnim.cancel(); |
| 377 | } |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 378 | |
Daniel Sandler | 8c98918 | 2011-01-30 01:24:09 -0500 | [diff] [blame] | 379 | Animator fadeAnim = ObjectAnimator.ofFloat(mContentParent, "alpha", |
Chet Haase | 41bff38 | 2011-08-29 16:00:23 -0700 | [diff] [blame] | 380 | appearing ? 1.0f : 0.0f); |
| 381 | fadeAnim.setInterpolator(appearing ? sAccelerateInterpolator : sDecelerateInterpolator); |
Daniel Sandler | 8c98918 | 2011-01-30 01:24:09 -0500 | [diff] [blame] | 382 | |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 383 | mContentAnim = new AnimatorSet(); |
| 384 | mContentAnim |
Daniel Sandler | 8c98918 | 2011-01-30 01:24:09 -0500 | [diff] [blame] | 385 | .play(fadeAnim) |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 386 | .with(posAnim) |
| 387 | ; |
Daniel Sandler | add2620 | 2011-01-20 02:53:43 -0500 | [diff] [blame] | 388 | mContentAnim.setDuration((DEBUG?10:1)*(appearing ? OPEN_DURATION : CLOSE_DURATION)); |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 389 | mContentAnim.addListener(this); |
| 390 | } |
| 391 | |
| 392 | void startAnimation(boolean appearing) { |
| 393 | if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")"); |
| 394 | |
| 395 | createAnimation(appearing); |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 396 | mContentAnim.start(); |
| 397 | |
| 398 | mVisible = appearing; |
Daniel Sandler | 1347c30 | 2011-08-01 16:47:53 -0400 | [diff] [blame] | 399 | |
| 400 | // we want to start disappearing promptly |
| 401 | if (!mVisible) updateClearButton(); |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 402 | } |
| 403 | |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 404 | public void onAnimationCancel(Animator animation) { |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 405 | if (DEBUG) Slog.d(TAG, "onAnimationCancel"); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 406 | } |
| 407 | |
| 408 | public void onAnimationEnd(Animator animation) { |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 409 | if (DEBUG) Slog.d(TAG, "onAnimationEnd"); |
| 410 | if (! mVisible) { |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 411 | setVisibility(View.GONE); |
| 412 | } |
Daniel Sandler | 7d9ea8c | 2011-01-11 10:28:58 -0500 | [diff] [blame] | 413 | mContentParent.setLayerType(View.LAYER_TYPE_NONE, null); |
| 414 | mContentAnim = null; |
Daniel Sandler | 1347c30 | 2011-08-01 16:47:53 -0400 | [diff] [blame] | 415 | |
| 416 | // we want to show the X lazily |
| 417 | if (mVisible) updateClearButton(); |
Joe Onorato | 7c270fa | 2010-12-08 17:31:42 -0800 | [diff] [blame] | 418 | } |
| 419 | |
| 420 | public void onAnimationRepeat(Animator animation) { |
| 421 | } |
| 422 | |
| 423 | public void onAnimationStart(Animator animation) { |
| 424 | } |
| 425 | } |
Chris Wren | 1e8f65d | 2012-06-06 18:08:56 -0400 | [diff] [blame] | 426 | |
| 427 | @Override |
| 428 | public boolean onInterceptTouchEvent(MotionEvent ev) { |
| 429 | MotionEvent cancellation = MotionEvent.obtain(ev); |
| 430 | cancellation.setAction(MotionEvent.ACTION_CANCEL); |
| 431 | |
| 432 | boolean intercept = mExpandHelper.onInterceptTouchEvent(ev) || |
| 433 | super.onInterceptTouchEvent(ev); |
| 434 | if (intercept) { |
| 435 | latestItems.onInterceptTouchEvent(cancellation); |
| 436 | } |
| 437 | return intercept; |
| 438 | } |
| 439 | |
| 440 | @Override |
| 441 | public boolean onTouchEvent(MotionEvent ev) { |
| 442 | boolean handled = mExpandHelper.onTouchEvent(ev) || |
| 443 | super.onTouchEvent(ev); |
| 444 | return handled; |
| 445 | } |
John Spurlock | 3623128 | 2012-06-23 17:11:27 -0400 | [diff] [blame] | 446 | |
| 447 | public void setSettingsEnabled(boolean settingsEnabled) { |
| 448 | if (mSettingsButton != null) { |
| 449 | mSettingsButton.setEnabled(settingsEnabled); |
| 450 | mSettingsButton.setVisibility(settingsEnabled ? View.VISIBLE : View.GONE); |
| 451 | } |
| 452 | } |
Fabrice Di Meglio | 8afcd14 | 2012-07-27 18:27:11 -0700 | [diff] [blame] | 453 | |
| 454 | public void refreshLayout(int layoutDirection) { |
| 455 | // Force asset reloading |
| 456 | mSettingsButton.setImageDrawable(null); |
| 457 | mSettingsButton.setImageResource(R.drawable.ic_notify_settings); |
| 458 | |
| 459 | // Force asset reloading |
| 460 | mNotificationButton.setImageDrawable(null); |
| 461 | mNotificationButton.setImageResource(R.drawable.ic_notifications); |
| 462 | } |
Joe Onorato | ddf680b | 2010-09-26 13:59:40 -0700 | [diff] [blame] | 463 | } |
| 464 | |