| 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 |