OLD | NEW |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.appmenu; | 5 package org.chromium.chrome.browser.appmenu; |
6 | 6 |
7 import android.animation.Animator; | 7 import android.animation.Animator; |
| 8 import android.animation.Animator.AnimatorListener; |
8 import android.animation.AnimatorSet; | 9 import android.animation.AnimatorSet; |
9 import android.content.Context; | 10 import android.content.Context; |
10 import android.content.res.Resources; | 11 import android.content.res.Resources; |
11 import android.graphics.Rect; | 12 import android.graphics.Rect; |
12 import android.graphics.drawable.Drawable; | 13 import android.graphics.drawable.Drawable; |
13 import android.os.Build; | 14 import android.os.Build; |
14 import android.view.KeyEvent; | 15 import android.view.KeyEvent; |
15 import android.view.LayoutInflater; | 16 import android.view.LayoutInflater; |
16 import android.view.Menu; | 17 import android.view.Menu; |
17 import android.view.MenuItem; | 18 import android.view.MenuItem; |
18 import android.view.Surface; | 19 import android.view.Surface; |
19 import android.view.View; | 20 import android.view.View; |
20 import android.view.View.OnKeyListener; | 21 import android.view.View.OnKeyListener; |
21 import android.view.ViewGroup; | 22 import android.view.ViewGroup; |
22 import android.widget.AdapterView; | 23 import android.widget.AdapterView; |
23 import android.widget.AdapterView.OnItemClickListener; | 24 import android.widget.AdapterView.OnItemClickListener; |
24 import android.widget.ImageButton; | 25 import android.widget.ImageButton; |
25 import android.widget.ListPopupWindow; | 26 import android.widget.ListPopupWindow; |
26 import android.widget.ListView; | 27 import android.widget.ListView; |
27 import android.widget.PopupWindow; | 28 import android.widget.PopupWindow; |
28 import android.widget.PopupWindow.OnDismissListener; | 29 import android.widget.PopupWindow.OnDismissListener; |
29 | 30 |
| 31 import org.chromium.base.AnimationFrameTimeHistogram; |
30 import org.chromium.base.SysUtils; | 32 import org.chromium.base.SysUtils; |
31 import org.chromium.chrome.R; | 33 import org.chromium.chrome.R; |
32 | 34 |
33 import java.util.ArrayList; | 35 import java.util.ArrayList; |
34 import java.util.List; | 36 import java.util.List; |
35 | 37 |
36 /** | 38 /** |
37 * Shows a popup of menuitems anchored to a host view. When a item is selected w
e call | 39 * Shows a popup of menuitems anchored to a host view. When a item is selected w
e call |
38 * Activity.onOptionsItemSelected with the appropriate MenuItem. | 40 * Activity.onOptionsItemSelected with the appropriate MenuItem. |
39 * - Only visible MenuItems are shown. | 41 * - Only visible MenuItems are shown. |
40 * - Disabled items are grayed out. | 42 * - Disabled items are grayed out. |
41 */ | 43 */ |
42 public class AppMenu implements OnItemClickListener, OnKeyListener { | 44 public class AppMenu implements OnItemClickListener, OnKeyListener { |
43 | 45 |
44 private static final float LAST_ITEM_SHOW_FRACTION = 0.5f; | 46 private static final float LAST_ITEM_SHOW_FRACTION = 0.5f; |
45 | 47 |
46 private final Menu mMenu; | 48 private final Menu mMenu; |
47 private final int mItemRowHeight; | 49 private final int mItemRowHeight; |
48 private final int mItemDividerHeight; | 50 private final int mItemDividerHeight; |
49 private final int mVerticalFadeDistance; | 51 private final int mVerticalFadeDistance; |
50 private final int mNegativeSoftwareVerticalOffset; | 52 private final int mNegativeSoftwareVerticalOffset; |
51 private ListPopupWindow mPopup; | 53 private ListPopupWindow mPopup; |
52 private AppMenuAdapter mAdapter; | 54 private AppMenuAdapter mAdapter; |
53 private AppMenuHandler mHandler; | 55 private AppMenuHandler mHandler; |
54 private int mCurrentScreenRotation = -1; | 56 private int mCurrentScreenRotation = -1; |
55 private boolean mIsByHardwareButton; | 57 private boolean mIsByHardwareButton; |
| 58 private AnimatorSet mMenuItemEnterAnimator; |
| 59 private AnimatorListener mAnimationHistogramRecorder = AnimationFrameTimeHis
togram |
| 60 .getAnimatorRecorder("WrenchMenu.OpeningAnimationFrameTimes"); |
56 | 61 |
57 /** | 62 /** |
58 * Creates and sets up the App Menu. | 63 * Creates and sets up the App Menu. |
59 * @param menu Original menu created by the framework. | 64 * @param menu Original menu created by the framework. |
60 * @param itemRowHeight Desired height for each app menu row. | 65 * @param itemRowHeight Desired height for each app menu row. |
61 * @param itemDividerHeight Desired height for the divider between app menu
items. | 66 * @param itemDividerHeight Desired height for the divider between app menu
items. |
62 * @param handler AppMenuHandler receives callbacks from AppMenu. | 67 * @param handler AppMenuHandler receives callbacks from AppMenu. |
63 * @param res Resources object used to get dimensions and style attributes. | 68 * @param res Resources object used to get dimensions and style attributes. |
64 */ | 69 */ |
65 AppMenu(Menu menu, int itemRowHeight, int itemDividerHeight, AppMenuHandler
handler, | 70 AppMenu(Menu menu, int itemRowHeight, int itemDividerHeight, AppMenuHandler
handler, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 mPopup = new ListPopupWindow(context, null, android.R.attr.popupMenuStyl
e); | 138 mPopup = new ListPopupWindow(context, null, android.R.attr.popupMenuStyl
e); |
134 mPopup.setModal(true); | 139 mPopup.setModal(true); |
135 mPopup.setAnchorView(anchorView); | 140 mPopup.setAnchorView(anchorView); |
136 mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); | 141 mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); |
137 mPopup.setOnDismissListener(new OnDismissListener() { | 142 mPopup.setOnDismissListener(new OnDismissListener() { |
138 @Override | 143 @Override |
139 public void onDismiss() { | 144 public void onDismiss() { |
140 if (mPopup.getAnchorView() instanceof ImageButton) { | 145 if (mPopup.getAnchorView() instanceof ImageButton) { |
141 ((ImageButton) mPopup.getAnchorView()).setSelected(false); | 146 ((ImageButton) mPopup.getAnchorView()).setSelected(false); |
142 } | 147 } |
| 148 |
| 149 if (mMenuItemEnterAnimator != null) mMenuItemEnterAnimator.cance
l(); |
| 150 |
| 151 mHandler.appMenuDismissed(); |
143 mHandler.onMenuVisibilityChanged(false); | 152 mHandler.onMenuVisibilityChanged(false); |
144 } | 153 } |
145 }); | 154 }); |
146 | 155 |
147 // Some OEMs don't actually let us change the background... but they sti
ll return the | 156 // Some OEMs don't actually let us change the background... but they sti
ll return the |
148 // padding of the new background, which breaks the menu height. If we s
till have a | 157 // padding of the new background, which breaks the menu height. If we s
till have a |
149 // drawable here even though our style says @null we should use this pad
ding instead... | 158 // drawable here even though our style says @null we should use this pad
ding instead... |
150 Drawable originalBgDrawable = mPopup.getBackground(); | 159 Drawable originalBgDrawable = mPopup.getBackground(); |
151 | 160 |
152 // Need to explicitly set the background here. Relying on it being set
in the style caused | 161 // Need to explicitly set the background here. Relying on it being set
in the style caused |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 } | 301 } |
293 } | 302 } |
294 } | 303 } |
295 return false; | 304 return false; |
296 } | 305 } |
297 | 306 |
298 /** | 307 /** |
299 * Dismisses the app menu and cancels the drag-to-scroll if it is taking pla
ce. | 308 * Dismisses the app menu and cancels the drag-to-scroll if it is taking pla
ce. |
300 */ | 309 */ |
301 void dismiss() { | 310 void dismiss() { |
302 mHandler.appMenuDismissed(); | |
303 if (isShowing()) { | 311 if (isShowing()) { |
304 mPopup.dismiss(); | 312 mPopup.dismiss(); |
305 } | 313 } |
306 } | 314 } |
307 | 315 |
308 /** | 316 /** |
309 * @return Whether the app menu is currently showing. | 317 * @return Whether the app menu is currently showing. |
310 */ | 318 */ |
311 boolean isShowing() { | 319 boolean isShowing() { |
312 if (mPopup == null) { | 320 if (mPopup == null) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 } else { | 362 } else { |
355 mPopup.setHeight(spaceForFullItems - mItemRowHeight + spaceForPa
rtialItem | 363 mPopup.setHeight(spaceForFullItems - mItemRowHeight + spaceForPa
rtialItem |
356 + padding.top + padding.bottom); | 364 + padding.top + padding.bottom); |
357 } | 365 } |
358 } else { | 366 } else { |
359 mPopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); | 367 mPopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); |
360 } | 368 } |
361 } | 369 } |
362 | 370 |
363 private void runMenuItemEnterAnimations() { | 371 private void runMenuItemEnterAnimations() { |
364 AnimatorSet animation = new AnimatorSet(); | 372 mMenuItemEnterAnimator = new AnimatorSet(); |
365 AnimatorSet.Builder builder = null; | 373 AnimatorSet.Builder builder = null; |
366 | 374 |
367 ViewGroup list = mPopup.getListView(); | 375 ViewGroup list = mPopup.getListView(); |
368 for (int i = 0; i < list.getChildCount(); i++) { | 376 for (int i = 0; i < list.getChildCount(); i++) { |
369 View view = list.getChildAt(i); | 377 View view = list.getChildAt(i); |
370 Object animatorObject = view.getTag(R.id.menu_item_enter_anim_id); | 378 Object animatorObject = view.getTag(R.id.menu_item_enter_anim_id); |
371 if (animatorObject != null) { | 379 if (animatorObject != null) { |
372 if (builder == null) { | 380 if (builder == null) { |
373 builder = animation.play((Animator) animatorObject); | 381 builder = mMenuItemEnterAnimator.play((Animator) animatorObj
ect); |
374 } else { | 382 } else { |
375 builder.with((Animator) animatorObject); | 383 builder.with((Animator) animatorObject); |
376 } | 384 } |
377 } | 385 } |
378 } | 386 } |
379 | 387 |
380 animation.start(); | 388 mMenuItemEnterAnimator.addListener(mAnimationHistogramRecorder); |
| 389 mMenuItemEnterAnimator.start(); |
381 } | 390 } |
382 } | 391 } |
OLD | NEW |